Merge "Add name hash to chrome user action proto."
diff --git a/.gitignore b/.gitignore
index 655f094..f24c442 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,5 +1,6 @@
.android_config
.ccls-cache
+.clangd
.cproject
.deps_sha1
.DS_Store
diff --git a/Android.bp b/Android.bp
index 5ed362b..c1ca304 100644
--- a/Android.bp
+++ b/Android.bp
@@ -21,6 +21,7 @@
"src/trace_processor/metrics/android/android_batt.sql",
"src/trace_processor/metrics/android/android_cpu.sql",
"src/trace_processor/metrics/android/android_cpu_agg.sql",
+ "src/trace_processor/metrics/android/android_hwui_metric.sql",
"src/trace_processor/metrics/android/android_ion.sql",
"src/trace_processor/metrics/android/android_lmk.sql",
"src/trace_processor/metrics/android/android_lmk_reason.sql",
@@ -107,7 +108,8 @@
":perfetto_protos_perfetto_trace_track_event_zero_gen",
":perfetto_src_base_base",
":perfetto_src_base_unix_socket",
- ":perfetto_src_ipc_ipc",
+ ":perfetto_src_ipc_client",
+ ":perfetto_src_ipc_common",
":perfetto_src_profiling_memory_daemon",
":perfetto_src_profiling_memory_proc_utils",
":perfetto_src_profiling_memory_ring_buffer",
@@ -115,8 +117,9 @@
":perfetto_src_profiling_memory_wire_protocol",
":perfetto_src_protozero_protozero",
":perfetto_src_tracing_common",
- ":perfetto_src_tracing_ipc",
- ":perfetto_src_tracing_tracing",
+ ":perfetto_src_tracing_core_core",
+ ":perfetto_src_tracing_ipc_common",
+ ":perfetto_src_tracing_ipc_producer_producer",
"src/profiling/memory/main.cc",
],
shared_libs: [
@@ -296,7 +299,9 @@
":perfetto_src_android_internal_lazy_library_loader",
":perfetto_src_base_base",
":perfetto_src_base_unix_socket",
- ":perfetto_src_ipc_ipc",
+ ":perfetto_src_ipc_client",
+ ":perfetto_src_ipc_common",
+ ":perfetto_src_ipc_host",
":perfetto_src_perfetto_cmd_perfetto_atoms",
":perfetto_src_protozero_protozero",
":perfetto_src_traced_probes_android_log_android_log",
@@ -313,9 +318,13 @@
":perfetto_src_traced_probes_sys_stats_sys_stats",
":perfetto_src_traced_service_service",
":perfetto_src_tracing_common",
- ":perfetto_src_tracing_consumer_api_deprecated",
- ":perfetto_src_tracing_ipc",
- ":perfetto_src_tracing_tracing",
+ ":perfetto_src_tracing_consumer_api_deprecated_consumer_api_deprecated",
+ ":perfetto_src_tracing_core_core",
+ ":perfetto_src_tracing_core_service",
+ ":perfetto_src_tracing_ipc_common",
+ ":perfetto_src_tracing_ipc_consumer_consumer",
+ ":perfetto_src_tracing_ipc_producer_producer",
+ ":perfetto_src_tracing_ipc_service_service",
],
shared_libs: [
"liblog",
@@ -465,13 +474,22 @@
":perfetto_protos_perfetto_trace_track_event_zero_gen",
":perfetto_src_base_base",
":perfetto_src_base_unix_socket",
- ":perfetto_src_ipc_ipc",
+ ":perfetto_src_ipc_client",
+ ":perfetto_src_ipc_common",
+ ":perfetto_src_ipc_host",
":perfetto_src_protozero_protozero",
- ":perfetto_src_tracing_client_api",
+ ":perfetto_src_tracing_client_api_base",
+ ":perfetto_src_tracing_client_api_system_backend_only",
":perfetto_src_tracing_common",
- ":perfetto_src_tracing_ipc",
+ ":perfetto_src_tracing_core_core",
+ ":perfetto_src_tracing_core_service",
+ ":perfetto_src_tracing_in_process_backend_fake",
+ ":perfetto_src_tracing_ipc_common",
+ ":perfetto_src_tracing_ipc_consumer_consumer",
+ ":perfetto_src_tracing_ipc_producer_producer",
+ ":perfetto_src_tracing_ipc_service_service",
":perfetto_src_tracing_platform_posix",
- ":perfetto_src_tracing_tracing",
+ ":perfetto_src_tracing_system_process_backend",
],
export_include_dirs: [
"include",
@@ -619,15 +637,18 @@
":perfetto_src_android_internal_lazy_library_loader",
":perfetto_src_base_base",
":perfetto_src_base_unix_socket",
- ":perfetto_src_ipc_ipc",
+ ":perfetto_src_ipc_client",
+ ":perfetto_src_ipc_common",
":perfetto_src_perfetto_cmd_perfetto_atoms",
":perfetto_src_perfetto_cmd_perfetto_cmd",
":perfetto_src_perfetto_cmd_protos_gen",
":perfetto_src_perfetto_cmd_trigger_producer",
":perfetto_src_protozero_protozero",
":perfetto_src_tracing_common",
- ":perfetto_src_tracing_ipc",
- ":perfetto_src_tracing_tracing",
+ ":perfetto_src_tracing_core_core",
+ ":perfetto_src_tracing_ipc_common",
+ ":perfetto_src_tracing_ipc_consumer_consumer",
+ ":perfetto_src_tracing_ipc_producer_producer",
"src/perfetto_cmd/main.cc",
],
shared_libs: [
@@ -755,7 +776,9 @@
":perfetto_src_base_base",
":perfetto_src_base_test_support",
":perfetto_src_base_unix_socket",
- ":perfetto_src_ipc_ipc",
+ ":perfetto_src_ipc_client",
+ ":perfetto_src_ipc_common",
+ ":perfetto_src_ipc_host",
":perfetto_src_perfetto_cmd_perfetto_atoms",
":perfetto_src_protozero_protozero",
":perfetto_src_traced_probes_android_log_android_log",
@@ -770,10 +793,13 @@
":perfetto_src_traced_probes_ps_ps",
":perfetto_src_traced_probes_sys_stats_sys_stats",
":perfetto_src_tracing_common",
- ":perfetto_src_tracing_ipc",
- ":perfetto_src_tracing_tracing",
- ":perfetto_test_task_runner_thread",
- ":perfetto_test_task_runner_thread_delegates",
+ ":perfetto_src_tracing_core_core",
+ ":perfetto_src_tracing_core_service",
+ ":perfetto_src_tracing_ipc_common",
+ ":perfetto_src_tracing_ipc_consumer_consumer",
+ ":perfetto_src_tracing_ipc_producer_producer",
+ ":perfetto_src_tracing_ipc_service_service",
+ ":perfetto_test_end_to_end_integrationtests",
":perfetto_test_test_helper",
"test/cts/device_feature_test_cts.cc",
"test/cts/end_to_end_integrationtest_cts.cc",
@@ -905,6 +931,221 @@
],
}
+// GN: //test/cts:perfetto_cts_jni_deps
+cc_library_static {
+ name: "perfetto_cts_jni_deps",
+ srcs: [
+ ":perfetto_include_perfetto_base_base",
+ ":perfetto_include_perfetto_ext_base_base",
+ ":perfetto_include_perfetto_ext_ipc_ipc",
+ ":perfetto_include_perfetto_ext_traced_sys_stats_counters",
+ ":perfetto_include_perfetto_ext_traced_traced",
+ ":perfetto_include_perfetto_ext_tracing_core_core",
+ ":perfetto_include_perfetto_ext_tracing_ipc_ipc",
+ ":perfetto_include_perfetto_protozero_protozero",
+ ":perfetto_include_perfetto_tracing_core_core",
+ ":perfetto_include_perfetto_tracing_core_forward_decls",
+ ":perfetto_include_perfetto_tracing_tracing",
+ ":perfetto_protos_perfetto_common_cpp_gen",
+ ":perfetto_protos_perfetto_common_zero_gen",
+ ":perfetto_protos_perfetto_config_android_cpp_gen",
+ ":perfetto_protos_perfetto_config_android_zero_gen",
+ ":perfetto_protos_perfetto_config_cpp_gen",
+ ":perfetto_protos_perfetto_config_ftrace_cpp_gen",
+ ":perfetto_protos_perfetto_config_ftrace_zero_gen",
+ ":perfetto_protos_perfetto_config_gpu_cpp_gen",
+ ":perfetto_protos_perfetto_config_gpu_zero_gen",
+ ":perfetto_protos_perfetto_config_inode_file_cpp_gen",
+ ":perfetto_protos_perfetto_config_inode_file_zero_gen",
+ ":perfetto_protos_perfetto_config_power_cpp_gen",
+ ":perfetto_protos_perfetto_config_power_zero_gen",
+ ":perfetto_protos_perfetto_config_process_stats_cpp_gen",
+ ":perfetto_protos_perfetto_config_process_stats_zero_gen",
+ ":perfetto_protos_perfetto_config_profiling_cpp_gen",
+ ":perfetto_protos_perfetto_config_profiling_zero_gen",
+ ":perfetto_protos_perfetto_config_sys_stats_cpp_gen",
+ ":perfetto_protos_perfetto_config_sys_stats_zero_gen",
+ ":perfetto_protos_perfetto_config_zero_gen",
+ ":perfetto_protos_perfetto_ipc_cpp_gen",
+ ":perfetto_protos_perfetto_ipc_ipc_gen",
+ ":perfetto_protos_perfetto_ipc_wire_protocol_cpp_gen",
+ ":perfetto_protos_perfetto_trace_android_cpp_gen",
+ ":perfetto_protos_perfetto_trace_android_zero_gen",
+ ":perfetto_protos_perfetto_trace_chrome_cpp_gen",
+ ":perfetto_protos_perfetto_trace_chrome_zero_gen",
+ ":perfetto_protos_perfetto_trace_filesystem_cpp_gen",
+ ":perfetto_protos_perfetto_trace_filesystem_zero_gen",
+ ":perfetto_protos_perfetto_trace_ftrace_cpp_gen",
+ ":perfetto_protos_perfetto_trace_ftrace_zero_gen",
+ ":perfetto_protos_perfetto_trace_gpu_cpp_gen",
+ ":perfetto_protos_perfetto_trace_gpu_zero_gen",
+ ":perfetto_protos_perfetto_trace_interned_data_cpp_gen",
+ ":perfetto_protos_perfetto_trace_interned_data_zero_gen",
+ ":perfetto_protos_perfetto_trace_minimal_cpp_gen",
+ ":perfetto_protos_perfetto_trace_minimal_zero_gen",
+ ":perfetto_protos_perfetto_trace_non_minimal_cpp_gen",
+ ":perfetto_protos_perfetto_trace_non_minimal_zero_gen",
+ ":perfetto_protos_perfetto_trace_perfetto_cpp_gen",
+ ":perfetto_protos_perfetto_trace_perfetto_zero_gen",
+ ":perfetto_protos_perfetto_trace_power_cpp_gen",
+ ":perfetto_protos_perfetto_trace_power_zero_gen",
+ ":perfetto_protos_perfetto_trace_profiling_cpp_gen",
+ ":perfetto_protos_perfetto_trace_profiling_zero_gen",
+ ":perfetto_protos_perfetto_trace_ps_cpp_gen",
+ ":perfetto_protos_perfetto_trace_ps_zero_gen",
+ ":perfetto_protos_perfetto_trace_sys_stats_cpp_gen",
+ ":perfetto_protos_perfetto_trace_sys_stats_zero_gen",
+ ":perfetto_protos_perfetto_trace_track_event_cpp_gen",
+ ":perfetto_protos_perfetto_trace_track_event_zero_gen",
+ ":perfetto_src_android_internal_headers",
+ ":perfetto_src_android_internal_lazy_library_loader",
+ ":perfetto_src_base_base",
+ ":perfetto_src_base_test_support",
+ ":perfetto_src_base_unix_socket",
+ ":perfetto_src_ipc_client",
+ ":perfetto_src_ipc_common",
+ ":perfetto_src_ipc_host",
+ ":perfetto_src_perfetto_cmd_perfetto_atoms",
+ ":perfetto_src_protozero_protozero",
+ ":perfetto_src_traced_probes_android_log_android_log",
+ ":perfetto_src_traced_probes_data_source",
+ ":perfetto_src_traced_probes_filesystem_filesystem",
+ ":perfetto_src_traced_probes_ftrace_format_parser",
+ ":perfetto_src_traced_probes_ftrace_ftrace",
+ ":perfetto_src_traced_probes_metatrace_metatrace",
+ ":perfetto_src_traced_probes_packages_list_packages_list",
+ ":perfetto_src_traced_probes_power_power",
+ ":perfetto_src_traced_probes_probes_src",
+ ":perfetto_src_traced_probes_ps_ps",
+ ":perfetto_src_traced_probes_sys_stats_sys_stats",
+ ":perfetto_src_tracing_common",
+ ":perfetto_src_tracing_core_core",
+ ":perfetto_src_tracing_core_service",
+ ":perfetto_src_tracing_ipc_common",
+ ":perfetto_src_tracing_ipc_consumer_consumer",
+ ":perfetto_src_tracing_ipc_producer_producer",
+ ":perfetto_src_tracing_ipc_service_service",
+ ":perfetto_test_test_helper",
+ ],
+ export_include_dirs: [
+ "include",
+ "include/perfetto/base/build_configs/android_tree",
+ ],
+ generated_headers: [
+ "perfetto_protos_perfetto_common_cpp_gen_headers",
+ "perfetto_protos_perfetto_common_zero_gen_headers",
+ "perfetto_protos_perfetto_config_android_cpp_gen_headers",
+ "perfetto_protos_perfetto_config_android_zero_gen_headers",
+ "perfetto_protos_perfetto_config_cpp_gen_headers",
+ "perfetto_protos_perfetto_config_ftrace_cpp_gen_headers",
+ "perfetto_protos_perfetto_config_ftrace_zero_gen_headers",
+ "perfetto_protos_perfetto_config_gpu_cpp_gen_headers",
+ "perfetto_protos_perfetto_config_gpu_zero_gen_headers",
+ "perfetto_protos_perfetto_config_inode_file_cpp_gen_headers",
+ "perfetto_protos_perfetto_config_inode_file_zero_gen_headers",
+ "perfetto_protos_perfetto_config_power_cpp_gen_headers",
+ "perfetto_protos_perfetto_config_power_zero_gen_headers",
+ "perfetto_protos_perfetto_config_process_stats_cpp_gen_headers",
+ "perfetto_protos_perfetto_config_process_stats_zero_gen_headers",
+ "perfetto_protos_perfetto_config_profiling_cpp_gen_headers",
+ "perfetto_protos_perfetto_config_profiling_zero_gen_headers",
+ "perfetto_protos_perfetto_config_sys_stats_cpp_gen_headers",
+ "perfetto_protos_perfetto_config_sys_stats_zero_gen_headers",
+ "perfetto_protos_perfetto_config_zero_gen_headers",
+ "perfetto_protos_perfetto_ipc_cpp_gen_headers",
+ "perfetto_protos_perfetto_ipc_ipc_gen_headers",
+ "perfetto_protos_perfetto_ipc_wire_protocol_cpp_gen_headers",
+ "perfetto_protos_perfetto_trace_android_cpp_gen_headers",
+ "perfetto_protos_perfetto_trace_android_zero_gen_headers",
+ "perfetto_protos_perfetto_trace_chrome_cpp_gen_headers",
+ "perfetto_protos_perfetto_trace_chrome_zero_gen_headers",
+ "perfetto_protos_perfetto_trace_filesystem_cpp_gen_headers",
+ "perfetto_protos_perfetto_trace_filesystem_zero_gen_headers",
+ "perfetto_protos_perfetto_trace_ftrace_cpp_gen_headers",
+ "perfetto_protos_perfetto_trace_ftrace_zero_gen_headers",
+ "perfetto_protos_perfetto_trace_gpu_cpp_gen_headers",
+ "perfetto_protos_perfetto_trace_gpu_zero_gen_headers",
+ "perfetto_protos_perfetto_trace_interned_data_cpp_gen_headers",
+ "perfetto_protos_perfetto_trace_interned_data_zero_gen_headers",
+ "perfetto_protos_perfetto_trace_minimal_cpp_gen_headers",
+ "perfetto_protos_perfetto_trace_minimal_zero_gen_headers",
+ "perfetto_protos_perfetto_trace_non_minimal_cpp_gen_headers",
+ "perfetto_protos_perfetto_trace_non_minimal_zero_gen_headers",
+ "perfetto_protos_perfetto_trace_perfetto_cpp_gen_headers",
+ "perfetto_protos_perfetto_trace_perfetto_zero_gen_headers",
+ "perfetto_protos_perfetto_trace_power_cpp_gen_headers",
+ "perfetto_protos_perfetto_trace_power_zero_gen_headers",
+ "perfetto_protos_perfetto_trace_profiling_cpp_gen_headers",
+ "perfetto_protos_perfetto_trace_profiling_zero_gen_headers",
+ "perfetto_protos_perfetto_trace_ps_cpp_gen_headers",
+ "perfetto_protos_perfetto_trace_ps_zero_gen_headers",
+ "perfetto_protos_perfetto_trace_sys_stats_cpp_gen_headers",
+ "perfetto_protos_perfetto_trace_sys_stats_zero_gen_headers",
+ "perfetto_protos_perfetto_trace_track_event_cpp_gen_headers",
+ "perfetto_protos_perfetto_trace_track_event_zero_gen_headers",
+ ],
+ export_generated_headers: [
+ "perfetto_protos_perfetto_common_cpp_gen_headers",
+ "perfetto_protos_perfetto_common_zero_gen_headers",
+ "perfetto_protos_perfetto_config_android_cpp_gen_headers",
+ "perfetto_protos_perfetto_config_android_zero_gen_headers",
+ "perfetto_protos_perfetto_config_cpp_gen_headers",
+ "perfetto_protos_perfetto_config_ftrace_cpp_gen_headers",
+ "perfetto_protos_perfetto_config_ftrace_zero_gen_headers",
+ "perfetto_protos_perfetto_config_gpu_cpp_gen_headers",
+ "perfetto_protos_perfetto_config_gpu_zero_gen_headers",
+ "perfetto_protos_perfetto_config_inode_file_cpp_gen_headers",
+ "perfetto_protos_perfetto_config_inode_file_zero_gen_headers",
+ "perfetto_protos_perfetto_config_power_cpp_gen_headers",
+ "perfetto_protos_perfetto_config_power_zero_gen_headers",
+ "perfetto_protos_perfetto_config_process_stats_cpp_gen_headers",
+ "perfetto_protos_perfetto_config_process_stats_zero_gen_headers",
+ "perfetto_protos_perfetto_config_profiling_cpp_gen_headers",
+ "perfetto_protos_perfetto_config_profiling_zero_gen_headers",
+ "perfetto_protos_perfetto_config_sys_stats_cpp_gen_headers",
+ "perfetto_protos_perfetto_config_sys_stats_zero_gen_headers",
+ "perfetto_protos_perfetto_config_zero_gen_headers",
+ "perfetto_protos_perfetto_ipc_cpp_gen_headers",
+ "perfetto_protos_perfetto_ipc_ipc_gen_headers",
+ "perfetto_protos_perfetto_ipc_wire_protocol_cpp_gen_headers",
+ "perfetto_protos_perfetto_trace_android_cpp_gen_headers",
+ "perfetto_protos_perfetto_trace_android_zero_gen_headers",
+ "perfetto_protos_perfetto_trace_chrome_cpp_gen_headers",
+ "perfetto_protos_perfetto_trace_chrome_zero_gen_headers",
+ "perfetto_protos_perfetto_trace_filesystem_cpp_gen_headers",
+ "perfetto_protos_perfetto_trace_filesystem_zero_gen_headers",
+ "perfetto_protos_perfetto_trace_ftrace_cpp_gen_headers",
+ "perfetto_protos_perfetto_trace_ftrace_zero_gen_headers",
+ "perfetto_protos_perfetto_trace_gpu_cpp_gen_headers",
+ "perfetto_protos_perfetto_trace_gpu_zero_gen_headers",
+ "perfetto_protos_perfetto_trace_interned_data_cpp_gen_headers",
+ "perfetto_protos_perfetto_trace_interned_data_zero_gen_headers",
+ "perfetto_protos_perfetto_trace_minimal_cpp_gen_headers",
+ "perfetto_protos_perfetto_trace_minimal_zero_gen_headers",
+ "perfetto_protos_perfetto_trace_non_minimal_cpp_gen_headers",
+ "perfetto_protos_perfetto_trace_non_minimal_zero_gen_headers",
+ "perfetto_protos_perfetto_trace_perfetto_cpp_gen_headers",
+ "perfetto_protos_perfetto_trace_perfetto_zero_gen_headers",
+ "perfetto_protos_perfetto_trace_power_cpp_gen_headers",
+ "perfetto_protos_perfetto_trace_power_zero_gen_headers",
+ "perfetto_protos_perfetto_trace_profiling_cpp_gen_headers",
+ "perfetto_protos_perfetto_trace_profiling_zero_gen_headers",
+ "perfetto_protos_perfetto_trace_ps_cpp_gen_headers",
+ "perfetto_protos_perfetto_trace_ps_zero_gen_headers",
+ "perfetto_protos_perfetto_trace_sys_stats_cpp_gen_headers",
+ "perfetto_protos_perfetto_trace_sys_stats_zero_gen_headers",
+ "perfetto_protos_perfetto_trace_track_event_cpp_gen_headers",
+ "perfetto_protos_perfetto_trace_track_event_zero_gen_headers",
+ ],
+ defaults: [
+ "perfetto_defaults",
+ ],
+ cflags: [
+ "-DGOOGLE_PROTOBUF_NO_RTTI",
+ "-DGOOGLE_PROTOBUF_NO_STATIC_INITIALIZER",
+ ],
+}
+
// GN: //gn:default_deps
cc_defaults {
name: "perfetto_defaults",
@@ -1097,7 +1338,9 @@
":perfetto_src_base_base",
":perfetto_src_base_test_support",
":perfetto_src_base_unix_socket",
- ":perfetto_src_ipc_ipc",
+ ":perfetto_src_ipc_client",
+ ":perfetto_src_ipc_common",
+ ":perfetto_src_ipc_host",
":perfetto_src_perfetto_cmd_perfetto_atoms",
":perfetto_src_profiling_memory_client",
":perfetto_src_profiling_memory_daemon",
@@ -1120,16 +1363,20 @@
":perfetto_src_traced_probes_probes_src",
":perfetto_src_traced_probes_ps_ps",
":perfetto_src_traced_probes_sys_stats_sys_stats",
- ":perfetto_src_tracing_client_api",
- ":perfetto_src_tracing_client_api_integrationtests",
+ ":perfetto_src_tracing_client_api_base",
":perfetto_src_tracing_common",
- ":perfetto_src_tracing_ipc",
+ ":perfetto_src_tracing_core_core",
+ ":perfetto_src_tracing_core_service",
+ ":perfetto_src_tracing_in_process_backend",
+ ":perfetto_src_tracing_ipc_common",
+ ":perfetto_src_tracing_ipc_consumer_consumer",
+ ":perfetto_src_tracing_ipc_producer_producer",
+ ":perfetto_src_tracing_ipc_service_service",
":perfetto_src_tracing_platform_posix",
+ ":perfetto_src_tracing_system_process_backend",
":perfetto_src_tracing_test_api_test_support",
- ":perfetto_src_tracing_tracing",
+ ":perfetto_src_tracing_test_client_api_integrationtests",
":perfetto_test_end_to_end_integrationtests",
- ":perfetto_test_task_runner_thread",
- ":perfetto_test_task_runner_thread_delegates",
":perfetto_test_test_helper",
],
shared_libs: [
@@ -1295,7 +1542,7 @@
tools: [
"aprotoc",
],
- cmd: "mkdir -p $(genDir)/external/perfetto/ && $(location aprotoc) --proto_path=external/perfetto --cpp_out=$(genDir)/external/perfetto/ $(in)",
+ cmd: "mkdir -p $(genDir)/external/perfetto/ && $(location aprotoc) --proto_path=external/perfetto --cpp_out=lite=true:$(genDir)/external/perfetto/ $(in)",
out: [
"external/perfetto/protos/perfetto/common/android_log_constants.pb.cc",
"external/perfetto/protos/perfetto/common/commit_data_request.pb.cc",
@@ -1328,7 +1575,7 @@
tools: [
"aprotoc",
],
- cmd: "mkdir -p $(genDir)/external/perfetto/ && $(location aprotoc) --proto_path=external/perfetto --cpp_out=$(genDir)/external/perfetto/ $(in)",
+ cmd: "mkdir -p $(genDir)/external/perfetto/ && $(location aprotoc) --proto_path=external/perfetto --cpp_out=lite=true:$(genDir)/external/perfetto/ $(in)",
out: [
"external/perfetto/protos/perfetto/common/android_log_constants.pb.h",
"external/perfetto/protos/perfetto/common/commit_data_request.pb.h",
@@ -1469,7 +1716,7 @@
tools: [
"aprotoc",
],
- cmd: "mkdir -p $(genDir)/external/perfetto/ && $(location aprotoc) --proto_path=external/perfetto --cpp_out=$(genDir)/external/perfetto/ $(in)",
+ cmd: "mkdir -p $(genDir)/external/perfetto/ && $(location aprotoc) --proto_path=external/perfetto --cpp_out=lite=true:$(genDir)/external/perfetto/ $(in)",
out: [
"external/perfetto/protos/perfetto/config/android/android_log_config.pb.cc",
"external/perfetto/protos/perfetto/config/android/packages_list_config.pb.cc",
@@ -1486,7 +1733,7 @@
tools: [
"aprotoc",
],
- cmd: "mkdir -p $(genDir)/external/perfetto/ && $(location aprotoc) --proto_path=external/perfetto --cpp_out=$(genDir)/external/perfetto/ $(in)",
+ cmd: "mkdir -p $(genDir)/external/perfetto/ && $(location aprotoc) --proto_path=external/perfetto --cpp_out=lite=true:$(genDir)/external/perfetto/ $(in)",
out: [
"external/perfetto/protos/perfetto/config/android/android_log_config.pb.h",
"external/perfetto/protos/perfetto/config/android/packages_list_config.pb.h",
@@ -1630,7 +1877,7 @@
tools: [
"aprotoc",
],
- cmd: "mkdir -p $(genDir)/external/perfetto/ && $(location aprotoc) --proto_path=external/perfetto --cpp_out=$(genDir)/external/perfetto/ $(in)",
+ cmd: "mkdir -p $(genDir)/external/perfetto/ && $(location aprotoc) --proto_path=external/perfetto --cpp_out=lite=true:$(genDir)/external/perfetto/ $(in)",
out: [
"external/perfetto/protos/perfetto/config/ftrace/ftrace_config.pb.cc",
],
@@ -1645,7 +1892,7 @@
tools: [
"aprotoc",
],
- cmd: "mkdir -p $(genDir)/external/perfetto/ && $(location aprotoc) --proto_path=external/perfetto --cpp_out=$(genDir)/external/perfetto/ $(in)",
+ cmd: "mkdir -p $(genDir)/external/perfetto/ && $(location aprotoc) --proto_path=external/perfetto --cpp_out=lite=true:$(genDir)/external/perfetto/ $(in)",
out: [
"external/perfetto/protos/perfetto/config/ftrace/ftrace_config.pb.h",
],
@@ -1741,7 +1988,7 @@
tools: [
"aprotoc",
],
- cmd: "mkdir -p $(genDir)/external/perfetto/ && $(location aprotoc) --proto_path=external/perfetto --cpp_out=$(genDir)/external/perfetto/ $(in)",
+ cmd: "mkdir -p $(genDir)/external/perfetto/ && $(location aprotoc) --proto_path=external/perfetto --cpp_out=lite=true:$(genDir)/external/perfetto/ $(in)",
out: [
"external/perfetto/protos/perfetto/config/gpu/gpu_counter_config.pb.cc",
"external/perfetto/protos/perfetto/config/gpu/vulkan_memory_config.pb.cc",
@@ -1758,7 +2005,7 @@
tools: [
"aprotoc",
],
- cmd: "mkdir -p $(genDir)/external/perfetto/ && $(location aprotoc) --proto_path=external/perfetto --cpp_out=$(genDir)/external/perfetto/ $(in)",
+ cmd: "mkdir -p $(genDir)/external/perfetto/ && $(location aprotoc) --proto_path=external/perfetto --cpp_out=lite=true:$(genDir)/external/perfetto/ $(in)",
out: [
"external/perfetto/protos/perfetto/config/gpu/gpu_counter_config.pb.h",
"external/perfetto/protos/perfetto/config/gpu/vulkan_memory_config.pb.h",
@@ -1854,7 +2101,7 @@
tools: [
"aprotoc",
],
- cmd: "mkdir -p $(genDir)/external/perfetto/ && $(location aprotoc) --proto_path=external/perfetto --cpp_out=$(genDir)/external/perfetto/ $(in)",
+ cmd: "mkdir -p $(genDir)/external/perfetto/ && $(location aprotoc) --proto_path=external/perfetto --cpp_out=lite=true:$(genDir)/external/perfetto/ $(in)",
out: [
"external/perfetto/protos/perfetto/config/inode_file/inode_file_config.pb.cc",
],
@@ -1869,7 +2116,7 @@
tools: [
"aprotoc",
],
- cmd: "mkdir -p $(genDir)/external/perfetto/ && $(location aprotoc) --proto_path=external/perfetto --cpp_out=$(genDir)/external/perfetto/ $(in)",
+ cmd: "mkdir -p $(genDir)/external/perfetto/ && $(location aprotoc) --proto_path=external/perfetto --cpp_out=lite=true:$(genDir)/external/perfetto/ $(in)",
out: [
"external/perfetto/protos/perfetto/config/inode_file/inode_file_config.pb.h",
],
@@ -1927,7 +2174,7 @@
tools: [
"aprotoc",
],
- cmd: "mkdir -p $(genDir)/external/perfetto/ && $(location aprotoc) --proto_path=external/perfetto --cpp_out=$(genDir)/external/perfetto/ $(in)",
+ cmd: "mkdir -p $(genDir)/external/perfetto/ && $(location aprotoc) --proto_path=external/perfetto --cpp_out=lite=true:$(genDir)/external/perfetto/ $(in)",
out: [
"external/perfetto/protos/perfetto/config/chrome/chrome_config.pb.cc",
"external/perfetto/protos/perfetto/config/data_source_config.pb.cc",
@@ -1948,7 +2195,7 @@
tools: [
"aprotoc",
],
- cmd: "mkdir -p $(genDir)/external/perfetto/ && $(location aprotoc) --proto_path=external/perfetto --cpp_out=$(genDir)/external/perfetto/ $(in)",
+ cmd: "mkdir -p $(genDir)/external/perfetto/ && $(location aprotoc) --proto_path=external/perfetto --cpp_out=lite=true:$(genDir)/external/perfetto/ $(in)",
out: [
"external/perfetto/protos/perfetto/config/chrome/chrome_config.pb.h",
"external/perfetto/protos/perfetto/config/data_source_config.pb.h",
@@ -2006,7 +2253,7 @@
tools: [
"aprotoc",
],
- cmd: "mkdir -p $(genDir)/external/perfetto/ && $(location aprotoc) --proto_path=external/perfetto --cpp_out=$(genDir)/external/perfetto/ $(in)",
+ cmd: "mkdir -p $(genDir)/external/perfetto/ && $(location aprotoc) --proto_path=external/perfetto --cpp_out=lite=true:$(genDir)/external/perfetto/ $(in)",
out: [
"external/perfetto/protos/perfetto/config/power/android_power_config.pb.cc",
],
@@ -2021,7 +2268,7 @@
tools: [
"aprotoc",
],
- cmd: "mkdir -p $(genDir)/external/perfetto/ && $(location aprotoc) --proto_path=external/perfetto --cpp_out=$(genDir)/external/perfetto/ $(in)",
+ cmd: "mkdir -p $(genDir)/external/perfetto/ && $(location aprotoc) --proto_path=external/perfetto --cpp_out=lite=true:$(genDir)/external/perfetto/ $(in)",
out: [
"external/perfetto/protos/perfetto/config/power/android_power_config.pb.h",
],
@@ -2112,7 +2359,7 @@
tools: [
"aprotoc",
],
- cmd: "mkdir -p $(genDir)/external/perfetto/ && $(location aprotoc) --proto_path=external/perfetto --cpp_out=$(genDir)/external/perfetto/ $(in)",
+ cmd: "mkdir -p $(genDir)/external/perfetto/ && $(location aprotoc) --proto_path=external/perfetto --cpp_out=lite=true:$(genDir)/external/perfetto/ $(in)",
out: [
"external/perfetto/protos/perfetto/config/process_stats/process_stats_config.pb.cc",
],
@@ -2127,7 +2374,7 @@
tools: [
"aprotoc",
],
- cmd: "mkdir -p $(genDir)/external/perfetto/ && $(location aprotoc) --proto_path=external/perfetto --cpp_out=$(genDir)/external/perfetto/ $(in)",
+ cmd: "mkdir -p $(genDir)/external/perfetto/ && $(location aprotoc) --proto_path=external/perfetto --cpp_out=lite=true:$(genDir)/external/perfetto/ $(in)",
out: [
"external/perfetto/protos/perfetto/config/process_stats/process_stats_config.pb.h",
],
@@ -2228,7 +2475,7 @@
tools: [
"aprotoc",
],
- cmd: "mkdir -p $(genDir)/external/perfetto/ && $(location aprotoc) --proto_path=external/perfetto --cpp_out=$(genDir)/external/perfetto/ $(in)",
+ cmd: "mkdir -p $(genDir)/external/perfetto/ && $(location aprotoc) --proto_path=external/perfetto --cpp_out=lite=true:$(genDir)/external/perfetto/ $(in)",
out: [
"external/perfetto/protos/perfetto/config/profiling/heapprofd_config.pb.cc",
"external/perfetto/protos/perfetto/config/profiling/java_hprof_config.pb.cc",
@@ -2247,7 +2494,7 @@
tools: [
"aprotoc",
],
- cmd: "mkdir -p $(genDir)/external/perfetto/ && $(location aprotoc) --proto_path=external/perfetto --cpp_out=$(genDir)/external/perfetto/ $(in)",
+ cmd: "mkdir -p $(genDir)/external/perfetto/ && $(location aprotoc) --proto_path=external/perfetto --cpp_out=lite=true:$(genDir)/external/perfetto/ $(in)",
out: [
"external/perfetto/protos/perfetto/config/profiling/heapprofd_config.pb.h",
"external/perfetto/protos/perfetto/config/profiling/java_hprof_config.pb.h",
@@ -2348,7 +2595,7 @@
tools: [
"aprotoc",
],
- cmd: "mkdir -p $(genDir)/external/perfetto/ && $(location aprotoc) --proto_path=external/perfetto --cpp_out=$(genDir)/external/perfetto/ $(in)",
+ cmd: "mkdir -p $(genDir)/external/perfetto/ && $(location aprotoc) --proto_path=external/perfetto --cpp_out=lite=true:$(genDir)/external/perfetto/ $(in)",
out: [
"external/perfetto/protos/perfetto/config/sys_stats/sys_stats_config.pb.cc",
],
@@ -2363,7 +2610,7 @@
tools: [
"aprotoc",
],
- cmd: "mkdir -p $(genDir)/external/perfetto/ && $(location aprotoc) --proto_path=external/perfetto --cpp_out=$(genDir)/external/perfetto/ $(in)",
+ cmd: "mkdir -p $(genDir)/external/perfetto/ && $(location aprotoc) --proto_path=external/perfetto --cpp_out=lite=true:$(genDir)/external/perfetto/ $(in)",
out: [
"external/perfetto/protos/perfetto/config/sys_stats/sys_stats_config.pb.h",
],
@@ -2580,6 +2827,7 @@
"protos/perfetto/metrics/android/batt_metric.proto",
"protos/perfetto/metrics/android/cpu_metric.proto",
"protos/perfetto/metrics/android/heap_profile_callsites.proto",
+ "protos/perfetto/metrics/android/hwui_metric.proto",
"protos/perfetto/metrics/android/ion_metric.proto",
"protos/perfetto/metrics/android/java_heap_stats.proto",
"protos/perfetto/metrics/android/lmk_metric.proto",
@@ -2602,6 +2850,7 @@
"external/perfetto/protos/perfetto/metrics/android/batt_metric.pbzero.cc",
"external/perfetto/protos/perfetto/metrics/android/cpu_metric.pbzero.cc",
"external/perfetto/protos/perfetto/metrics/android/heap_profile_callsites.pbzero.cc",
+ "external/perfetto/protos/perfetto/metrics/android/hwui_metric.pbzero.cc",
"external/perfetto/protos/perfetto/metrics/android/ion_metric.pbzero.cc",
"external/perfetto/protos/perfetto/metrics/android/java_heap_stats.pbzero.cc",
"external/perfetto/protos/perfetto/metrics/android/lmk_metric.pbzero.cc",
@@ -2624,6 +2873,7 @@
"protos/perfetto/metrics/android/batt_metric.proto",
"protos/perfetto/metrics/android/cpu_metric.proto",
"protos/perfetto/metrics/android/heap_profile_callsites.proto",
+ "protos/perfetto/metrics/android/hwui_metric.proto",
"protos/perfetto/metrics/android/ion_metric.proto",
"protos/perfetto/metrics/android/java_heap_stats.proto",
"protos/perfetto/metrics/android/lmk_metric.proto",
@@ -2646,6 +2896,7 @@
"external/perfetto/protos/perfetto/metrics/android/batt_metric.pbzero.h",
"external/perfetto/protos/perfetto/metrics/android/cpu_metric.pbzero.h",
"external/perfetto/protos/perfetto/metrics/android/heap_profile_callsites.pbzero.h",
+ "external/perfetto/protos/perfetto/metrics/android/hwui_metric.pbzero.h",
"external/perfetto/protos/perfetto/metrics/android/ion_metric.pbzero.h",
"external/perfetto/protos/perfetto/metrics/android/java_heap_stats.pbzero.h",
"external/perfetto/protos/perfetto/metrics/android/lmk_metric.pbzero.h",
@@ -2756,7 +3007,7 @@
tools: [
"aprotoc",
],
- cmd: "mkdir -p $(genDir)/external/perfetto/ && $(location aprotoc) --proto_path=external/perfetto --cpp_out=$(genDir)/external/perfetto/ $(in)",
+ cmd: "mkdir -p $(genDir)/external/perfetto/ && $(location aprotoc) --proto_path=external/perfetto --cpp_out=lite=true:$(genDir)/external/perfetto/ $(in)",
out: [
"external/perfetto/protos/perfetto/trace/android/android_log.pb.cc",
"external/perfetto/protos/perfetto/trace/android/graphics_frame_event.pb.cc",
@@ -2775,7 +3026,7 @@
tools: [
"aprotoc",
],
- cmd: "mkdir -p $(genDir)/external/perfetto/ && $(location aprotoc) --proto_path=external/perfetto --cpp_out=$(genDir)/external/perfetto/ $(in)",
+ cmd: "mkdir -p $(genDir)/external/perfetto/ && $(location aprotoc) --proto_path=external/perfetto --cpp_out=lite=true:$(genDir)/external/perfetto/ $(in)",
out: [
"external/perfetto/protos/perfetto/trace/android/android_log.pb.h",
"external/perfetto/protos/perfetto/trace/android/graphics_frame_event.pb.h",
@@ -2886,7 +3137,7 @@
tools: [
"aprotoc",
],
- cmd: "mkdir -p $(genDir)/external/perfetto/ && $(location aprotoc) --proto_path=external/perfetto --cpp_out=$(genDir)/external/perfetto/ $(in)",
+ cmd: "mkdir -p $(genDir)/external/perfetto/ && $(location aprotoc) --proto_path=external/perfetto --cpp_out=lite=true:$(genDir)/external/perfetto/ $(in)",
out: [
"external/perfetto/protos/perfetto/trace/chrome/chrome_benchmark_metadata.pb.cc",
"external/perfetto/protos/perfetto/trace/chrome/chrome_metadata.pb.cc",
@@ -2905,7 +3156,7 @@
tools: [
"aprotoc",
],
- cmd: "mkdir -p $(genDir)/external/perfetto/ && $(location aprotoc) --proto_path=external/perfetto --cpp_out=$(genDir)/external/perfetto/ $(in)",
+ cmd: "mkdir -p $(genDir)/external/perfetto/ && $(location aprotoc) --proto_path=external/perfetto --cpp_out=lite=true:$(genDir)/external/perfetto/ $(in)",
out: [
"external/perfetto/protos/perfetto/trace/chrome/chrome_benchmark_metadata.pb.h",
"external/perfetto/protos/perfetto/trace/chrome/chrome_metadata.pb.h",
@@ -3006,7 +3257,7 @@
tools: [
"aprotoc",
],
- cmd: "mkdir -p $(genDir)/external/perfetto/ && $(location aprotoc) --proto_path=external/perfetto --cpp_out=$(genDir)/external/perfetto/ $(in)",
+ cmd: "mkdir -p $(genDir)/external/perfetto/ && $(location aprotoc) --proto_path=external/perfetto --cpp_out=lite=true:$(genDir)/external/perfetto/ $(in)",
out: [
"external/perfetto/protos/perfetto/trace/filesystem/inode_file_map.pb.cc",
],
@@ -3021,7 +3272,7 @@
tools: [
"aprotoc",
],
- cmd: "mkdir -p $(genDir)/external/perfetto/ && $(location aprotoc) --proto_path=external/perfetto --cpp_out=$(genDir)/external/perfetto/ $(in)",
+ cmd: "mkdir -p $(genDir)/external/perfetto/ && $(location aprotoc) --proto_path=external/perfetto --cpp_out=lite=true:$(genDir)/external/perfetto/ $(in)",
out: [
"external/perfetto/protos/perfetto/trace/filesystem/inode_file_map.pb.h",
],
@@ -3277,7 +3528,7 @@
tools: [
"aprotoc",
],
- cmd: "mkdir -p $(genDir)/external/perfetto/ && $(location aprotoc) --proto_path=external/perfetto --cpp_out=$(genDir)/external/perfetto/ $(in)",
+ cmd: "mkdir -p $(genDir)/external/perfetto/ && $(location aprotoc) --proto_path=external/perfetto --cpp_out=lite=true:$(genDir)/external/perfetto/ $(in)",
out: [
"external/perfetto/protos/perfetto/trace/ftrace/binder.pb.cc",
"external/perfetto/protos/perfetto/trace/ftrace/block.pb.cc",
@@ -3358,7 +3609,7 @@
tools: [
"aprotoc",
],
- cmd: "mkdir -p $(genDir)/external/perfetto/ && $(location aprotoc) --proto_path=external/perfetto --cpp_out=$(genDir)/external/perfetto/ $(in)",
+ cmd: "mkdir -p $(genDir)/external/perfetto/ && $(location aprotoc) --proto_path=external/perfetto --cpp_out=lite=true:$(genDir)/external/perfetto/ $(in)",
out: [
"external/perfetto/protos/perfetto/trace/ftrace/binder.pb.h",
"external/perfetto/protos/perfetto/trace/ftrace/block.pb.h",
@@ -3634,7 +3885,7 @@
tools: [
"aprotoc",
],
- cmd: "mkdir -p $(genDir)/external/perfetto/ && $(location aprotoc) --proto_path=external/perfetto --cpp_out=$(genDir)/external/perfetto/ $(in)",
+ cmd: "mkdir -p $(genDir)/external/perfetto/ && $(location aprotoc) --proto_path=external/perfetto --cpp_out=lite=true:$(genDir)/external/perfetto/ $(in)",
out: [
"external/perfetto/protos/perfetto/trace/gpu/gpu_counter_event.pb.cc",
"external/perfetto/protos/perfetto/trace/gpu/gpu_log.pb.cc",
@@ -3657,7 +3908,7 @@
tools: [
"aprotoc",
],
- cmd: "mkdir -p $(genDir)/external/perfetto/ && $(location aprotoc) --proto_path=external/perfetto --cpp_out=$(genDir)/external/perfetto/ $(in)",
+ cmd: "mkdir -p $(genDir)/external/perfetto/ && $(location aprotoc) --proto_path=external/perfetto --cpp_out=lite=true:$(genDir)/external/perfetto/ $(in)",
out: [
"external/perfetto/protos/perfetto/trace/gpu/gpu_counter_event.pb.h",
"external/perfetto/protos/perfetto/trace/gpu/gpu_log.pb.h",
@@ -3768,7 +4019,7 @@
tools: [
"aprotoc",
],
- cmd: "mkdir -p $(genDir)/external/perfetto/ && $(location aprotoc) --proto_path=external/perfetto --cpp_out=$(genDir)/external/perfetto/ $(in)",
+ cmd: "mkdir -p $(genDir)/external/perfetto/ && $(location aprotoc) --proto_path=external/perfetto --cpp_out=lite=true:$(genDir)/external/perfetto/ $(in)",
out: [
"external/perfetto/protos/perfetto/trace/interned_data/interned_data.pb.cc",
],
@@ -3783,7 +4034,7 @@
tools: [
"aprotoc",
],
- cmd: "mkdir -p $(genDir)/external/perfetto/ && $(location aprotoc) --proto_path=external/perfetto --cpp_out=$(genDir)/external/perfetto/ $(in)",
+ cmd: "mkdir -p $(genDir)/external/perfetto/ && $(location aprotoc) --proto_path=external/perfetto --cpp_out=lite=true:$(genDir)/external/perfetto/ $(in)",
out: [
"external/perfetto/protos/perfetto/trace/interned_data/interned_data.pb.h",
],
@@ -3884,7 +4135,7 @@
tools: [
"aprotoc",
],
- cmd: "mkdir -p $(genDir)/external/perfetto/ && $(location aprotoc) --proto_path=external/perfetto --cpp_out=$(genDir)/external/perfetto/ $(in)",
+ cmd: "mkdir -p $(genDir)/external/perfetto/ && $(location aprotoc) --proto_path=external/perfetto --cpp_out=lite=true:$(genDir)/external/perfetto/ $(in)",
out: [
"external/perfetto/protos/perfetto/trace/clock_snapshot.pb.cc",
"external/perfetto/protos/perfetto/trace/system_info.pb.cc",
@@ -3903,7 +4154,7 @@
tools: [
"aprotoc",
],
- cmd: "mkdir -p $(genDir)/external/perfetto/ && $(location aprotoc) --proto_path=external/perfetto --cpp_out=$(genDir)/external/perfetto/ $(in)",
+ cmd: "mkdir -p $(genDir)/external/perfetto/ && $(location aprotoc) --proto_path=external/perfetto --cpp_out=lite=true:$(genDir)/external/perfetto/ $(in)",
out: [
"external/perfetto/protos/perfetto/trace/clock_snapshot.pb.h",
"external/perfetto/protos/perfetto/trace/system_info.pb.h",
@@ -4019,7 +4270,7 @@
tools: [
"aprotoc",
],
- cmd: "mkdir -p $(genDir)/external/perfetto/ && $(location aprotoc) --proto_path=external/perfetto --cpp_out=$(genDir)/external/perfetto/ $(in)",
+ cmd: "mkdir -p $(genDir)/external/perfetto/ && $(location aprotoc) --proto_path=external/perfetto --cpp_out=lite=true:$(genDir)/external/perfetto/ $(in)",
out: [
"external/perfetto/protos/perfetto/trace/test_event.pb.cc",
"external/perfetto/protos/perfetto/trace/trace.pb.cc",
@@ -4040,7 +4291,7 @@
tools: [
"aprotoc",
],
- cmd: "mkdir -p $(genDir)/external/perfetto/ && $(location aprotoc) --proto_path=external/perfetto --cpp_out=$(genDir)/external/perfetto/ $(in)",
+ cmd: "mkdir -p $(genDir)/external/perfetto/ && $(location aprotoc) --proto_path=external/perfetto --cpp_out=lite=true:$(genDir)/external/perfetto/ $(in)",
out: [
"external/perfetto/protos/perfetto/trace/test_event.pb.h",
"external/perfetto/protos/perfetto/trace/trace.pb.h",
@@ -4146,7 +4397,7 @@
tools: [
"aprotoc",
],
- cmd: "mkdir -p $(genDir)/external/perfetto/ && $(location aprotoc) --proto_path=external/perfetto --cpp_out=$(genDir)/external/perfetto/ $(in)",
+ cmd: "mkdir -p $(genDir)/external/perfetto/ && $(location aprotoc) --proto_path=external/perfetto --cpp_out=lite=true:$(genDir)/external/perfetto/ $(in)",
out: [
"external/perfetto/protos/perfetto/trace/perfetto/perfetto_metatrace.pb.cc",
],
@@ -4161,7 +4412,7 @@
tools: [
"aprotoc",
],
- cmd: "mkdir -p $(genDir)/external/perfetto/ && $(location aprotoc) --proto_path=external/perfetto --cpp_out=$(genDir)/external/perfetto/ $(in)",
+ cmd: "mkdir -p $(genDir)/external/perfetto/ && $(location aprotoc) --proto_path=external/perfetto --cpp_out=lite=true:$(genDir)/external/perfetto/ $(in)",
out: [
"external/perfetto/protos/perfetto/trace/perfetto/perfetto_metatrace.pb.h",
],
@@ -4257,7 +4508,7 @@
tools: [
"aprotoc",
],
- cmd: "mkdir -p $(genDir)/external/perfetto/ && $(location aprotoc) --proto_path=external/perfetto --cpp_out=$(genDir)/external/perfetto/ $(in)",
+ cmd: "mkdir -p $(genDir)/external/perfetto/ && $(location aprotoc) --proto_path=external/perfetto --cpp_out=lite=true:$(genDir)/external/perfetto/ $(in)",
out: [
"external/perfetto/protos/perfetto/trace/power/battery_counters.pb.cc",
"external/perfetto/protos/perfetto/trace/power/power_rails.pb.cc",
@@ -4274,7 +4525,7 @@
tools: [
"aprotoc",
],
- cmd: "mkdir -p $(genDir)/external/perfetto/ && $(location aprotoc) --proto_path=external/perfetto --cpp_out=$(genDir)/external/perfetto/ $(in)",
+ cmd: "mkdir -p $(genDir)/external/perfetto/ && $(location aprotoc) --proto_path=external/perfetto --cpp_out=lite=true:$(genDir)/external/perfetto/ $(in)",
out: [
"external/perfetto/protos/perfetto/trace/power/battery_counters.pb.h",
"external/perfetto/protos/perfetto/trace/power/power_rails.pb.h",
@@ -4416,7 +4667,7 @@
tools: [
"aprotoc",
],
- cmd: "mkdir -p $(genDir)/external/perfetto/ && $(location aprotoc) --proto_path=external/perfetto --cpp_out=$(genDir)/external/perfetto/ $(in)",
+ cmd: "mkdir -p $(genDir)/external/perfetto/ && $(location aprotoc) --proto_path=external/perfetto --cpp_out=lite=true:$(genDir)/external/perfetto/ $(in)",
out: [
"external/perfetto/protos/perfetto/trace/profiling/heap_graph.pb.cc",
"external/perfetto/protos/perfetto/trace/profiling/profile_common.pb.cc",
@@ -4435,7 +4686,7 @@
tools: [
"aprotoc",
],
- cmd: "mkdir -p $(genDir)/external/perfetto/ && $(location aprotoc) --proto_path=external/perfetto --cpp_out=$(genDir)/external/perfetto/ $(in)",
+ cmd: "mkdir -p $(genDir)/external/perfetto/ && $(location aprotoc) --proto_path=external/perfetto --cpp_out=lite=true:$(genDir)/external/perfetto/ $(in)",
out: [
"external/perfetto/protos/perfetto/trace/profiling/heap_graph.pb.h",
"external/perfetto/protos/perfetto/trace/profiling/profile_common.pb.h",
@@ -4541,7 +4792,7 @@
tools: [
"aprotoc",
],
- cmd: "mkdir -p $(genDir)/external/perfetto/ && $(location aprotoc) --proto_path=external/perfetto --cpp_out=$(genDir)/external/perfetto/ $(in)",
+ cmd: "mkdir -p $(genDir)/external/perfetto/ && $(location aprotoc) --proto_path=external/perfetto --cpp_out=lite=true:$(genDir)/external/perfetto/ $(in)",
out: [
"external/perfetto/protos/perfetto/trace/ps/process_stats.pb.cc",
"external/perfetto/protos/perfetto/trace/ps/process_tree.pb.cc",
@@ -4558,7 +4809,7 @@
tools: [
"aprotoc",
],
- cmd: "mkdir -p $(genDir)/external/perfetto/ && $(location aprotoc) --proto_path=external/perfetto --cpp_out=$(genDir)/external/perfetto/ $(in)",
+ cmd: "mkdir -p $(genDir)/external/perfetto/ && $(location aprotoc) --proto_path=external/perfetto --cpp_out=lite=true:$(genDir)/external/perfetto/ $(in)",
out: [
"external/perfetto/protos/perfetto/trace/ps/process_stats.pb.h",
"external/perfetto/protos/perfetto/trace/ps/process_tree.pb.h",
@@ -4654,7 +4905,7 @@
tools: [
"aprotoc",
],
- cmd: "mkdir -p $(genDir)/external/perfetto/ && $(location aprotoc) --proto_path=external/perfetto --cpp_out=$(genDir)/external/perfetto/ $(in)",
+ cmd: "mkdir -p $(genDir)/external/perfetto/ && $(location aprotoc) --proto_path=external/perfetto --cpp_out=lite=true:$(genDir)/external/perfetto/ $(in)",
out: [
"external/perfetto/protos/perfetto/trace/sys_stats/sys_stats.pb.cc",
],
@@ -4669,7 +4920,7 @@
tools: [
"aprotoc",
],
- cmd: "mkdir -p $(genDir)/external/perfetto/ && $(location aprotoc) --proto_path=external/perfetto --cpp_out=$(genDir)/external/perfetto/ $(in)",
+ cmd: "mkdir -p $(genDir)/external/perfetto/ && $(location aprotoc) --proto_path=external/perfetto --cpp_out=lite=true:$(genDir)/external/perfetto/ $(in)",
out: [
"external/perfetto/protos/perfetto/trace/sys_stats/sys_stats.pb.h",
],
@@ -4830,7 +5081,7 @@
tools: [
"aprotoc",
],
- cmd: "mkdir -p $(genDir)/external/perfetto/ && $(location aprotoc) --proto_path=external/perfetto --cpp_out=$(genDir)/external/perfetto/ $(in)",
+ cmd: "mkdir -p $(genDir)/external/perfetto/ && $(location aprotoc) --proto_path=external/perfetto --cpp_out=lite=true:$(genDir)/external/perfetto/ $(in)",
out: [
"external/perfetto/protos/perfetto/trace/track_event/chrome_compositor_scheduler_state.pb.cc",
"external/perfetto/protos/perfetto/trace/track_event/chrome_histogram_sample.pb.cc",
@@ -4873,7 +5124,7 @@
tools: [
"aprotoc",
],
- cmd: "mkdir -p $(genDir)/external/perfetto/ && $(location aprotoc) --proto_path=external/perfetto --cpp_out=$(genDir)/external/perfetto/ $(in)",
+ cmd: "mkdir -p $(genDir)/external/perfetto/ && $(location aprotoc) --proto_path=external/perfetto --cpp_out=lite=true:$(genDir)/external/perfetto/ $(in)",
out: [
"external/perfetto/protos/perfetto/trace/track_event/chrome_compositor_scheduler_state.pb.h",
"external/perfetto/protos/perfetto/trace/track_event/chrome_histogram_sample.pb.h",
@@ -5122,19 +5373,33 @@
],
}
-// GN: //src/ipc:ipc
+// GN: //src/ipc:client
filegroup {
- name: "perfetto_src_ipc_ipc",
+ name: "perfetto_src_ipc_client",
+ srcs: [
+ "src/ipc/client_impl.cc",
+ "src/ipc/service_proxy.cc",
+ ],
+}
+
+// GN: //src/ipc:common
+filegroup {
+ name: "perfetto_src_ipc_common",
srcs: [
"src/ipc/buffered_frame_deserializer.cc",
- "src/ipc/client_impl.cc",
"src/ipc/deferred.cc",
- "src/ipc/host_impl.cc",
- "src/ipc/service_proxy.cc",
"src/ipc/virtual_destructors.cc",
],
}
+// GN: //src/ipc:host
+filegroup {
+ name: "perfetto_src_ipc_host",
+ srcs: [
+ "src/ipc/host_impl.cc",
+ ],
+}
+
// GN: //src/ipc:test_messages_cpp
genrule {
name: "perfetto_src_ipc_test_messages_cpp_gen",
@@ -5576,7 +5841,7 @@
tools: [
"aprotoc",
],
- cmd: "mkdir -p $(genDir)/external/perfetto/ && $(location aprotoc) --proto_path=external/perfetto --cpp_out=$(genDir)/external/perfetto/ $(in)",
+ cmd: "mkdir -p $(genDir)/external/perfetto/ && $(location aprotoc) --proto_path=external/perfetto --cpp_out=lite=true:$(genDir)/external/perfetto/ $(in)",
out: [
"external/perfetto/src/protozero/test/example_proto/library.pb.cc",
"external/perfetto/src/protozero/test/example_proto/library_internals/galaxies.pb.cc",
@@ -5597,7 +5862,7 @@
tools: [
"aprotoc",
],
- cmd: "mkdir -p $(genDir)/external/perfetto/ && $(location aprotoc) --proto_path=external/perfetto --cpp_out=$(genDir)/external/perfetto/ $(in)",
+ cmd: "mkdir -p $(genDir)/external/perfetto/ && $(location aprotoc) --proto_path=external/perfetto --cpp_out=lite=true:$(genDir)/external/perfetto/ $(in)",
out: [
"external/perfetto/src/protozero/test/example_proto/library.pb.h",
"external/perfetto/src/protozero/test/example_proto/library_internals/galaxies.pb.h",
@@ -5726,21 +5991,18 @@
filegroup {
name: "perfetto_src_trace_processor_lib",
srcs: [
- "src/trace_processor/args_table.cc",
"src/trace_processor/filtered_row_index.cc",
- "src/trace_processor/gfp_flags.cc",
- "src/trace_processor/process_table.cc",
- "src/trace_processor/raw_table.cc",
"src/trace_processor/read_trace.cc",
"src/trace_processor/row_iterators.cc",
"src/trace_processor/sched_slice_table.cc",
"src/trace_processor/span_join_operator_table.cc",
"src/trace_processor/sql_stats_table.cc",
+ "src/trace_processor/sqlite_experimental_flamegraph_table.cc",
+ "src/trace_processor/sqlite_raw_table.cc",
"src/trace_processor/stats_table.cc",
"src/trace_processor/storage_columns.cc",
"src/trace_processor/storage_schema.cc",
"src/trace_processor/storage_table.cc",
- "src/trace_processor/thread_table.cc",
"src/trace_processor/trace_processor.cc",
"src/trace_processor/trace_processor_impl.cc",
"src/trace_processor/window_operator_table.cc",
@@ -5830,6 +6092,7 @@
"src/trace_processor/event_tracker.cc",
"src/trace_processor/forwarding_trace_parser.cc",
"src/trace_processor/ftrace_utils.cc",
+ "src/trace_processor/global_args_tracker.cc",
"src/trace_processor/gzip_trace_parser.cc",
"src/trace_processor/heap_profile_tracker.cc",
"src/trace_processor/importers/ftrace/ftrace_module.cc",
@@ -5872,11 +6135,19 @@
],
}
+// GN: //src/trace_processor/types:types
+filegroup {
+ name: "perfetto_src_trace_processor_types_types",
+ srcs: [
+ "src/trace_processor/types/gfp_flags.cc",
+ "src/trace_processor/types/variadic.cc",
+ ],
+}
+
// GN: //src/trace_processor:unittests
filegroup {
name: "perfetto_src_trace_processor_unittests",
srcs: [
- "src/trace_processor/args_table_unittest.cc",
"src/trace_processor/clock_tracker_unittest.cc",
"src/trace_processor/event_tracker_unittest.cc",
"src/trace_processor/filtered_row_index_unittest.cc",
@@ -5885,17 +6156,16 @@
"src/trace_processor/heap_profile_tracker_unittest.cc",
"src/trace_processor/importers/fuchsia/fuchsia_trace_utils_unittest.cc",
"src/trace_processor/importers/proto/args_table_utils_unittest.cc",
+ "src/trace_processor/importers/proto/heap_graph_tracker_unittest.cc",
"src/trace_processor/importers/proto/heap_graph_walker_unittest.cc",
"src/trace_processor/importers/proto/proto_trace_parser_unittest.cc",
"src/trace_processor/importers/systrace/systrace_parser_unittest.cc",
- "src/trace_processor/process_table_unittest.cc",
"src/trace_processor/process_tracker_unittest.cc",
"src/trace_processor/protozero_to_text_unittests.cc",
"src/trace_processor/sched_slice_table_unittest.cc",
"src/trace_processor/slice_tracker_unittest.cc",
"src/trace_processor/span_join_operator_table_unittest.cc",
"src/trace_processor/syscall_tracker_unittest.cc",
- "src/trace_processor/thread_table_unittest.cc",
"src/trace_processor/trace_sorter_unittest.cc",
],
}
@@ -5987,6 +6257,22 @@
],
}
+// GN: //src/traced/probes/ftrace/kallsyms:kallsyms
+filegroup {
+ name: "perfetto_src_traced_probes_ftrace_kallsyms_kallsyms",
+ srcs: [
+ "src/traced/probes/ftrace/kallsyms/kernel_symbol_map.cc",
+ ],
+}
+
+// GN: //src/traced/probes/ftrace/kallsyms:unittests
+filegroup {
+ name: "perfetto_src_traced_probes_ftrace_kallsyms_unittests",
+ srcs: [
+ "src/traced/probes/ftrace/kallsyms/kernel_symbol_map_unittest.cc",
+ ],
+}
+
// GN: //src/traced/probes/ftrace:test_messages_cpp
genrule {
name: "perfetto_src_traced_probes_ftrace_test_messages_cpp_gen",
@@ -6032,7 +6318,7 @@
tools: [
"aprotoc",
],
- cmd: "mkdir -p $(genDir)/external/perfetto/ && $(location aprotoc) --proto_path=external/perfetto --cpp_out=$(genDir)/external/perfetto/ $(in)",
+ cmd: "mkdir -p $(genDir)/external/perfetto/ && $(location aprotoc) --proto_path=external/perfetto --cpp_out=lite=true:$(genDir)/external/perfetto/ $(in)",
out: [
"external/perfetto/src/traced/probes/ftrace/test/test_messages.pb.cc",
],
@@ -6047,7 +6333,7 @@
tools: [
"aprotoc",
],
- cmd: "mkdir -p $(genDir)/external/perfetto/ && $(location aprotoc) --proto_path=external/perfetto --cpp_out=$(genDir)/external/perfetto/ $(in)",
+ cmd: "mkdir -p $(genDir)/external/perfetto/ && $(location aprotoc) --proto_path=external/perfetto --cpp_out=lite=true:$(genDir)/external/perfetto/ $(in)",
out: [
"external/perfetto/src/traced/probes/ftrace/test/test_messages.pb.h",
],
@@ -6219,32 +6505,26 @@
],
}
-// GN: //src/tracing:client_api
+// GN: //src/tracing:client_api_base
filegroup {
- name: "perfetto_src_tracing_client_api",
+ name: "perfetto_src_tracing_client_api_base",
srcs: [
"src/tracing/data_source.cc",
"src/tracing/debug_annotation.cc",
"src/tracing/event_context.cc",
- "src/tracing/internal/in_process_tracing_backend.cc",
- "src/tracing/internal/system_tracing_backend.cc",
"src/tracing/internal/tracing_muxer_impl.cc",
"src/tracing/internal/track_event_internal.cc",
"src/tracing/platform.cc",
"src/tracing/tracing.cc",
+ "src/tracing/track.cc",
"src/tracing/track_event_category_registry.cc",
"src/tracing/virtual_destructors.cc",
],
}
-// GN: //src/tracing:client_api_integrationtests
+// GN: //src/tracing:client_api_system_backend_only
filegroup {
- name: "perfetto_src_tracing_client_api_integrationtests",
- srcs: [
- "src/tracing/api_integrationtest.cc",
- "src/tracing/test/tracing_module.cc",
- "src/tracing/test/tracing_module2.cc",
- ],
+ name: "perfetto_src_tracing_client_api_system_backend_only",
}
// GN: //src/tracing:common
@@ -6255,75 +6535,52 @@
],
}
-// GN: //src/tracing:consumer_api_deprecated
+// GN: //src/tracing/consumer_api_deprecated:consumer_api_deprecated
filegroup {
- name: "perfetto_src_tracing_consumer_api_deprecated",
+ name: "perfetto_src_tracing_consumer_api_deprecated_consumer_api_deprecated",
srcs: [
- "src/tracing/api_impl/consumer_api.cc",
+ "src/tracing/consumer_api_deprecated/consumer_api_deprecated.cc",
],
}
-// GN: //src/tracing:ipc
+// GN: //src/tracing/core:core
filegroup {
- name: "perfetto_src_tracing_ipc",
+ name: "perfetto_src_tracing_core_core",
srcs: [
- "src/tracing/ipc/consumer/consumer_ipc_client_impl.cc",
- "src/tracing/ipc/default_socket.cc",
- "src/tracing/ipc/posix_shared_memory.cc",
- "src/tracing/ipc/producer/producer_ipc_client_impl.cc",
- "src/tracing/ipc/service/consumer_ipc_service.cc",
- "src/tracing/ipc/service/producer_ipc_service.cc",
- "src/tracing/ipc/service/service_ipc_host_impl.cc",
+ "src/tracing/core/id_allocator.cc",
+ "src/tracing/core/null_trace_writer.cc",
+ "src/tracing/core/shared_memory_abi.cc",
+ "src/tracing/core/shared_memory_arbiter_impl.cc",
+ "src/tracing/core/startup_trace_writer.cc",
+ "src/tracing/core/startup_trace_writer_registry.cc",
+ "src/tracing/core/trace_packet.cc",
+ "src/tracing/core/trace_writer_impl.cc",
+ "src/tracing/core/virtual_destructors.cc",
],
}
-// GN: //src/tracing:platform_posix
+// GN: //src/tracing/core:service
filegroup {
- name: "perfetto_src_tracing_platform_posix",
+ name: "perfetto_src_tracing_core_service",
srcs: [
- "src/tracing/platform_posix.cc",
+ "src/tracing/core/metatrace_writer.cc",
+ "src/tracing/core/packet_stream_validator.cc",
+ "src/tracing/core/trace_buffer.cc",
+ "src/tracing/core/tracing_service_impl.cc",
],
}
-// GN: //src/tracing/test:api_test_support
+// GN: //src/tracing/core:test_support
filegroup {
- name: "perfetto_src_tracing_test_api_test_support",
- srcs: [
- "src/tracing/test/api_test_support.cc",
- ],
-}
-
-// GN: //src/tracing:test_support
-filegroup {
- name: "perfetto_src_tracing_test_support",
+ name: "perfetto_src_tracing_core_test_support",
srcs: [
"src/tracing/core/trace_writer_for_testing.cc",
],
}
-// GN: //src/tracing:tracing
+// GN: //src/tracing/core:unittests
filegroup {
- name: "perfetto_src_tracing_tracing",
- srcs: [
- "src/tracing/core/id_allocator.cc",
- "src/tracing/core/metatrace_writer.cc",
- "src/tracing/core/null_trace_writer.cc",
- "src/tracing/core/packet_stream_validator.cc",
- "src/tracing/core/shared_memory_abi.cc",
- "src/tracing/core/shared_memory_arbiter_impl.cc",
- "src/tracing/core/startup_trace_writer.cc",
- "src/tracing/core/startup_trace_writer_registry.cc",
- "src/tracing/core/trace_buffer.cc",
- "src/tracing/core/trace_packet.cc",
- "src/tracing/core/trace_writer_impl.cc",
- "src/tracing/core/tracing_service_impl.cc",
- "src/tracing/core/virtual_destructors.cc",
- ],
-}
-
-// GN: //src/tracing:unittests
-filegroup {
- name: "perfetto_src_tracing_unittests",
+ name: "perfetto_src_tracing_core_unittests",
srcs: [
"src/tracing/core/id_allocator_unittest.cc",
"src/tracing/core/null_trace_writer_unittest.cc",
@@ -6336,12 +6593,118 @@
"src/tracing/core/trace_packet_unittest.cc",
"src/tracing/core/trace_writer_impl_unittest.cc",
"src/tracing/core/tracing_service_impl_unittest.cc",
+ ],
+}
+
+// GN: //src/tracing:in_process_backend
+filegroup {
+ name: "perfetto_src_tracing_in_process_backend",
+ srcs: [
+ "src/tracing/internal/in_process_tracing_backend.cc",
+ ],
+}
+
+// GN: //src/tracing:in_process_backend_fake
+filegroup {
+ name: "perfetto_src_tracing_in_process_backend_fake",
+ srcs: [
+ "src/tracing/internal/in_process_tracing_backend_fake.cc",
+ ],
+}
+
+// GN: //src/tracing/ipc:common
+filegroup {
+ name: "perfetto_src_tracing_ipc_common",
+ srcs: [
+ "src/tracing/ipc/default_socket.cc",
+ "src/tracing/ipc/posix_shared_memory.cc",
+ ],
+}
+
+// GN: //src/tracing/ipc/consumer:consumer
+filegroup {
+ name: "perfetto_src_tracing_ipc_consumer_consumer",
+ srcs: [
+ "src/tracing/ipc/consumer/consumer_ipc_client_impl.cc",
+ ],
+}
+
+// GN: //src/tracing/ipc/producer:producer
+filegroup {
+ name: "perfetto_src_tracing_ipc_producer_producer",
+ srcs: [
+ "src/tracing/ipc/producer/producer_ipc_client_impl.cc",
+ ],
+}
+
+// GN: //src/tracing/ipc/service:service
+filegroup {
+ name: "perfetto_src_tracing_ipc_service_service",
+ srcs: [
+ "src/tracing/ipc/service/consumer_ipc_service.cc",
+ "src/tracing/ipc/service/producer_ipc_service.cc",
+ "src/tracing/ipc/service/service_ipc_host_impl.cc",
+ ],
+}
+
+// GN: //src/tracing/ipc:unittests
+filegroup {
+ name: "perfetto_src_tracing_ipc_unittests",
+ srcs: [
"src/tracing/ipc/posix_shared_memory_unittest.cc",
+ ],
+}
+
+// GN: //src/tracing:platform_posix
+filegroup {
+ name: "perfetto_src_tracing_platform_posix",
+ srcs: [
+ "src/tracing/platform_posix.cc",
+ ],
+}
+
+// GN: //src/tracing:system_process_backend
+filegroup {
+ name: "perfetto_src_tracing_system_process_backend",
+ srcs: [
+ "src/tracing/internal/system_tracing_backend.cc",
+ ],
+}
+
+// GN: //src/tracing/test:api_test_support
+filegroup {
+ name: "perfetto_src_tracing_test_api_test_support",
+ srcs: [
+ "src/tracing/test/api_test_support.cc",
+ ],
+}
+
+// GN: //src/tracing/test:client_api_integrationtests
+filegroup {
+ name: "perfetto_src_tracing_test_client_api_integrationtests",
+ srcs: [
+ "src/tracing/test/api_integrationtest.cc",
+ "src/tracing/test/tracing_module.cc",
+ "src/tracing/test/tracing_module2.cc",
+ ],
+}
+
+// GN: //src/tracing/test:test_support
+filegroup {
+ name: "perfetto_src_tracing_test_test_support",
+ srcs: [
"src/tracing/test/aligned_buffer_test.cc",
"src/tracing/test/fake_packet.cc",
"src/tracing/test/mock_consumer.cc",
"src/tracing/test/mock_producer.cc",
"src/tracing/test/test_shared_memory.cc",
+ ],
+}
+
+// GN: //src/tracing/test:tracing_integration_test
+filegroup {
+ name: "perfetto_src_tracing_test_tracing_integration_test",
+ srcs: [
"src/tracing/test/tracing_integration_test.cc",
],
}
@@ -6354,27 +6717,11 @@
],
}
-// GN: //test:task_runner_thread
-filegroup {
- name: "perfetto_test_task_runner_thread",
- srcs: [
- "test/task_runner_thread.cc",
- ],
-}
-
-// GN: //test:task_runner_thread_delegates
-filegroup {
- name: "perfetto_test_task_runner_thread_delegates",
- srcs: [
- "test/fake_producer.cc",
- "test/task_runner_thread_delegates.cc",
- ],
-}
-
// GN: //test:test_helper
filegroup {
name: "perfetto_test_test_helper",
srcs: [
+ "test/fake_producer.cc",
"test/test_helper.cc",
],
}
@@ -6603,7 +6950,9 @@
":perfetto_src_base_test_support",
":perfetto_src_base_unittests",
":perfetto_src_base_unix_socket",
- ":perfetto_src_ipc_ipc",
+ ":perfetto_src_ipc_client",
+ ":perfetto_src_ipc_common",
+ ":perfetto_src_ipc_host",
":perfetto_src_ipc_test_messages_cpp_gen",
":perfetto_src_ipc_test_messages_ipc_gen",
":perfetto_src_ipc_unittests",
@@ -6645,6 +6994,7 @@
":perfetto_src_trace_processor_storage_minimal",
":perfetto_src_trace_processor_tables_tables",
":perfetto_src_trace_processor_tables_unittests",
+ ":perfetto_src_trace_processor_types_types",
":perfetto_src_trace_processor_unittests",
":perfetto_src_traced_probes_android_log_android_log",
":perfetto_src_traced_probes_android_log_unittests",
@@ -6653,6 +7003,8 @@
":perfetto_src_traced_probes_filesystem_unittests",
":perfetto_src_traced_probes_ftrace_format_parser",
":perfetto_src_traced_probes_ftrace_ftrace",
+ ":perfetto_src_traced_probes_ftrace_kallsyms_kallsyms",
+ ":perfetto_src_traced_probes_ftrace_kallsyms_unittests",
":perfetto_src_traced_probes_ftrace_test_messages_cpp_gen",
":perfetto_src_traced_probes_ftrace_test_messages_lite_gen",
":perfetto_src_traced_probes_ftrace_test_messages_zero_gen",
@@ -6671,10 +7023,17 @@
":perfetto_src_traced_service_service",
":perfetto_src_traced_service_unittests",
":perfetto_src_tracing_common",
- ":perfetto_src_tracing_ipc",
- ":perfetto_src_tracing_test_support",
- ":perfetto_src_tracing_tracing",
- ":perfetto_src_tracing_unittests",
+ ":perfetto_src_tracing_core_core",
+ ":perfetto_src_tracing_core_service",
+ ":perfetto_src_tracing_core_test_support",
+ ":perfetto_src_tracing_core_unittests",
+ ":perfetto_src_tracing_ipc_common",
+ ":perfetto_src_tracing_ipc_consumer_consumer",
+ ":perfetto_src_tracing_ipc_producer_producer",
+ ":perfetto_src_tracing_ipc_service_service",
+ ":perfetto_src_tracing_ipc_unittests",
+ ":perfetto_src_tracing_test_test_support",
+ ":perfetto_src_tracing_test_tracing_integration_test",
":perfetto_tools_sanitizers_unittests_sanitizers_unittests",
],
shared_libs: [
@@ -6859,6 +7218,7 @@
":perfetto_src_trace_processor_storage_full",
":perfetto_src_trace_processor_storage_minimal",
":perfetto_src_trace_processor_tables_tables",
+ ":perfetto_src_trace_processor_types_types",
"src/trace_processor/proto_to_json.cc",
"src/trace_processor/trace_processor_shell.cc",
],
@@ -6968,6 +7328,7 @@
":perfetto_src_trace_processor_storage_full",
":perfetto_src_trace_processor_storage_minimal",
":perfetto_src_trace_processor_tables_tables",
+ ":perfetto_src_trace_processor_types_types",
":perfetto_tools_trace_to_text_common",
":perfetto_tools_trace_to_text_full",
":perfetto_tools_trace_to_text_pprofbuilder",
@@ -7092,14 +7453,16 @@
":perfetto_protos_perfetto_trace_track_event_zero_gen",
":perfetto_src_base_base",
":perfetto_src_base_unix_socket",
- ":perfetto_src_ipc_ipc",
+ ":perfetto_src_ipc_client",
+ ":perfetto_src_ipc_common",
":perfetto_src_profiling_perf_producer",
":perfetto_src_profiling_perf_traced_perf_main",
":perfetto_src_profiling_perf_unwind_support",
":perfetto_src_protozero_protozero",
":perfetto_src_tracing_common",
- ":perfetto_src_tracing_ipc",
- ":perfetto_src_tracing_tracing",
+ ":perfetto_src_tracing_core_core",
+ ":perfetto_src_tracing_ipc_common",
+ ":perfetto_src_tracing_ipc_producer_producer",
"src/profiling/perf/main.cc",
],
shared_libs: [
@@ -7232,14 +7595,16 @@
":perfetto_protos_perfetto_trace_track_event_zero_gen",
":perfetto_src_base_base",
":perfetto_src_base_unix_socket",
- ":perfetto_src_ipc_ipc",
+ ":perfetto_src_ipc_client",
+ ":perfetto_src_ipc_common",
":perfetto_src_perfetto_cmd_protos_gen",
":perfetto_src_perfetto_cmd_trigger_perfetto_cmd",
":perfetto_src_perfetto_cmd_trigger_producer",
":perfetto_src_protozero_protozero",
":perfetto_src_tracing_common",
- ":perfetto_src_tracing_ipc",
- ":perfetto_src_tracing_tracing",
+ ":perfetto_src_tracing_core_core",
+ ":perfetto_src_tracing_ipc_common",
+ ":perfetto_src_tracing_ipc_producer_producer",
"src/perfetto_cmd/trigger_perfetto_main.cc",
],
shared_libs: [
@@ -7296,25 +7661,6 @@
// These targets are appended to the autogenerated Android.bp by tools/gen_android_bp.
-cc_library_static {
- name: "perfetto_cts_jni_deps",
- srcs: [
- "src/base/test/test_task_runner.cc",
- "test/fake_producer.cc",
- "test/task_runner_thread_delegates.cc",
- ],
- shared_libs: [
- "libprotobuf-cpp-lite",
- ],
- static_libs: [
- "libgtest",
- "libperfetto_client_experimental",
- ],
- defaults: [
- "perfetto_defaults",
- ],
-}
-
java_library_host {
name: "perfetto_config-full",
proto: {
diff --git a/Android.bp.extras b/Android.bp.extras
index 9586516..65a81f4 100644
--- a/Android.bp.extras
+++ b/Android.bp.extras
@@ -1,24 +1,5 @@
// These targets are appended to the autogenerated Android.bp by tools/gen_android_bp.
-cc_library_static {
- name: "perfetto_cts_jni_deps",
- srcs: [
- "src/base/test/test_task_runner.cc",
- "test/fake_producer.cc",
- "test/task_runner_thread_delegates.cc",
- ],
- shared_libs: [
- "libprotobuf-cpp-lite",
- ],
- static_libs: [
- "libgtest",
- "libperfetto_client_experimental",
- ],
- defaults: [
- "perfetto_defaults",
- ],
-}
-
java_library_host {
name: "perfetto_config-full",
proto: {
diff --git a/BUILD b/BUILD
index 5303bde..1d891cc 100644
--- a/BUILD
+++ b/BUILD
@@ -58,7 +58,9 @@
srcs = [
":src_base_base",
":src_base_unix_socket",
- ":src_ipc_ipc",
+ ":src_ipc_client",
+ ":src_ipc_common",
+ ":src_ipc_host",
],
hdrs = [
":include_perfetto_base_base",
@@ -161,7 +163,9 @@
":src_android_internal_lazy_library_loader",
":src_base_base",
":src_base_unix_socket",
- ":src_ipc_ipc",
+ ":src_ipc_client",
+ ":src_ipc_common",
+ ":src_ipc_host",
":src_perfetto_cmd_perfetto_atoms",
":src_protozero_protozero",
":src_traced_probes_android_log_android_log",
@@ -178,9 +182,13 @@
":src_traced_probes_sys_stats_sys_stats",
":src_traced_service_service",
":src_tracing_common",
- ":src_tracing_consumer_api_deprecated",
- ":src_tracing_ipc",
- ":src_tracing_tracing",
+ ":src_tracing_consumer_api_deprecated_consumer_api_deprecated",
+ ":src_tracing_core_core",
+ ":src_tracing_core_service",
+ ":src_tracing_ipc_common",
+ ":src_tracing_ipc_consumer_consumer",
+ ":src_tracing_ipc_producer_producer",
+ ":src_tracing_ipc_service_service",
],
hdrs = [
":include_perfetto_base_base",
@@ -245,8 +253,11 @@
"include/perfetto/base/build_config.h",
"include/perfetto/base/compiler.h",
"include/perfetto/base/export.h",
+ "include/perfetto/base/flat_set.h",
"include/perfetto/base/logging.h",
+ "include/perfetto/base/proc_utils.h",
"include/perfetto/base/task_runner.h",
+ "include/perfetto/base/thread_utils.h",
"include/perfetto/base/time.h",
],
)
@@ -259,7 +270,6 @@
"include/perfetto/ext/base/container_annotations.h",
"include/perfetto/ext/base/event_fd.h",
"include/perfetto/ext/base/file_utils.h",
- "include/perfetto/ext/base/flat_set.h",
"include/perfetto/ext/base/hash.h",
"include/perfetto/ext/base/lookup_set.h",
"include/perfetto/ext/base/metatrace.h",
@@ -268,7 +278,6 @@
"include/perfetto/ext/base/optional.h",
"include/perfetto/ext/base/paged_memory.h",
"include/perfetto/ext/base/pipe.h",
- "include/perfetto/ext/base/proc_utils.h",
"include/perfetto/ext/base/scoped_file.h",
"include/perfetto/ext/base/small_set.h",
"include/perfetto/ext/base/string_splitter.h",
@@ -279,7 +288,6 @@
"include/perfetto/ext/base/thread_annotations.h",
"include/perfetto/ext/base/thread_checker.h",
"include/perfetto/ext/base/thread_task_runner.h",
- "include/perfetto/ext/base/thread_utils.h",
"include/perfetto/ext/base/unix_socket.h",
"include/perfetto/ext/base/unix_task_runner.h",
"include/perfetto/ext/base/utils.h",
@@ -477,9 +485,11 @@
"include/perfetto/tracing/trace_writer_base.h",
"include/perfetto/tracing/tracing.h",
"include/perfetto/tracing/tracing_backend.h",
+ "include/perfetto/tracing/track.h",
"include/perfetto/tracing/track_event.h",
"include/perfetto/tracing/track_event_category_registry.h",
"include/perfetto/tracing/track_event_interned_data_index.h",
+ "include/perfetto/tracing/track_event_legacy.h",
],
)
@@ -538,19 +548,33 @@
],
)
-# GN target: //src/ipc:ipc
+# GN target: //src/ipc:client
filegroup(
- name = "src_ipc_ipc",
+ name = "src_ipc_client",
+ srcs = [
+ "src/ipc/client_impl.cc",
+ "src/ipc/client_impl.h",
+ "src/ipc/service_proxy.cc",
+ ],
+)
+
+# GN target: //src/ipc:common
+filegroup(
+ name = "src_ipc_common",
srcs = [
"src/ipc/buffered_frame_deserializer.cc",
"src/ipc/buffered_frame_deserializer.h",
- "src/ipc/client_impl.cc",
- "src/ipc/client_impl.h",
"src/ipc/deferred.cc",
+ "src/ipc/virtual_destructors.cc",
+ ],
+)
+
+# GN target: //src/ipc:host
+filegroup(
+ name = "src_ipc_host",
+ srcs = [
"src/ipc/host_impl.cc",
"src/ipc/host_impl.h",
- "src/ipc/service_proxy.cc",
- "src/ipc/virtual_destructors.cc",
],
)
@@ -661,6 +685,7 @@
"src/trace_processor/db/table.cc",
"src/trace_processor/db/table.h",
"src/trace_processor/db/typed_column.h",
+ "src/trace_processor/db/typed_column_internal.h",
],
)
@@ -670,6 +695,7 @@
"src/trace_processor/metrics/android/android_batt.sql",
"src/trace_processor/metrics/android/android_cpu.sql",
"src/trace_processor/metrics/android/android_cpu_agg.sql",
+ "src/trace_processor/metrics/android/android_hwui_metric.sql",
"src/trace_processor/metrics/android/android_ion.sql",
"src/trace_processor/metrics/android/android_lmk.sql",
"src/trace_processor/metrics/android/android_lmk_reason.sql",
@@ -707,6 +733,7 @@
filegroup(
name = "src_trace_processor_metrics_lib",
srcs = [
+ "src/trace_processor/metrics/custom_options.descriptor.h",
"src/trace_processor/metrics/metrics.cc",
"src/trace_processor/metrics/metrics.descriptor.h",
"src/trace_processor/metrics/metrics.h",
@@ -763,6 +790,17 @@
],
)
+# GN target: //src/trace_processor/types:types
+filegroup(
+ name = "src_trace_processor_types_types",
+ srcs = [
+ "src/trace_processor/types/gfp_flags.cc",
+ "src/trace_processor/types/gfp_flags.h",
+ "src/trace_processor/types/variadic.cc",
+ "src/trace_processor/types/variadic.h",
+ ],
+)
+
# GN target: //src/trace_processor:descriptors
filegroup(
name = "src_trace_processor_descriptors",
@@ -785,16 +823,8 @@
filegroup(
name = "src_trace_processor_lib",
srcs = [
- "src/trace_processor/args_table.cc",
- "src/trace_processor/args_table.h",
"src/trace_processor/filtered_row_index.cc",
"src/trace_processor/filtered_row_index.h",
- "src/trace_processor/gfp_flags.cc",
- "src/trace_processor/gfp_flags.h",
- "src/trace_processor/process_table.cc",
- "src/trace_processor/process_table.h",
- "src/trace_processor/raw_table.cc",
- "src/trace_processor/raw_table.h",
"src/trace_processor/read_trace.cc",
"src/trace_processor/row_iterators.cc",
"src/trace_processor/row_iterators.h",
@@ -804,6 +834,10 @@
"src/trace_processor/span_join_operator_table.h",
"src/trace_processor/sql_stats_table.cc",
"src/trace_processor/sql_stats_table.h",
+ "src/trace_processor/sqlite_experimental_flamegraph_table.cc",
+ "src/trace_processor/sqlite_experimental_flamegraph_table.h",
+ "src/trace_processor/sqlite_raw_table.cc",
+ "src/trace_processor/sqlite_raw_table.h",
"src/trace_processor/stats_table.cc",
"src/trace_processor/stats_table.h",
"src/trace_processor/storage_columns.cc",
@@ -812,8 +846,6 @@
"src/trace_processor/storage_schema.h",
"src/trace_processor/storage_table.cc",
"src/trace_processor/storage_table.h",
- "src/trace_processor/thread_table.cc",
- "src/trace_processor/thread_table.h",
"src/trace_processor/trace_processor.cc",
"src/trace_processor/trace_processor_impl.cc",
"src/trace_processor/trace_processor_impl.h",
@@ -891,6 +923,8 @@
"src/trace_processor/forwarding_trace_parser.h",
"src/trace_processor/ftrace_utils.cc",
"src/trace_processor/ftrace_utils.h",
+ "src/trace_processor/global_args_tracker.cc",
+ "src/trace_processor/global_args_tracker.h",
"src/trace_processor/gzip_trace_parser.cc",
"src/trace_processor/gzip_trace_parser.h",
"src/trace_processor/heap_profile_tracker.cc",
@@ -954,7 +988,6 @@
"src/trace_processor/trace_storage.h",
"src/trace_processor/track_tracker.cc",
"src/trace_processor/track_tracker.h",
- "src/trace_processor/variadic.h",
"src/trace_processor/virtual_destructors.cc",
],
)
@@ -1113,22 +1146,106 @@
],
)
-# GN target: //src/tracing:client_api
+# GN target: //src/tracing/consumer_api_deprecated:consumer_api_deprecated
filegroup(
- name = "src_tracing_client_api",
+ name = "src_tracing_consumer_api_deprecated_consumer_api_deprecated",
+ srcs = [
+ "src/tracing/consumer_api_deprecated/consumer_api_deprecated.cc",
+ ],
+)
+
+# GN target: //src/tracing/core:core
+filegroup(
+ name = "src_tracing_core_core",
+ srcs = [
+ "src/tracing/core/id_allocator.cc",
+ "src/tracing/core/id_allocator.h",
+ "src/tracing/core/null_trace_writer.cc",
+ "src/tracing/core/null_trace_writer.h",
+ "src/tracing/core/patch_list.h",
+ "src/tracing/core/shared_memory_abi.cc",
+ "src/tracing/core/shared_memory_arbiter_impl.cc",
+ "src/tracing/core/shared_memory_arbiter_impl.h",
+ "src/tracing/core/startup_trace_writer.cc",
+ "src/tracing/core/startup_trace_writer_registry.cc",
+ "src/tracing/core/trace_packet.cc",
+ "src/tracing/core/trace_writer_impl.cc",
+ "src/tracing/core/trace_writer_impl.h",
+ "src/tracing/core/virtual_destructors.cc",
+ ],
+)
+
+# GN target: //src/tracing/core:service
+filegroup(
+ name = "src_tracing_core_service",
+ srcs = [
+ "src/tracing/core/metatrace_writer.cc",
+ "src/tracing/core/metatrace_writer.h",
+ "src/tracing/core/packet_stream_validator.cc",
+ "src/tracing/core/packet_stream_validator.h",
+ "src/tracing/core/trace_buffer.cc",
+ "src/tracing/core/trace_buffer.h",
+ "src/tracing/core/tracing_service_impl.cc",
+ "src/tracing/core/tracing_service_impl.h",
+ ],
+)
+
+# GN target: //src/tracing/ipc/consumer:consumer
+filegroup(
+ name = "src_tracing_ipc_consumer_consumer",
+ srcs = [
+ "src/tracing/ipc/consumer/consumer_ipc_client_impl.cc",
+ "src/tracing/ipc/consumer/consumer_ipc_client_impl.h",
+ ],
+)
+
+# GN target: //src/tracing/ipc/producer:producer
+filegroup(
+ name = "src_tracing_ipc_producer_producer",
+ srcs = [
+ "src/tracing/ipc/producer/producer_ipc_client_impl.cc",
+ "src/tracing/ipc/producer/producer_ipc_client_impl.h",
+ ],
+)
+
+# GN target: //src/tracing/ipc/service:service
+filegroup(
+ name = "src_tracing_ipc_service_service",
+ srcs = [
+ "src/tracing/ipc/service/consumer_ipc_service.cc",
+ "src/tracing/ipc/service/consumer_ipc_service.h",
+ "src/tracing/ipc/service/producer_ipc_service.cc",
+ "src/tracing/ipc/service/producer_ipc_service.h",
+ "src/tracing/ipc/service/service_ipc_host_impl.cc",
+ "src/tracing/ipc/service/service_ipc_host_impl.h",
+ ],
+)
+
+# GN target: //src/tracing/ipc:common
+filegroup(
+ name = "src_tracing_ipc_common",
+ srcs = [
+ "src/tracing/ipc/default_socket.cc",
+ "src/tracing/ipc/posix_shared_memory.cc",
+ "src/tracing/ipc/posix_shared_memory.h",
+ ],
+)
+
+# GN target: //src/tracing:client_api_base
+filegroup(
+ name = "src_tracing_client_api_base",
srcs = [
"src/tracing/data_source.cc",
"src/tracing/debug_annotation.cc",
"src/tracing/event_context.cc",
- "src/tracing/internal/in_process_tracing_backend.cc",
"src/tracing/internal/in_process_tracing_backend.h",
- "src/tracing/internal/system_tracing_backend.cc",
"src/tracing/internal/system_tracing_backend.h",
"src/tracing/internal/tracing_muxer_impl.cc",
"src/tracing/internal/tracing_muxer_impl.h",
"src/tracing/internal/track_event_internal.cc",
"src/tracing/platform.cc",
"src/tracing/tracing.cc",
+ "src/tracing/track.cc",
"src/tracing/track_event_category_registry.cc",
"src/tracing/virtual_destructors.cc",
],
@@ -1142,31 +1259,11 @@
],
)
-# GN target: //src/tracing:consumer_api_deprecated
+# GN target: //src/tracing:in_process_backend
filegroup(
- name = "src_tracing_consumer_api_deprecated",
+ name = "src_tracing_in_process_backend",
srcs = [
- "src/tracing/api_impl/consumer_api.cc",
- ],
-)
-
-# GN target: //src/tracing:ipc
-filegroup(
- name = "src_tracing_ipc",
- srcs = [
- "src/tracing/ipc/consumer/consumer_ipc_client_impl.cc",
- "src/tracing/ipc/consumer/consumer_ipc_client_impl.h",
- "src/tracing/ipc/default_socket.cc",
- "src/tracing/ipc/posix_shared_memory.cc",
- "src/tracing/ipc/posix_shared_memory.h",
- "src/tracing/ipc/producer/producer_ipc_client_impl.cc",
- "src/tracing/ipc/producer/producer_ipc_client_impl.h",
- "src/tracing/ipc/service/consumer_ipc_service.cc",
- "src/tracing/ipc/service/consumer_ipc_service.h",
- "src/tracing/ipc/service/producer_ipc_service.cc",
- "src/tracing/ipc/service/producer_ipc_service.h",
- "src/tracing/ipc/service/service_ipc_host_impl.cc",
- "src/tracing/ipc/service/service_ipc_host_impl.h",
+ "src/tracing/internal/in_process_tracing_backend.cc",
],
)
@@ -1178,32 +1275,11 @@
],
)
-# GN target: //src/tracing:tracing
+# GN target: //src/tracing:system_process_backend
filegroup(
- name = "src_tracing_tracing",
+ name = "src_tracing_system_process_backend",
srcs = [
- "src/tracing/core/id_allocator.cc",
- "src/tracing/core/id_allocator.h",
- "src/tracing/core/metatrace_writer.cc",
- "src/tracing/core/metatrace_writer.h",
- "src/tracing/core/null_trace_writer.cc",
- "src/tracing/core/null_trace_writer.h",
- "src/tracing/core/packet_stream_validator.cc",
- "src/tracing/core/packet_stream_validator.h",
- "src/tracing/core/patch_list.h",
- "src/tracing/core/shared_memory_abi.cc",
- "src/tracing/core/shared_memory_arbiter_impl.cc",
- "src/tracing/core/shared_memory_arbiter_impl.h",
- "src/tracing/core/startup_trace_writer.cc",
- "src/tracing/core/startup_trace_writer_registry.cc",
- "src/tracing/core/trace_buffer.cc",
- "src/tracing/core/trace_buffer.h",
- "src/tracing/core/trace_packet.cc",
- "src/tracing/core/trace_writer_impl.cc",
- "src/tracing/core/trace_writer_impl.h",
- "src/tracing/core/tracing_service_impl.cc",
- "src/tracing/core/tracing_service_impl.h",
- "src/tracing/core/virtual_destructors.cc",
+ "src/tracing/internal/system_tracing_backend.cc",
],
)
@@ -1486,9 +1562,7 @@
srcs = [
"protos/perfetto/config/perfetto_config.proto",
],
- visibility = [
- "//visibility:public",
- ],
+ visibility = PERFETTO_CONFIG.public_visibility,
)
# GN target: //protos/perfetto/config/power:cpp
@@ -1607,9 +1681,7 @@
"protos/perfetto/config/test_config.proto",
"protos/perfetto/config/trace_config.proto",
],
- visibility = [
- "//visibility:public",
- ],
+ visibility = PERFETTO_CONFIG.public_visibility,
deps = [
":protos_perfetto_common_protos",
":protos_perfetto_config_android_protos",
@@ -1767,6 +1839,7 @@
"protos/perfetto/metrics/android/batt_metric.proto",
"protos/perfetto/metrics/android/cpu_metric.proto",
"protos/perfetto/metrics/android/heap_profile_callsites.proto",
+ "protos/perfetto/metrics/android/hwui_metric.proto",
"protos/perfetto/metrics/android/ion_metric.proto",
"protos/perfetto/metrics/android/java_heap_stats.proto",
"protos/perfetto/metrics/android/lmk_metric.proto",
@@ -1780,9 +1853,7 @@
"protos/perfetto/metrics/android/unmapped_java_symbols.proto",
"protos/perfetto/metrics/android/unsymbolized_frames.proto",
],
- visibility = [
- "//visibility:public",
- ],
+ visibility = PERFETTO_CONFIG.public_visibility,
)
# GN target: //protos/perfetto/metrics/android:zero
@@ -1807,9 +1878,7 @@
srcs = [
"protos/perfetto/metrics/metrics.proto",
],
- visibility = [
- "//visibility:public",
- ],
+ visibility = PERFETTO_CONFIG.public_visibility,
deps = [
":protos_perfetto_metrics_android_protos",
],
@@ -2050,9 +2119,7 @@
srcs = [
"protos/perfetto/trace/perfetto_trace.proto",
],
- visibility = [
- "//visibility:public",
- ],
+ visibility = PERFETTO_CONFIG.public_visibility,
)
# GN target: //protos/perfetto/trace:minimal_lite
@@ -2113,9 +2180,7 @@
"protos/perfetto/trace/trace_packet.proto",
"protos/perfetto/trace/trace_packet_defaults.proto",
],
- visibility = [
- "//visibility:public",
- ],
+ visibility = PERFETTO_CONFIG.public_visibility,
deps = [
":protos_perfetto_common_protos",
":protos_perfetto_config_android_protos",
@@ -2420,13 +2485,21 @@
srcs = [
":src_base_base",
":src_base_unix_socket",
- ":src_ipc_ipc",
+ ":src_ipc_client",
+ ":src_ipc_common",
+ ":src_ipc_host",
":src_protozero_protozero",
- ":src_tracing_client_api",
+ ":src_tracing_client_api_base",
":src_tracing_common",
- ":src_tracing_ipc",
+ ":src_tracing_core_core",
+ ":src_tracing_core_service",
+ ":src_tracing_in_process_backend",
+ ":src_tracing_ipc_common",
+ ":src_tracing_ipc_consumer_consumer",
+ ":src_tracing_ipc_producer_producer",
+ ":src_tracing_ipc_service_service",
":src_tracing_platform_posix",
- ":src_tracing_tracing",
+ ":src_tracing_system_process_backend",
],
hdrs = [
":include_perfetto_base_base",
@@ -2504,14 +2577,17 @@
":src_android_internal_lazy_library_loader",
":src_base_base",
":src_base_unix_socket",
- ":src_ipc_ipc",
+ ":src_ipc_client",
+ ":src_ipc_common",
":src_perfetto_cmd_perfetto_atoms",
":src_perfetto_cmd_perfetto_cmd",
":src_perfetto_cmd_trigger_producer",
":src_protozero_protozero",
":src_tracing_common",
- ":src_tracing_ipc",
- ":src_tracing_tracing",
+ ":src_tracing_core_core",
+ ":src_tracing_ipc_common",
+ ":src_tracing_ipc_consumer_consumer",
+ ":src_tracing_ipc_producer_producer",
],
visibility = [
"//visibility:public",
@@ -2574,6 +2650,7 @@
":src_trace_processor_storage_full",
":src_trace_processor_storage_minimal",
":src_trace_processor_tables_tables",
+ ":src_trace_processor_types_types",
],
hdrs = [
":include_perfetto_base_base",
@@ -2657,6 +2734,7 @@
":src_trace_processor_storage_full",
":src_trace_processor_storage_minimal",
":src_trace_processor_tables_tables",
+ ":src_trace_processor_types_types",
],
visibility = [
"//visibility:public",
@@ -2812,6 +2890,7 @@
":src_trace_processor_storage_full",
":src_trace_processor_storage_minimal",
":src_trace_processor_tables_tables",
+ ":src_trace_processor_types_types",
":tools_trace_to_text_common",
":tools_trace_to_text_full",
":tools_trace_to_text_pprofbuilder",
diff --git a/BUILD.gn b/BUILD.gn
index b89b558..c57fd69 100644
--- a/BUILD.gn
+++ b/BUILD.gn
@@ -39,7 +39,7 @@
]
}
-if (enable_perfetto_trace_processor) {
+if (enable_perfetto_trace_processor && enable_perfetto_trace_processor_sqlite) {
all_targets += [ "src/trace_processor:trace_processor_shell" ]
}
@@ -82,7 +82,7 @@
}
if (enable_perfetto_trace_processor_json) {
- executable("trace_processor_minimal_smoke_tests") {
+ test("trace_processor_minimal_smoke_tests") {
testonly = true
deps = [
"gn:default_deps",
@@ -114,7 +114,7 @@
# compile-time checks for the CI.
if (perfetto_build_standalone) {
all_targets += [
- "src/tracing:consumer_api_test",
+ "src/tracing/consumer_api_deprecated:consumer_api_test",
"test/configs",
# For syntax-checking the proto.
@@ -132,6 +132,9 @@
# Used in the when updating the ftrace protos
"protos/perfetto/trace/ftrace:descriptor",
+
+ # Checks that the "fake" backend implementations build.
+ "src/tracing:client_api_no_backends_compile_test",
]
}
@@ -155,9 +158,7 @@
# depending on other GN files.
group("default") {
testonly = true
- deps = [
- ":all",
- ]
+ deps = [ ":all" ]
}
# +----------------------------------------------------------------------------+
@@ -166,9 +167,7 @@
if (enable_perfetto_ui) {
group("ui") {
- deps = [
- "ui",
- ]
+ deps = [ "ui" ]
}
}
@@ -198,13 +197,13 @@
"gn:default_deps",
"src/traced/probes",
"src/traced/service",
- "src/tracing:consumer_api_deprecated",
+ "src/tracing/consumer_api_deprecated",
]
}
}
if (!build_with_chromium) {
- # Client library target.
+ # Client library target exposed to the Android tree.
# Still in experimental stage and not API stable yet.
# See "libperfetto_client_example" (in Android.bp.extras) for an example
# on how to use the Perfetto Client API from the android tree.
@@ -212,13 +211,19 @@
complete_static_lib = true
public_deps = [
"gn:default_deps",
- "src/tracing",
- "src/tracing:client_api",
"src/tracing:platform_posix",
+ "src/tracing/core",
]
- sources = [
- "include/perfetto/tracing.h",
- ]
+
+ if (perfetto_build_with_android) {
+ # Android in-tree builds expose only the system backend and don't expose
+ # the in-process backend. This is to save binary size and memory (see
+ # b/148198993).
+ public_deps += [ "src/tracing:client_api_system_backend_only" ]
+ } else {
+ public_deps += [ "src/tracing:client_api" ]
+ }
+ sources = [ "include/perfetto/tracing.h" ]
assert_no_deps = [ "//gn:protobuf_lite" ]
}
}
@@ -233,7 +238,11 @@
deps = [
"src/trace_processor:export_json",
"src/trace_processor:storage_minimal",
- "src/tracing",
+ "src/tracing:client_api",
+ "src/tracing/core",
+
+ # TODO(eseckler): Create a platform for chrome and hook it up somehow.
+ "src/tracing:platform_fake",
]
configs -= [ "//build/config/compiler:chromium_code" ]
configs += [ "//build/config/compiler:no_chromium_code" ]
@@ -241,6 +250,7 @@
"include/perfetto/ext/trace_processor:export_json",
"include/perfetto/ext/tracing/core",
"include/perfetto/trace_processor:storage",
+ "include/perfetto/tracing",
"protos/perfetto/common:zero",
"protos/perfetto/trace:zero",
"protos/perfetto/trace/chrome:zero",
@@ -248,16 +258,19 @@
"protos/perfetto/trace/profiling:zero",
"protos/perfetto/trace/track_event:zero",
]
+ if (enable_perfetto_ipc) {
+ deps += [
+ "src/tracing/ipc/producer",
+ "src/tracing/ipc/service",
+ ]
+ public_deps += [ "include/perfetto/ext/tracing/ipc:ipc" ]
+ }
}
component("libtrace_processor") {
public_configs = [ "gn:public_config" ]
- deps = [
- "src/trace_processor:lib",
- ]
+ deps = [ "src/trace_processor:lib" ]
configs -= [ "//build/config/compiler:chromium_code" ]
configs += [ "//build/config/compiler:no_chromium_code" ]
- public_deps = [
- "include/perfetto/trace_processor",
- ]
+ public_deps = [ "include/perfetto/trace_processor" ]
}
}
diff --git a/bazel/proto_gen.bzl b/bazel/proto_gen.bzl
index 6886a28..14e7e75 100644
--- a/bazel/proto_gen.bzl
+++ b/bazel/proto_gen.bzl
@@ -71,7 +71,7 @@
plugin_deps += [ctx.executable.plugin]
else:
arguments += [
- "--cpp_out=" + out_dir,
+ "--cpp_out=lite=true:" + out_dir,
]
arguments += [src.path for src in proto_src]
diff --git a/bazel/rules.bzl b/bazel/rules.bzl
index 7fca94d..498f34a 100644
--- a/bazel/rules.bzl
+++ b/bazel/rules.bzl
@@ -22,7 +22,9 @@
def default_cc_args():
return {
"deps": PERFETTO_CONFIG.deps.build_config,
- "copts": [],
+ "copts": [
+ "-Wno-pragma-system-header-outside-header",
+ ],
"includes": ["include"],
"linkopts": select({
"@perfetto//bazel:os_linux": ["-ldl", "-lrt", "-lpthread"],
diff --git a/bazel/standalone/perfetto_cfg.bzl b/bazel/standalone/perfetto_cfg.bzl
index 1e8f6d0..d441c06 100644
--- a/bazel/standalone/perfetto_cfg.bzl
+++ b/bazel/standalone/perfetto_cfg.bzl
@@ -55,6 +55,13 @@
sqlite = [],
),
+ # Allow Bazel embedders to change the visibility of "public" targets.
+ # This variable has been introduced to limit the change to Bazel and avoid
+ # making the targets fully public in the google internal tree.
+ public_visibility = [
+ "//visibility:public",
+ ],
+
# Allow Bazel embedders to change the visibility of the proto targets.
# This variable has been introduced to limit the change to Bazel and avoid
# making the targets public in the google internal tree.
diff --git a/buildtools/BUILD.gn b/buildtools/BUILD.gn
index 6215959..a0d5f33 100644
--- a/buildtools/BUILD.gn
+++ b/buildtools/BUILD.gn
@@ -96,12 +96,8 @@
configs -= [ "//gn/standalone:extra_warnings" ]
public_configs = [ ":googletest_config" ]
all_dependent_configs = [ ":googletest_config" ]
- sources = [
- "googletest/googletest/src/gtest-all.cc",
- ]
- deps = [
- "//gn:default_deps",
- ]
+ sources = [ "googletest/googletest/src/gtest-all.cc" ]
+ deps = [ "//gn:default_deps" ]
}
source_set("gtest_main") {
@@ -109,12 +105,8 @@
testonly = true
configs -= [ "//gn/standalone:extra_warnings" ]
configs += [ ":googletest_config" ]
- sources = [
- "googletest/googletest/src/gtest_main.cc",
- ]
- deps = [
- "//gn:default_deps",
- ]
+ sources = [ "googletest/googletest/src/gtest_main.cc" ]
+ deps = [ "//gn:default_deps" ]
}
source_set("gmock") {
@@ -124,12 +116,8 @@
configs -= [ "//gn/standalone:extra_warnings" ]
public_configs = [ ":googletest_config" ]
all_dependent_configs = [ ":googletest_config" ]
- sources = [
- "googletest/googlemock/src/gmock-all.cc",
- ]
- deps = [
- "//gn:default_deps",
- ]
+ sources = [ "googletest/googlemock/src/gmock-all.cc" ]
+ deps = [ "//gn:default_deps" ]
}
# This config is applied to the autogenerated .pb.{cc,h} files in
@@ -257,9 +245,7 @@
configs -= [ "//gn/standalone:extra_warnings" ]
configs += [ ":protobuf_config" ]
public_configs = [ ":protobuf_gen_config" ]
- deps = [
- "//gn:default_deps",
- ]
+ deps = [ "//gn:default_deps" ]
}
source_set("protobuf_full") {
@@ -575,9 +561,7 @@
":protoc_lib",
"//gn:default_deps",
]
- sources = [
- "protobuf/src/google/protobuf/compiler/main.cc",
- ]
+ sources = [ "protobuf/src/google/protobuf/compiler/main.cc" ]
configs -= [ "//gn/standalone:extra_warnings" ]
}
} # host_toolchain
@@ -661,9 +645,7 @@
":libc++config",
"//gn/standalone/sanitizers:sanitizer_options_link_helper",
]
- deps = [
- ":libunwind",
- ]
+ deps = [ ":libunwind" ]
}
if (custom_libcxx_is_static) {
@@ -679,8 +661,10 @@
"libcxx/src/algorithm.cpp",
"libcxx/src/any.cpp",
"libcxx/src/bind.cpp",
+ "libcxx/src/charconv.cpp",
"libcxx/src/chrono.cpp",
"libcxx/src/condition_variable.cpp",
+ "libcxx/src/condition_variable_destructor.cpp",
"libcxx/src/debug.cpp",
"libcxx/src/exception.cpp",
"libcxx/src/functional.cpp",
@@ -691,6 +675,7 @@
"libcxx/src/locale.cpp",
"libcxx/src/memory.cpp",
"libcxx/src/mutex.cpp",
+ "libcxx/src/mutex_destructor.cpp",
"libcxx/src/new.cpp",
"libcxx/src/optional.cpp",
"libcxx/src/random.cpp",
@@ -718,9 +703,14 @@
"//gn/standalone/sanitizers:sanitizer_options_link_helper",
]
defines = [ "_LIBCPP_BUILDING_LIBRARY" ]
- deps = [
- ":libc++abi",
- ]
+ if ((is_linux || is_android) && (is_asan || is_tsan || is_msan)) {
+ # In {a,t,m}san configurations, operator new and operator delete will be
+ # provided by the sanitizer runtime library. Since libc++ defines these
+ # symbols with weak linkage, and the *san runtime uses strong linkage, it
+ # should technically be OK to omit this, but it's added to be explicit.
+ defines += [ "_LIBCPP_DISABLE_NEW_DELETE_DEFINITIONS" ]
+ }
+ deps = [ ":libc++abi" ]
}
} # if (use_custom_libcxx)
@@ -774,9 +764,7 @@
public_configs = [ ":benchmark_config" ]
all_dependent_configs = [ ":benchmark_config" ]
configs -= [ "//gn/standalone:extra_warnings" ]
- deps = [
- "//gn:default_deps",
- ]
+ deps = [ "//gn:default_deps" ]
}
# On Linux/Android use libbacktrace in debug builds for better stacktraces.
@@ -810,9 +798,7 @@
]
configs -= [ "//gn/standalone:extra_warnings" ]
public_configs = [ ":libbacktrace_config" ]
- deps = [
- "//gn:default_deps",
- ]
+ deps = [ "//gn:default_deps" ]
}
}
@@ -834,6 +820,7 @@
"-DSQLITE_TEMP_STORE=3",
"-DSQLITE_OMIT_LOAD_EXTENSION",
"-DSQLITE_OMIT_RANDOMNESS",
+ "-DSQLITE_OMIT_AUTOINIT",
]
}
@@ -847,17 +834,13 @@
]
configs -= [ "//gn/standalone:extra_warnings" ]
public_configs = [ ":sqlite_config" ]
- deps = [
- "//gn:default_deps",
- ]
+ deps = [ "//gn:default_deps" ]
}
source_set("sqlite_shell") {
visibility = _buildtools_visibility
testonly = true
- sources = [
- "sqlite/shell.c",
- ]
+ sources = [ "sqlite/shell.c" ]
configs -= [ "//gn/standalone:extra_warnings" ]
deps = [
":sqlite",
@@ -912,9 +895,7 @@
"-Wno-empty-body",
"-Wno-enum-conversion",
]
- deps = [
- "//gn:default_deps",
- ]
+ deps = [ "//gn:default_deps" ]
}
source_set("zlib") {
@@ -939,9 +920,7 @@
configs -= [ "//gn/standalone:extra_warnings" ]
cflags = []
public_configs = [ ":zlib_config" ]
- deps = [
- "//gn:default_deps",
- ]
+ deps = [ "//gn:default_deps" ]
}
config("zlib_config") {
@@ -973,11 +952,13 @@
]
sources = [
"android-core/base/file.cpp",
+ "android-core/base/liblog_symbols.cpp",
"android-core/base/logging.cpp",
"android-core/base/stringprintf.cpp",
"android-core/base/strings.cpp",
"android-core/base/threads.cpp",
- "android-core/demangle/Demangler.cpp",
+ "android-core/liblog/fake_log_device.cpp",
+ "android-core/liblog/logger_write.cpp",
"android-core/libunwindstack/ArmExidx.cpp",
"android-core/libunwindstack/DwarfCfa.cpp",
"android-core/libunwindstack/DwarfEhFrameWithHdr.cpp",
@@ -1003,7 +984,6 @@
"android-core/libunwindstack/RegsX86_64.cpp",
"android-core/libunwindstack/Symbols.cpp",
"android-core/libunwindstack/Unwinder.cpp",
- "android-core/libunwindstack/tests/LogFake.cpp",
]
if (current_cpu == "x86") {
sources += [ "android-core/libunwindstack/AsmGetRegsX86.S" ]
@@ -1015,10 +995,19 @@
"//gn/standalone:c++11",
"//gn/standalone:visibility_hidden",
]
+ cflags = [ "-DFAKE_LOG_DEVICE=1" ]
configs += [ "//gn/standalone:c++17" ]
public_configs = [ ":libunwindstack_config" ]
}
+config("bionic_kernel_uapi_headers") {
+ visibility = _buildtools_visibility
+ cflags = [
+ "-isystem",
+ rebase_path("bionic/libc/kernel", root_build_dir),
+ ]
+}
+
config("jsoncpp_config") {
visibility = _buildtools_visibility
cflags = [
@@ -1041,9 +1030,7 @@
]
configs -= [ "//gn/standalone:extra_warnings" ]
public_configs = [ ":jsoncpp_config" ]
- deps = [
- "//gn:default_deps",
- ]
+ deps = [ "//gn:default_deps" ]
}
config("linenoise_config") {
@@ -1066,9 +1053,7 @@
configs -= [ "//gn/standalone:extra_warnings" ]
public_configs = [ ":linenoise_config" ]
cflags = [ "-Wno-tautological-unsigned-zero-compare" ]
- deps = [
- "//gn:default_deps",
- ]
+ deps = [ "//gn:default_deps" ]
}
if (use_libfuzzer) {
@@ -1103,8 +1088,6 @@
"libfuzzer/FuzzerUtilPosix.cpp",
"libfuzzer/FuzzerUtilWindows.cpp",
]
- deps = [
- "//gn:default_deps",
- ]
+ deps = [ "//gn:default_deps" ]
}
}
diff --git a/docs/java-hprof.md b/docs/java-hprof.md
new file mode 100644
index 0000000..8a3e815
--- /dev/null
+++ b/docs/java-hprof.md
@@ -0,0 +1,52 @@
+# Java Heap Profiling
+
+**Java Heap Profiling requires Android 11.**
+
+Java Heap Profiling allows you to capture a snapshot of the memory use of
+objects managed by ART (Android RunTime). This allows to debug situations
+where a lot of memory is used on the managed heap.
+
+## Quickstart
+
+To grab a profile from your device, run the following command, substituting
+`YOUR_APP_NAME` with the name of the app you want to profile.
+
+```
+ echo 'buffers {
+ size_kb: 100024
+ fill_policy: RING_BUFFER
+}
+
+data_sources {
+ config {
+ name: "android.java_hprof"
+ java_hprof_config {
+ process_cmdline: "YOUR_APP_NAME"
+ }
+ }
+}
+
+duration_ms: 10000
+write_into_file: true
+' | adb shell perfetto -c - --out /data/misc/perfetto-traces/profile --txt
+```
+
+Then, pull the data onto your machine.
+
+```
+adb pull /data/misc/perfetto-traces/profile some/path
+```
+
+## Viewing the data
+
+Upload the trace to the [Perfetto UI](https://ui.perfetto.dev) and click on
+diamond marker that shows.
+
+This will present a flamegraph of the memory attributed to the shortest path
+to a garbage-collection root. In general an object is reachable by many paths,
+we only show the shortest as that reduces the complexity of the data displayed
+and is generally the highest-signal.
+
+We aggregate the paths per class name, so if there are two `Foo` objects that
+each retain a `String`, we will show one element for `String` as a child of
+one `Foo`.
diff --git a/docs/metrics.md b/docs/metrics.md
index 6f4079b..27e9c0a 100644
--- a/docs/metrics.md
+++ b/docs/metrics.md
@@ -117,7 +117,6 @@
gives:
```protobuf
syntax = "proto2";
-option optimize_for = LITE_RUNTIME;
package perfetto.protos;
diff --git a/docs/toc.md b/docs/toc.md
index 3aac647..ddc2992 100644
--- a/docs/toc.md
+++ b/docs/toc.md
@@ -8,6 +8,7 @@
* [Advanced trace config](trace-config.md)
* [Running in detached mode](detached-mode.md)
* [Native Heap Profiling](heapprofd.md)
+ * [Java Heap Profiling](java-hprof.md)
* Trace analysis
* [Trace processor](trace-processor.md)
* [Trace-based metrics](metrics.md)
diff --git a/docs/trace-processor.md b/docs/trace-processor.md
index cea8846..532056b 100644
--- a/docs/trace-processor.md
+++ b/docs/trace-processor.md
@@ -8,8 +8,10 @@
through SQL queries. The trace processor is used:
* By the [Perfetto UI](https://ui.perfetto.dev/), in the form of a
Web Assembly module.
-* Standalone, using the `trace_processor_shell` target
- (`ninja -C out/xxx trace_processor_shell`).
+* Standalone:
+ * using the [prebuilt](http://get.perfetto.dev/trace_processor) binaries.
+ * using the `trace_processor_shell` target from source
+ (`ninja -C out/xxx trace_processor_shell`).
* In internal pipelines for batch processing.
Supported input formats:
diff --git a/gn/BUILD.gn b/gn/BUILD.gn
index cb35cd0..b00f447 100644
--- a/gn/BUILD.gn
+++ b/gn/BUILD.gn
@@ -85,6 +85,7 @@
"PERFETTO_TP_JSON_IMPORT=$enable_perfetto_trace_processor_json_import",
"PERFETTO_TP_FUCHSIA=$enable_perfetto_trace_processor_fuchsia",
"PERFETTO_LOCAL_SYMBOLIZER=$perfetto_local_symbolizer",
+ "PERFETTO_ZLIB=$enable_perfetto_zlib",
]
rel_out_path = rebase_path(gen_header_path, "$root_build_dir")
@@ -95,18 +96,14 @@
"{{response_file_name}}",
]
- outputs = [
- gen_header_path,
- ]
+ outputs = [ gen_header_path ]
}
# All targets should depend on this target to inherit the right flags and
# include directories.
group("default_deps") {
public_configs = [ ":default_config" ]
- deps = [
- ":gen_buildflags",
- ]
+ deps = [ ":gen_buildflags" ]
if (perfetto_build_standalone) {
public_deps = [
"//gn/standalone/libc++:deps",
@@ -138,6 +135,12 @@
# For perfetto_build_flags.h
buildflag_gen_dir_,
+
+ # For generated files (proto libraries etc). We add the directory here
+ # because we stop propagation of the configs for individual proto libraries
+ # to avoid duplicate include directory command line flags in compiler
+ # invocations, see proto_library.gni, crbug.com/1043279, crbug.com/gn/142.
+ "$root_gen_dir/$perfetto_root_path",
]
}
@@ -177,33 +180,25 @@
testonly = true
if (perfetto_root_path == "//") {
- public_deps = [
- "//buildtools:gtest_main",
- ]
+ public_deps = [ "//buildtools:gtest_main" ]
} else if (build_with_chromium) {
- public_deps = [
- "//base/test:run_all_unittests",
- ]
+ public_deps = [ "//base/test:run_all_unittests" ]
} else {
- public_deps = [
- "//testing/gtest:gtest_main",
- ]
+ public_deps = [ "//testing/gtest:gtest_main" ]
}
}
# Full protobuf is just for host tools .No binary shipped on device should
# depend on this.
whitelisted_protobuf_full_deps = [
- "../tools/*",
"../src/ipc/protoc_plugin:*",
"../src/protozero/protoc_plugin:*",
"../src/trace_processor:trace_processor_shell",
+ "../tools/*",
]
group("protoc") {
- public_deps = [
- "${perfetto_protobuf_target_prefix}:protoc($host_toolchain)",
- ]
+ public_deps = [ "${perfetto_protobuf_target_prefix}:protoc($host_toolchain)" ]
}
# protoc compiler library, it's used for building protoc plugins and by
@@ -211,25 +206,19 @@
group("protoc_lib") {
visibility = whitelisted_protobuf_full_deps
if (current_toolchain == host_toolchain) {
- public_deps = [
- "${perfetto_protobuf_target_prefix}:protoc_lib",
- ]
+ public_deps = [ "${perfetto_protobuf_target_prefix}:protoc_lib" ]
}
}
group("protobuf_full") {
visibility = whitelisted_protobuf_full_deps
if (current_toolchain == host_toolchain) {
- public_deps = [
- "${perfetto_protobuf_target_prefix}:protobuf_full",
- ]
+ public_deps = [ "${perfetto_protobuf_target_prefix}:protobuf_full" ]
}
}
group("protobuf_lite") {
- public_deps = [
- "${perfetto_protobuf_target_prefix}:protobuf_lite",
- ]
+ public_deps = [ "${perfetto_protobuf_target_prefix}:protobuf_lite" ]
}
# The Google C++ Benchmark library.
@@ -237,9 +226,7 @@
if (enable_perfetto_benchmarks) {
group("benchmark") {
testonly = true
- public_deps = [
- "//buildtools:benchmark",
- ]
+ public_deps = [ "//buildtools:benchmark" ]
}
}
@@ -247,22 +234,18 @@
# standalone debug builds.
if (perfetto_build_standalone && (is_linux || is_android)) {
group("libbacktrace") {
- public_deps = [
- "//buildtools:libbacktrace",
- ]
+ public_deps = [ "//buildtools:libbacktrace" ]
}
}
-group("sqlite") {
- if (perfetto_root_path == "//") {
- public_deps = [
- "//buildtools:sqlite",
- ]
- } else {
- public_deps = [
- "//third_party/sqlite:sqlite",
- ]
- public_configs = [ ":sqlite_third_party_include_path" ]
+if (enable_perfetto_trace_processor_sqlite) {
+ group("sqlite") {
+ if (perfetto_root_path == "//") {
+ public_deps = [ "//buildtools:sqlite" ]
+ } else {
+ public_deps = [ "//third_party/sqlite:sqlite" ]
+ public_configs = [ ":sqlite_third_party_include_path" ]
+ }
}
}
@@ -274,13 +257,9 @@
group("jsoncpp") {
if (perfetto_root_path == "//") {
public_configs = [ "//buildtools:jsoncpp_config" ]
- public_deps = [
- "//buildtools:jsoncpp",
- ]
+ public_deps = [ "//buildtools:jsoncpp" ]
} else {
- public_deps = [
- "//third_party/jsoncpp:jsoncpp",
- ]
+ public_deps = [ "//third_party/jsoncpp:jsoncpp" ]
}
}
}
@@ -289,35 +268,34 @@
# Used by the trace_processor_shell for REPL history.
# Only available in standalone builds.
group("linenoise") {
- public_deps = [
- "//buildtools:linenoise",
- ]
+ public_deps = [ "//buildtools:linenoise" ]
}
} # if (enable_perfetto_trace_processor_linenoise)
# Only used by src/profiling in standalone and android builds.
-if (enable_perfetto_heapprofd) {
+if (enable_perfetto_heapprofd || enable_perfetto_traced_perf) {
group("libunwindstack") {
public_configs = [ "//buildtools:libunwindstack_config" ]
- public_deps = [
- "//buildtools:libunwindstack",
- ]
+ public_deps = [ "//buildtools:libunwindstack" ]
+ }
+}
+
+# Used by src/profiling/perf for perf_regs.h.
+if (enable_perfetto_traced_perf) {
+ group("bionic_kernel_uapi_headers") {
+ public_configs = [ "//buildtools:bionic_kernel_uapi_headers" ]
}
}
# Zlib is used both by trace_processor and by perfetto_cmd.
-if (enable_perfetto_trace_processor || enable_perfetto_platform_services) {
+if (enable_perfetto_zlib) {
group("zlib") {
if (perfetto_root_path == "//") {
public_configs = [ "//buildtools:zlib_config" ]
- public_deps = [
- "//buildtools:zlib",
- ]
+ public_deps = [ "//buildtools:zlib" ]
} else {
public_configs = [ "//third_party/zlib:zlib_config" ]
- public_deps = [
- "//third_party/zlib",
- ]
+ public_deps = [ "//third_party/zlib" ]
}
}
}
@@ -326,8 +304,6 @@
if (enable_perfetto_fuzzers && use_libfuzzer) {
group("libfuzzer") {
assert(perfetto_root_path == "//")
- public_deps = [
- "//buildtools:libfuzzer",
- ]
+ public_deps = [ "//buildtools:libfuzzer" ]
}
}
diff --git a/gn/perfetto.gni b/gn/perfetto.gni
index b479435..e6ed051 100644
--- a/gn/perfetto.gni
+++ b/gn/perfetto.gni
@@ -66,6 +66,10 @@
build_with_chromium = false
}
+if (!defined(is_nacl)) {
+ is_nacl = false
+}
+
declare_args() {
# The Android blueprint file generator set this to true (as well as
# is_perfetto_build_generator). This is just about being built in the
@@ -135,7 +139,7 @@
# system backend in the client library.
# This includes building things that rely on POSIX sockets, this places
# limitations on the supported operating systems.
- enable_perfetto_ipc = (is_android || is_linux || is_mac) &&
+ enable_perfetto_ipc = !is_win && !is_fuchsia && !is_nacl &&
(perfetto_build_standalone ||
perfetto_build_with_android || build_with_chromium)
@@ -149,7 +153,11 @@
# Build the perf event profiler (traced_perf).
# TODO(b/144281346): under development.
- enable_perfetto_traced_perf = perfetto_build_with_android
+ # TODO(rsavitski): figure out how to make the android-core dependencies build
+ # under gcc (_Atomic and other issues).
+ enable_perfetto_traced_perf =
+ perfetto_build_with_android ||
+ (perfetto_build_standalone && is_clang && is_linux)
# The Trace Processor: offline analytical engine to process traces and compute
# metrics using a SQL engine.
@@ -200,6 +208,11 @@
perfetto_verbose_logs_enabled =
!build_with_chromium || perfetto_force_dlog == "on"
+ # Enables the SQL query layer of trace processor.
+ enable_perfetto_trace_processor_sqlite =
+ enable_perfetto_trace_processor &&
+ (build_with_chromium || !perfetto_build_with_embedder)
+
# Enables the optional SQLite percentile module.
enable_perfetto_trace_processor_percentile =
enable_perfetto_trace_processor && perfetto_build_standalone
@@ -223,6 +236,11 @@
# Further per-OS conditionals are applied in gn/BUILD.gn.
enable_perfetto_trace_processor_httpd =
enable_perfetto_trace_processor && perfetto_build_standalone
+
+ # Enables Zlib support. This is used both by the "perfetto" cmdline client
+ # (for compressing traces) and by trace processor (for compressed traces).
+ enable_perfetto_zlib =
+ enable_perfetto_trace_processor || enable_perfetto_platform_services
}
declare_args() {
@@ -232,10 +250,12 @@
!(build_with_chromium && is_android)
# Enables the trace_to_text tool.
- enable_perfetto_tools_trace_to_text = enable_perfetto_tools
+ enable_perfetto_tools_trace_to_text =
+ enable_perfetto_tools && enable_perfetto_trace_processor_sqlite
# Allows to build the UI (TypeScript/ HTML / WASM)
- enable_perfetto_ui = perfetto_build_standalone
+ enable_perfetto_ui =
+ perfetto_build_standalone && enable_perfetto_trace_processor_sqlite
}
# +---------------------------------------------------------------------------+
diff --git a/gn/perfetto_benchmarks.gni b/gn/perfetto_benchmarks.gni
index 122c6ff..2abd944 100644
--- a/gn/perfetto_benchmarks.gni
+++ b/gn/perfetto_benchmarks.gni
@@ -20,7 +20,8 @@
"src/traced/probes/ftrace:benchmarks",
"src/trace_processor/containers:benchmarks",
"src/trace_processor/tables:benchmarks",
- "src/tracing:benchmarks",
+ "src/tracing/core:benchmarks",
+ "src/traced/probes/ftrace/kallsyms:benchmarks",
"test:benchmark_main",
"test:end_to_end_benchmarks",
]
diff --git a/gn/perfetto_fuzzers.gni b/gn/perfetto_fuzzers.gni
index a82b74f..0a5dbfa 100644
--- a/gn/perfetto_fuzzers.gni
+++ b/gn/perfetto_fuzzers.gni
@@ -18,7 +18,7 @@
"gn:default_deps",
"src/ipc:buffered_frame_deserializer_fuzzer",
"src/protozero:protozero_decoder_fuzzer",
- "src/tracing:packet_stream_validator_fuzzer",
+ "src/tracing/core:packet_stream_validator_fuzzer",
"src/trace_processor:trace_processor_fuzzer",
"src/traced/probes/ftrace:cpu_reader_fuzzer",
"test:end_to_end_shared_memory_fuzzer",
diff --git a/gn/perfetto_host_executable.gni b/gn/perfetto_host_executable.gni
index 55edc9a..1d12d92 100644
--- a/gn/perfetto_host_executable.gni
+++ b/gn/perfetto_host_executable.gni
@@ -36,27 +36,19 @@
# (See crbug.com/1002599).
group(target_name) {
testonly = _testonly
- deps = [
- _host_target,
- ]
+ deps = [ _host_target ]
}
} else {
copy(target_name) {
testonly = _testonly
- deps = [
- _host_target,
- ]
+ deps = [ _host_target ]
_host_out_dir = get_label_info(_host_target, "root_out_dir")
_extension = ""
if (host_os == "win") {
_extension = ".exe"
}
- sources = [
- "$_host_out_dir/$target_name${_extension}",
- ]
- outputs = [
- "$root_out_dir/$target_name${_extension}",
- ]
+ sources = [ "$_host_out_dir/$target_name${_extension}" ]
+ outputs = [ "$root_out_dir/$target_name${_extension}" ]
}
}
}
diff --git a/gn/perfetto_integrationtests.gni b/gn/perfetto_integrationtests.gni
index 19b5189..d2b0181 100644
--- a/gn/perfetto_integrationtests.gni
+++ b/gn/perfetto_integrationtests.gni
@@ -17,7 +17,7 @@
perfetto_integrationtests_targets = [
"gn:default_deps",
"gn:gtest_main",
- "src/tracing:client_api_integrationtests",
+ "src/tracing/test:client_api_integrationtests",
]
if (enable_perfetto_platform_services) {
diff --git a/gn/perfetto_unittests.gni b/gn/perfetto_unittests.gni
index ead0c8b..84467e6 100644
--- a/gn/perfetto_unittests.gni
+++ b/gn/perfetto_unittests.gni
@@ -19,10 +19,14 @@
"gn:gtest_main",
"src/base:unittests",
"src/protozero:unittests",
- "src/tracing:unittests",
+ "src/tracing/core:unittests",
"src/profiling:unittests",
]
+if (enable_perfetto_ipc) {
+ perfetto_unittests_targets += [ "src/tracing/test:tracing_integration_test" ]
+}
+
if (enable_perfetto_tools && current_toolchain == host_toolchain) {
perfetto_unittests_targets += [ "tools/ftrace_proto_gen:unittests" ]
}
@@ -36,7 +40,10 @@
}
if (enable_perfetto_ipc) {
- perfetto_unittests_targets += [ "src/ipc:unittests" ]
+ perfetto_unittests_targets += [
+ "src/tracing/ipc:unittests",
+ "src/ipc:unittests",
+ ]
}
if (enable_perfetto_platform_services) {
@@ -45,6 +52,7 @@
"src/traced/probes:unittests",
"src/traced/probes/filesystem:unittests",
"src/traced/probes/ftrace:unittests",
+ "src/traced/probes/ftrace/kallsyms:unittests",
"src/traced/service:unittests",
]
}
@@ -61,8 +69,9 @@
}
if (enable_perfetto_trace_processor) {
- perfetto_unittests_targets += [
- "src/trace_processor:unittests",
- "src/trace_processor/metrics:unittests",
- ]
+ perfetto_unittests_targets += [ "src/trace_processor:unittests" ]
+
+ if (enable_perfetto_trace_processor_sqlite) {
+ perfetto_unittests_targets += [ "src/trace_processor/metrics:unittests" ]
+ }
}
diff --git a/gn/proto_library.gni b/gn/proto_library.gni
index 1a59de7..d92c669 100644
--- a/gn/proto_library.gni
+++ b/gn/proto_library.gni
@@ -90,6 +90,7 @@
"testonly",
"visibility",
"generate_descriptor",
+ "propagate_imports_configs",
])
}
}
@@ -133,6 +134,7 @@
"testonly",
"visibility",
"generate_descriptor",
+ "propagate_imports_configs",
])
}
}
@@ -147,7 +149,8 @@
"$perfetto_root_path/src/ipc/protoc_plugin:ipc_plugin"
generator_plugin_suffix = ".ipc"
deps = [
- "$perfetto_root_path/src/ipc",
+ "$perfetto_root_path/gn:default_deps",
+ "$perfetto_root_path/src/ipc:common",
]
if (defined(invoker.deps)) {
deps += invoker.deps
@@ -163,6 +166,7 @@
"sources",
"testonly",
"visibility",
+ "propagate_imports_configs",
])
}
}
@@ -193,6 +197,11 @@
]
expansion_token = "@TYPE@"
+ # gn:public_config propagates the gen dir as include directory. We
+ # disable the proto_library's public_config to avoid duplicate include
+ # directory command line flags (crbug.com/1043279, crbug.com/gn/142).
+ propagate_imports_configs_ = false
+
foreach(gen_type, proto_generators) {
target_name_ = string_replace(target_name, expansion_token, gen_type)
@@ -210,6 +219,7 @@
proto_out_dir = proto_path
generator_plugin_options = "wrapper_namespace=pbzero"
deps = deps_
+ propagate_imports_configs = propagate_imports_configs_
forward_variables_from(invoker, vars_to_forward)
}
} else if (gen_type == "cpp") {
@@ -218,6 +228,7 @@
proto_out_dir = proto_path
generator_plugin_options = "wrapper_namespace=gen"
deps = deps_
+ propagate_imports_configs = propagate_imports_configs_
forward_variables_from(invoker, vars_to_forward)
}
} else if (gen_type == "ipc") {
@@ -227,6 +238,7 @@
proto_out_dir = proto_path
generator_plugin_options = "wrapper_namespace=gen"
deps = deps_ + [ ":$cpp_target_name_" ]
+ propagate_imports_configs = propagate_imports_configs_
forward_variables_from(invoker, vars_to_forward)
}
} else if (gen_type == "lite") {
@@ -235,6 +247,8 @@
proto_out_dir = proto_path
generate_python = false
deps = deps_
+ cc_generator_options = "lite=true:"
+ propagate_imports_configs = propagate_imports_configs_
forward_variables_from(invoker, vars_to_forward)
}
} else if (gen_type == "descriptor") {
@@ -247,6 +261,9 @@
deps = deps_
forward_variables_from(invoker, vars_to_forward)
}
+
+ # Not needed for descriptor proto_library target.
+ not_needed([ "propagate_imports_configs_" ])
} else {
assert(false, "Invalid 'proto_generators' value.")
}
diff --git a/gn/standalone/BUILD.gn b/gn/standalone/BUILD.gn
index 0c77eca..387e258 100644
--- a/gn/standalone/BUILD.gn
+++ b/gn/standalone/BUILD.gn
@@ -16,12 +16,28 @@
import("//gn/standalone/sanitizers/sanitizers.gni")
import("//gn/standalone/wasm.gni")
+# These warnings have been introduced with the newest version of clang (only in
+# the hermetic build) and are enabled just with -Werror.
+# TODO(primiano): we should look into Wimplicit-int-float-conversion. Seems
+# failing mostly in tests though.
+hermetic_clang_suppressions = [
+ "-Wno-c99-designator",
+ "-Wno-implicit-int-float-conversion",
+]
+
config("extra_warnings") {
cflags = [
"-Wall",
"-Wextra",
+ "-Wpedantic",
]
+ # Disable variadic macro warning as we make extensive use of them in trace
+ # processor and client API.
+ if (is_clang) {
+ cflags += [ "-Wno-gnu-zero-variadic-macro-arguments" ]
+ }
+
# Disable Weverything on fuzzers to avoid breakages when new versions of clang
# are rolled into OSS-fuzz.
if (is_clang && !is_fuzzer) {
@@ -32,7 +48,6 @@
"-Wno-disabled-macro-expansion",
"-Wno-gnu-include-next",
"-Wno-gnu-statement-expression",
- "-Wno-gnu-zero-variadic-macro-arguments",
"-Wno-padded",
"-Wno-reserved-id-macro",
"-Wno-unknown-sanitizers",
@@ -90,6 +105,12 @@
]
}
+ if (is_hermetic_clang && is_linux && !is_wasm) {
+ cflags += hermetic_clang_suppressions
+ } else {
+ not_needed([ "hermetic_clang_suppressions" ])
+ }
+
if (is_lto) {
cflags += [ "-flto=full" ]
ldflags += [ "-flto=full" ]
@@ -262,8 +283,6 @@
generated_header = "${root_gen_dir}/perfetto_version.gen.h"
args = [ rebase_path(generated_header, root_build_dir) ]
inputs = []
- outputs = [
- generated_header,
- ]
+ outputs = [ generated_header ]
public_configs = [ ":gen_include_path" ]
}
diff --git a/gn/standalone/BUILDCONFIG.gn b/gn/standalone/BUILDCONFIG.gn
index d980a05..3668c0f 100644
--- a/gn/standalone/BUILDCONFIG.gn
+++ b/gn/standalone/BUILDCONFIG.gn
@@ -36,10 +36,11 @@
is_linux_host = host_os == "linux"
is_mac = current_os == "mac"
-# Building with Windows/Fuchsia is currently only supported in the Chromium
+# Building with Windows/Fuchsia/nacl is currently only supported in the Chromium
# tree so always set this to false.
is_win = false
is_fuchsia = false
+is_nacl = false
if (target_cpu == "") {
target_cpu = host_cpu
diff --git a/gn/standalone/libc++/BUILD.gn b/gn/standalone/libc++/BUILD.gn
index a8ccba1..8590f85 100644
--- a/gn/standalone/libc++/BUILD.gn
+++ b/gn/standalone/libc++/BUILD.gn
@@ -42,8 +42,6 @@
group("deps") {
if (use_custom_libcxx) {
- public_deps = [
- "//buildtools:libc++",
- ]
+ public_deps = [ "//buildtools:libc++" ]
}
}
diff --git a/gn/standalone/proto_library.gni b/gn/standalone/proto_library.gni
index 0180b2b..212ea42 100644
--- a/gn/standalone/proto_library.gni
+++ b/gn/standalone/proto_library.gni
@@ -138,9 +138,13 @@
rebase_path(proto_in_dir, root_build_dir),
]
if (generate_cc) {
+ cc_generator_options_ = ""
+ if (defined(invoker.cc_generator_options)) {
+ cc_generator_options_ = invoker.cc_generator_options
+ }
args += [
"--cpp_out",
- rel_cc_out_dir,
+ cc_generator_options_ + rel_cc_out_dir,
]
}
if (generate_descriptor != "") {
@@ -170,13 +174,9 @@
args += rebase_path(proto_sources, root_build_dir)
- inputs = [
- protoc_path,
- ]
+ inputs = [ protoc_path ]
- deps = [
- protoc_label,
- ]
+ deps = [ protoc_label ]
# TODO(hjd): Avoid adding to deps here this.
# When we generate BUILD files we need find the transitive proto,
@@ -226,16 +226,24 @@
":$config_name",
]
+ # By default, propagate the config for |include_dirs| to dependent
+ # targets, so that public imports can be resolved to corresponding header
+ # files. In some cases, the embedder target handles include directory
+ # propagation itself, e.g. via a common config.
+ propagate_imports_configs = !defined(invoker.propagate_imports_configs) ||
+ invoker.propagate_imports_configs
+ if (propagate_imports_configs) {
+ public_configs += [ ":$config_name" ]
+ } else {
+ configs += [ ":$config_name" ]
+ }
+
# Use protobuf_full only for tests.
if (defined(invoker.use_protobuf_full) &&
invoker.use_protobuf_full == true) {
- deps = [
- "//gn:protobuf_full",
- ]
+ deps = [ "//gn:protobuf_full" ]
} else if (generate_cc) {
- deps = [
- "//gn:protobuf_lite",
- ]
+ deps = [ "//gn:protobuf_lite" ]
} else {
deps = []
}
diff --git a/gn/standalone/sanitizers/BUILD.gn b/gn/standalone/sanitizers/BUILD.gn
index 8a5253d..c015d3e 100644
--- a/gn/standalone/sanitizers/BUILD.gn
+++ b/gn/standalone/sanitizers/BUILD.gn
@@ -20,21 +20,15 @@
if (using_sanitizer) {
public_configs = [ ":sanitizers_ldflags" ]
if (is_android && sanitizer_lib != "" && !sanitizer_lib_dir_is_static) {
- deps = [
- ":copy_sanitizer_lib",
- ]
+ deps = [ ":copy_sanitizer_lib" ]
}
}
}
if (is_android && sanitizer_lib != "" && !sanitizer_lib_dir_is_static) {
copy("copy_sanitizer_lib") {
- sources = [
- "${sanitizer_lib_dir}/lib${sanitizer_lib}.so",
- ]
- outputs = [
- "${root_out_dir}/sanitizer_libs/lib${sanitizer_lib}.so",
- ]
+ sources = [ "${sanitizer_lib_dir}/lib${sanitizer_lib}.so" ]
+ outputs = [ "${root_out_dir}/sanitizer_libs/lib${sanitizer_lib}.so" ]
}
}
diff --git a/gn/standalone/toolchain/BUILD.gn b/gn/standalone/toolchain/BUILD.gn
index 417d7f4..264d27f 100644
--- a/gn/standalone/toolchain/BUILD.gn
+++ b/gn/standalone/toolchain/BUILD.gn
@@ -146,9 +146,8 @@
depfile = "{{output}}.d"
command = "$cc_wrapper $cc -MMD -MF $depfile {{defines}} {{include_dirs}} {{cflags}} {{cflags_c}} ${extra_cflags} -c {{source}} -o {{output}}"
depsformat = "gcc"
- outputs = [
- "{{source_out_dir}}/{{target_output_name}}.{{source_name_part}}.o",
- ]
+ outputs =
+ [ "{{source_out_dir}}/{{target_output_name}}.{{source_name_part}}.o" ]
description = "compile {{source}}"
}
@@ -156,9 +155,8 @@
depfile = "{{output}}.d"
command = "$cc_wrapper $cxx -MMD -MF $depfile {{defines}} {{include_dirs}} {{cflags}} {{cflags_cc}} ${extra_cflags} ${extra_cxxflags} -c {{source}} -o {{output}}"
depsformat = "gcc"
- outputs = [
- "{{source_out_dir}}/{{target_output_name}}.{{source_name_part}}.o",
- ]
+ outputs =
+ [ "{{source_out_dir}}/{{target_output_name}}.{{source_name_part}}.o" ]
description = "compile {{source}}"
}
@@ -166,9 +164,8 @@
depfile = "{{output}}.d"
command = "$cc_wrapper $cc -MMD -MF $depfile {{defines}} {{include_dirs}} {{asmflags}} -c {{source}} -o {{output}}"
depsformat = "gcc"
- outputs = [
- "{{source_out_dir}}/{{target_output_name}}.{{source_name_part}}.o",
- ]
+ outputs =
+ [ "{{source_out_dir}}/{{target_output_name}}.{{source_name_part}}.o" ]
description = "assemble {{source}}"
}
@@ -181,9 +178,8 @@
rspfile_content = "{{inputs}}"
command = "rm -f {{output}} && $ar rcsD {{output}} @$rspfile"
}
- outputs = [
- "{{root_out_dir}}/{{target_output_name}}{{output_extension}}",
- ]
+ outputs =
+ [ "{{root_out_dir}}/{{target_output_name}}{{output_extension}}" ]
default_output_extension = ".a"
output_prefix = "lib"
description = "link {{output}}"
@@ -198,9 +194,7 @@
}
command = "$cc_wrapper $cxx $ld_arg -shared {{ldflags}} ${extra_ldflags} {{inputs}} {{solibs}} {{libs}} $rpath -o {{output}}"
- outputs = [
- "{{root_out_dir}}/$soname",
- ]
+ outputs = [ "{{root_out_dir}}/$soname" ]
output_prefix = "lib"
default_output_extension = ".so"
description = "link {{output}}"
@@ -208,9 +202,8 @@
tool("link") {
command = "$cc_wrapper $cxx $ld_arg {{ldflags}} ${extra_ldflags} {{inputs}} {{solibs}} {{libs}} -o {{output}}"
- outputs = [
- "{{root_out_dir}}/{{target_output_name}}{{output_extension}}",
- ]
+ outputs =
+ [ "{{root_out_dir}}/{{target_output_name}}{{output_extension}}" ]
description = "link {{output}}"
}
diff --git a/gn/standalone/toolchain/linux_find_llvm.py b/gn/standalone/toolchain/linux_find_llvm.py
index 858185c..3a957fe 100644
--- a/gn/standalone/toolchain/linux_find_llvm.py
+++ b/gn/standalone/toolchain/linux_find_llvm.py
@@ -22,7 +22,7 @@
for clang in ('clang', 'clang-3.8', 'clang-3.5'):
if subprocess.call(['which', clang], stdout=devnull, stderr=devnull) != 0:
continue
- res = subprocess.check_output([clang, '-print-search-dirs'])
+ res = subprocess.check_output([clang, '-print-search-dirs']).decode("utf-8")
for line in res.splitlines():
if not line.startswith('libraries:'):
continue
@@ -30,11 +30,11 @@
for lib in libs:
if '/clang/' not in lib or not os.path.isdir(lib + '/lib'):
continue
- print os.path.abspath(lib)
- print clang
- print clang.replace('clang', 'clang++')
+ print(os.path.abspath(lib))
+ print(clang)
+ print(clang.replace('clang', 'clang++'))
return 0
- print 'Could not find the LLVM lib dir'
+ print('Could not find the LLVM lib dir')
return 1
diff --git a/gn/standalone/wasm.gni b/gn/standalone/wasm.gni
index b3a6c1a..bfa46ec 100644
--- a/gn/standalone/wasm.gni
+++ b/gn/standalone/wasm.gni
@@ -116,12 +116,8 @@
# outputs also the .wasm file", so we can depend on that in copy() targets.
action("${_lib_name}.wasm") {
inputs = []
- deps = [
- ":${_lib_name}.js",
- ]
- outputs = [
- "$root_out_dir/$_lib_name.wasm",
- ]
+ deps = [ ":${_lib_name}.js" ]
+ outputs = [ "$root_out_dir/$_lib_name.wasm" ]
if (is_debug) {
outputs += [ "$root_out_dir/$_lib_name.wasm.map" ]
}
@@ -130,12 +126,8 @@
}
copy("${_lib_name}.d.ts") {
- sources = [
- "//gn/standalone/wasm_typescript_declaration.d.ts",
- ]
- outputs = [
- "$root_out_dir/$_lib_name.d.ts",
- ]
+ sources = [ "//gn/standalone/wasm_typescript_declaration.d.ts" ]
+ outputs = [ "$root_out_dir/$_lib_name.d.ts" ]
}
} else { # is_wasm
not_needed(invoker, "*")
diff --git a/gn/standalone/write_ui_dist_file_map.py b/gn/standalone/write_ui_dist_file_map.py
new file mode 100644
index 0000000..8ea5aff
--- /dev/null
+++ b/gn/standalone/write_ui_dist_file_map.py
@@ -0,0 +1,90 @@
+#!/usr/bin/env python
+# Copyright (C) 2020 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.
+""" Writes a TypeScript dict that contains SHA256s of the passed files.
+
+The output looks like this:
+{
+ hex_digest: '6c761701c5840483833ffb0bd70ae155b2b3c70e8f667c7bd1f6abc98095930',
+ files: {
+ 'frontend_bundle.js': 'sha256-2IVKK/3mEMlDdXNADyK03L1cANKbBpU+xue+vnLOcyo=',
+ 'index.html': 'sha256-ZRS1+Xh/dFZeWZi/dz8QMWg/8PYQHNdazsNX2oX8s70=',
+ ...
+ }
+}
+"""
+
+from __future__ import print_function
+
+import argparse
+import base64
+import hashlib
+import multiprocessing
+import os
+import sys
+
+from base64 import b64encode
+
+
+def hash_file(file_path):
+ hasher = hashlib.sha256()
+ with open(file_path, 'rb') as f:
+ for chunk in iter(lambda: f.read(32768), b''):
+ hasher.update(chunk)
+ return file_path, hasher.digest()
+
+
+def hash_list_hex(args):
+ hasher = hashlib.sha256()
+ for arg in args:
+ hasher.update(arg)
+ return hasher.hexdigest()
+
+
+def main():
+ parser = argparse.ArgumentParser()
+ parser.add_argument('--out', help='Path of the output file')
+ parser.add_argument(
+ '--strip', help='Strips the leading path in the generated file list')
+ parser.add_argument('file_list', nargs=argparse.REMAINDER)
+ args = parser.parse_args()
+
+ # Compute the hash of each file (in parallel).
+ pool = multiprocessing.Pool(multiprocessing.cpu_count() * 2)
+ digests = dict(pool.map(hash_file, args.file_list))
+
+ contents = '// __generated_by %s\n' % __file__
+ contents += 'export const UI_DIST_MAP = {\n'
+ contents += ' files: {\n'
+ strip = args.strip + ('' if args.strip[-1] == os.path.sep else os.path.sep)
+ for fname, digest in digests.iteritems():
+ if not fname.startswith(strip):
+ raise Exception('%s must start with %s (--strip arg)' % (fname, strip))
+ fname = fname[len(strip):]
+ # We use b64 instead of hexdigest() because it's handy for handling fetch()
+ # subresource integrity.
+ contents += ' \'%s\': \'sha256-%s\',\n' % (fname, b64encode(digest))
+ contents += ' },\n'
+
+ # Compute the hash of the all resources' hashes.
+ contents += ' hex_digest: \'%s\',\n' % hash_list_hex(digests.values())
+ contents += '};\n'
+
+ with open(args.out + '.tmp', 'w') as fout:
+ fout.write(contents)
+ os.rename(args.out + '.tmp', args.out)
+
+
+if __name__ == '__main__':
+ sys.exit(main())
diff --git a/include/README.md b/include/README.md
index 83a92f7..6edb3ca 100644
--- a/include/README.md
+++ b/include/README.md
@@ -87,8 +87,6 @@
void OnStop(const StopArgs&) override {}
};
...
- PERFETTO_DEFINE_DATA_SOURCE_STATIC_MEMBERS(MyDataSource);
- ...
perfetto::DataSourceDescriptor dsd;
dsd.set_name("my_data_source");
MyDataSource::Register(dsd);
diff --git a/include/perfetto/base/BUILD.gn b/include/perfetto/base/BUILD.gn
index e490551..85819b7 100644
--- a/include/perfetto/base/BUILD.gn
+++ b/include/perfetto/base/BUILD.gn
@@ -19,8 +19,11 @@
"build_config.h",
"compiler.h",
"export.h",
+ "flat_set.h",
"logging.h",
+ "proc_utils.h",
"task_runner.h",
+ "thread_utils.h",
"time.h",
]
}
diff --git a/include/perfetto/base/build_config.h b/include/perfetto/base/build_config.h
index bb641f5..047d897 100644
--- a/include/perfetto/base/build_config.h
+++ b/include/perfetto/base/build_config.h
@@ -31,6 +31,8 @@
#define PERFETTO_BUILDFLAG_DEFINE_PERFETTO_OS_WIN() 0
#define PERFETTO_BUILDFLAG_DEFINE_PERFETTO_OS_WASM() 0
#define PERFETTO_BUILDFLAG_DEFINE_PERFETTO_OS_FUCHSIA() 0
+#define PERFETTO_BUILDFLAG_DEFINE_PERFETTO_OS_NACL() 0
+#define PERFETTO_BUILDFLAG_DEFINE_PERFETTO_OS_IOS() 0
#elif defined(__APPLE__)
#define PERFETTO_BUILDFLAG_DEFINE_PERFETTO_OS_ANDROID() 0
#define PERFETTO_BUILDFLAG_DEFINE_PERFETTO_OS_MACOSX() 1
@@ -38,6 +40,12 @@
#define PERFETTO_BUILDFLAG_DEFINE_PERFETTO_OS_WIN() 0
#define PERFETTO_BUILDFLAG_DEFINE_PERFETTO_OS_WASM() 0
#define PERFETTO_BUILDFLAG_DEFINE_PERFETTO_OS_FUCHSIA() 0
+#define PERFETTO_BUILDFLAG_DEFINE_PERFETTO_OS_NACL() 0
+// Include TARGET_OS_IPHONE when on __APPLE__ systems.
+#include <TargetConditionals.h>
+#if defined(TARGET_OS_IPHONE) && TARGET_OS_IPHONE
+#define PERFETTO_BUILDFLAG_DEFINE_PERFETTO_OS_IOS() 1
+#endif
#elif defined(__linux__)
#define PERFETTO_BUILDFLAG_DEFINE_PERFETTO_OS_ANDROID() 0
#define PERFETTO_BUILDFLAG_DEFINE_PERFETTO_OS_MACOSX() 0
@@ -45,6 +53,8 @@
#define PERFETTO_BUILDFLAG_DEFINE_PERFETTO_OS_WIN() 0
#define PERFETTO_BUILDFLAG_DEFINE_PERFETTO_OS_WASM() 0
#define PERFETTO_BUILDFLAG_DEFINE_PERFETTO_OS_FUCHSIA() 0
+#define PERFETTO_BUILDFLAG_DEFINE_PERFETTO_OS_NACL() 0
+#define PERFETTO_BUILDFLAG_DEFINE_PERFETTO_OS_IOS() 0
#elif defined(_WIN32)
#define PERFETTO_BUILDFLAG_DEFINE_PERFETTO_OS_ANDROID() 0
#define PERFETTO_BUILDFLAG_DEFINE_PERFETTO_OS_MACOSX() 0
@@ -52,6 +62,8 @@
#define PERFETTO_BUILDFLAG_DEFINE_PERFETTO_OS_WIN() 1
#define PERFETTO_BUILDFLAG_DEFINE_PERFETTO_OS_WASM() 0
#define PERFETTO_BUILDFLAG_DEFINE_PERFETTO_OS_FUCHSIA() 0
+#define PERFETTO_BUILDFLAG_DEFINE_PERFETTO_OS_NACL() 0
+#define PERFETTO_BUILDFLAG_DEFINE_PERFETTO_OS_IOS() 0
#elif defined(__EMSCRIPTEN__)
#define PERFETTO_BUILDFLAG_DEFINE_PERFETTO_OS_ANDROID() 0
#define PERFETTO_BUILDFLAG_DEFINE_PERFETTO_OS_MACOSX() 0
@@ -59,6 +71,8 @@
#define PERFETTO_BUILDFLAG_DEFINE_PERFETTO_OS_WIN() 0
#define PERFETTO_BUILDFLAG_DEFINE_PERFETTO_OS_WASM() 1
#define PERFETTO_BUILDFLAG_DEFINE_PERFETTO_OS_FUCHSIA() 0
+#define PERFETTO_BUILDFLAG_DEFINE_PERFETTO_OS_NACL() 0
+#define PERFETTO_BUILDFLAG_DEFINE_PERFETTO_OS_IOS() 0
#elif defined(__Fuchsia__)
#define PERFETTO_BUILDFLAG_DEFINE_PERFETTO_OS_ANDROID() 0
#define PERFETTO_BUILDFLAG_DEFINE_PERFETTO_OS_MACOSX() 0
@@ -66,6 +80,17 @@
#define PERFETTO_BUILDFLAG_DEFINE_PERFETTO_OS_WIN() 0
#define PERFETTO_BUILDFLAG_DEFINE_PERFETTO_OS_WASM() 0
#define PERFETTO_BUILDFLAG_DEFINE_PERFETTO_OS_FUCHSIA() 1
+#define PERFETTO_BUILDFLAG_DEFINE_PERFETTO_OS_NACL() 0
+#define PERFETTO_BUILDFLAG_DEFINE_PERFETTO_OS_IOS() 0
+#elif defined(__native_client__)
+#define PERFETTO_BUILDFLAG_DEFINE_PERFETTO_OS_ANDROID() 0
+#define PERFETTO_BUILDFLAG_DEFINE_PERFETTO_OS_MACOSX() 0
+#define PERFETTO_BUILDFLAG_DEFINE_PERFETTO_OS_LINUX() 0
+#define PERFETTO_BUILDFLAG_DEFINE_PERFETTO_OS_WIN() 0
+#define PERFETTO_BUILDFLAG_DEFINE_PERFETTO_OS_WASM() 0
+#define PERFETTO_BUILDFLAG_DEFINE_PERFETTO_OS_FUCHSIA() 0
+#define PERFETTO_BUILDFLAG_DEFINE_PERFETTO_OS_NACL() 1
+#define PERFETTO_BUILDFLAG_DEFINE_PERFETTO_OS_IOS() 0
#else
#error OS not supported (see build_config.h)
#endif
diff --git a/include/perfetto/base/build_configs/android_tree/perfetto_build_flags.h b/include/perfetto/base/build_configs/android_tree/perfetto_build_flags.h
index 259721b..dbc68b7 100644
--- a/include/perfetto/base/build_configs/android_tree/perfetto_build_flags.h
+++ b/include/perfetto/base/build_configs/android_tree/perfetto_build_flags.h
@@ -39,6 +39,7 @@
#define PERFETTO_BUILDFLAG_DEFINE_PERFETTO_TP_JSON_IMPORT() (0)
#define PERFETTO_BUILDFLAG_DEFINE_PERFETTO_TP_FUCHSIA() (1)
#define PERFETTO_BUILDFLAG_DEFINE_PERFETTO_LOCAL_SYMBOLIZER() (PERFETTO_BUILDFLAG_DEFINE_PERFETTO_OS_LINUX())
+#define PERFETTO_BUILDFLAG_DEFINE_PERFETTO_ZLIB() (1)
// clang-format on
#endif // GEN_BUILD_CONFIG_PERFETTO_BUILD_FLAGS_H_
diff --git a/include/perfetto/base/build_configs/bazel/perfetto_build_flags.h b/include/perfetto/base/build_configs/bazel/perfetto_build_flags.h
index 7919b4d..ce91468 100644
--- a/include/perfetto/base/build_configs/bazel/perfetto_build_flags.h
+++ b/include/perfetto/base/build_configs/bazel/perfetto_build_flags.h
@@ -39,6 +39,7 @@
#define PERFETTO_BUILDFLAG_DEFINE_PERFETTO_TP_JSON_IMPORT() (1)
#define PERFETTO_BUILDFLAG_DEFINE_PERFETTO_TP_FUCHSIA() (1)
#define PERFETTO_BUILDFLAG_DEFINE_PERFETTO_LOCAL_SYMBOLIZER() (PERFETTO_BUILDFLAG_DEFINE_PERFETTO_OS_LINUX())
+#define PERFETTO_BUILDFLAG_DEFINE_PERFETTO_ZLIB() (1)
// clang-format on
#endif // GEN_BUILD_CONFIG_PERFETTO_BUILD_FLAGS_H_
diff --git a/include/perfetto/ext/base/flat_set.h b/include/perfetto/base/flat_set.h
similarity index 91%
rename from include/perfetto/ext/base/flat_set.h
rename to include/perfetto/base/flat_set.h
index e33fcf7..068ad3c 100644
--- a/include/perfetto/ext/base/flat_set.h
+++ b/include/perfetto/base/flat_set.h
@@ -14,8 +14,8 @@
* limitations under the License.
*/
-#ifndef INCLUDE_PERFETTO_EXT_BASE_FLAT_SET_H_
-#define INCLUDE_PERFETTO_EXT_BASE_FLAT_SET_H_
+#ifndef INCLUDE_PERFETTO_BASE_FLAT_SET_H_
+#define INCLUDE_PERFETTO_BASE_FLAT_SET_H_
#include <algorithm>
#include <vector>
@@ -63,14 +63,15 @@
size_t count(T value) const { return find(value) == entries_.end() ? 0 : 1; }
- void insert(T value) {
+ std::pair<iterator, bool> insert(T value) {
auto entries_end = entries_.end();
auto it = std::lower_bound(entries_.begin(), entries_end, value);
if (it != entries_end && *it == value)
- return;
+ return std::make_pair(it, false);
// If the value is not found |it| is either end() or the next item strictly
// greater than |value|. In both cases we want to insert just before that.
- entries_.insert(it, std::move(value));
+ it = entries_.insert(it, std::move(value));
+ return std::make_pair(it, true);
}
size_t erase(T value) {
@@ -96,4 +97,4 @@
} // namespace base
} // namespace perfetto
-#endif // INCLUDE_PERFETTO_EXT_BASE_FLAT_SET_H_
+#endif // INCLUDE_PERFETTO_BASE_FLAT_SET_H_
diff --git a/include/perfetto/base/logging.h b/include/perfetto/base/logging.h
index 2691438..aeebf0b 100644
--- a/include/perfetto/base/logging.h
+++ b/include/perfetto/base/logging.h
@@ -24,6 +24,9 @@
#include "perfetto/base/compiler.h"
#include "perfetto/base/export.h"
+// Ignore GCC warning about a missing argument for a variadic macro parameter.
+#pragma GCC system_header
+
// TODO(primiano): move this to base/build_config.h, turn into
// PERFETTO_BUILDFLAG(DCHECK_IS_ON) and update call sites to use that instead.
#if defined(NDEBUG) && !defined(DCHECK_ALWAYS_ON)
diff --git a/include/perfetto/ext/base/proc_utils.h b/include/perfetto/base/proc_utils.h
similarity index 90%
rename from include/perfetto/ext/base/proc_utils.h
rename to include/perfetto/base/proc_utils.h
index d5bacb9..8818ec0 100644
--- a/include/perfetto/ext/base/proc_utils.h
+++ b/include/perfetto/base/proc_utils.h
@@ -14,8 +14,8 @@
* limitations under the License.
*/
-#ifndef INCLUDE_PERFETTO_EXT_BASE_PROC_UTILS_H_
-#define INCLUDE_PERFETTO_EXT_BASE_PROC_UTILS_H_
+#ifndef INCLUDE_PERFETTO_BASE_PROC_UTILS_H_
+#define INCLUDE_PERFETTO_BASE_PROC_UTILS_H_
#include <stdint.h>
@@ -54,4 +54,4 @@
} // namespace base
} // namespace perfetto
-#endif // INCLUDE_PERFETTO_EXT_BASE_PROC_UTILS_H_
+#endif // INCLUDE_PERFETTO_BASE_PROC_UTILS_H_
diff --git a/include/perfetto/ext/base/thread_utils.h b/include/perfetto/base/thread_utils.h
similarity index 66%
rename from include/perfetto/ext/base/thread_utils.h
rename to include/perfetto/base/thread_utils.h
index 4ad1825..89da007 100644
--- a/include/perfetto/ext/base/thread_utils.h
+++ b/include/perfetto/base/thread_utils.h
@@ -14,8 +14,8 @@
* limitations under the License.
*/
-#ifndef INCLUDE_PERFETTO_EXT_BASE_THREAD_UTILS_H_
-#define INCLUDE_PERFETTO_EXT_BASE_THREAD_UTILS_H_
+#ifndef INCLUDE_PERFETTO_BASE_THREAD_UTILS_H_
+#define INCLUDE_PERFETTO_BASE_THREAD_UTILS_H_
#include <stdint.h>
@@ -38,35 +38,40 @@
namespace base {
#if PERFETTO_BUILDFLAG(PERFETTO_OS_ANDROID)
-using PlatformThreadID = pid_t;
-inline PlatformThreadID GetThreadId() {
+using PlatformThreadId = pid_t;
+inline PlatformThreadId GetThreadId() {
return gettid();
}
#elif PERFETTO_BUILDFLAG(PERFETTO_OS_LINUX)
-using PlatformThreadID = pid_t;
-inline PlatformThreadID GetThreadId() {
+using PlatformThreadId = pid_t;
+inline PlatformThreadId GetThreadId() {
return static_cast<pid_t>(syscall(__NR_gettid));
}
#elif PERFETTO_BUILDFLAG(PERFETTO_OS_FUCHSIA)
-using PlatformThreadID = zx_handle_t;
-inline PlatformThreadID GetThreadId() {
- return static_cast<pid_t>(zx_thread_self());
+using PlatformThreadId = zx_handle_t;
+inline PlatformThreadId GetThreadId() {
+ return zx_thread_self();
}
#elif PERFETTO_BUILDFLAG(PERFETTO_OS_MACOSX)
-using PlatformThreadID = uint64_t;
-inline PlatformThreadID GetThreadId() {
+using PlatformThreadId = uint64_t;
+inline PlatformThreadId GetThreadId() {
uint64_t tid;
pthread_threadid_np(nullptr, &tid);
return tid;
}
#elif PERFETTO_BUILDFLAG(PERFETTO_OS_WIN)
-using PlatformThreadID = uint64_t;
-inline PlatformThreadID GetThreadId() {
+using PlatformThreadId = uint64_t;
+inline PlatformThreadId GetThreadId() {
return static_cast<uint64_t>(GetCurrentThreadId());
}
+#elif PERFETTO_BUILDFLAG(PERFETTO_OS_NACL)
+using PlatformThreadId = pid_t;
+inline PlatformThreadId GetThreadId() {
+ return reinterpret_cast<int32_t>(pthread_self());
+}
#else // Default to pthreads in case no OS is set.
-using PlatformThreadID = pthread_t;
-inline PlatformThreadID GetThreadId() {
+using PlatformThreadId = pthread_t;
+inline PlatformThreadId GetThreadId() {
return pthread_self();
}
#endif
@@ -74,4 +79,4 @@
} // namespace base
} // namespace perfetto
-#endif // INCLUDE_PERFETTO_EXT_BASE_THREAD_UTILS_H_
+#endif // INCLUDE_PERFETTO_BASE_THREAD_UTILS_H_
diff --git a/include/perfetto/base/time.h b/include/perfetto/base/time.h
index 8c81faa..0ee6042 100644
--- a/include/perfetto/base/time.h
+++ b/include/perfetto/base/time.h
@@ -110,7 +110,25 @@
return GetWallTimeNs();
}
-#else
+#elif PERFETTO_BUILDFLAG(PERFETTO_OS_NACL)
+
+// Tracing time doesn't need to work on NaCl since its going away shortly. We
+// just need to compile on it. The only function NaCl could support is
+// GetWallTimeNs(), but to prevent false hope we leave it unimplemented.
+
+inline TimeNanos GetWallTimeNs() {
+ return TimeNanos(0);
+}
+
+inline TimeNanos GetThreadCPUTimeNs() {
+ return TimeNanos(0);
+}
+
+inline TimeNanos GetBootTimeNs() {
+ return TimeNanos(0);
+}
+
+#else // posix
constexpr clockid_t kWallTimeClockSource = CLOCK_MONOTONIC;
@@ -139,7 +157,6 @@
inline TimeNanos GetThreadCPUTimeNs() {
return GetTimeInternalNs(CLOCK_THREAD_CPUTIME_ID);
}
-
#endif
inline TimeSeconds GetBootTimeS() {
diff --git a/include/perfetto/ext/base/BUILD.gn b/include/perfetto/ext/base/BUILD.gn
index 7d76c84..052d277 100644
--- a/include/perfetto/ext/base/BUILD.gn
+++ b/include/perfetto/ext/base/BUILD.gn
@@ -20,7 +20,6 @@
"container_annotations.h",
"event_fd.h",
"file_utils.h",
- "flat_set.h",
"hash.h",
"lookup_set.h",
"metatrace.h",
@@ -29,7 +28,6 @@
"optional.h",
"paged_memory.h",
"pipe.h",
- "proc_utils.h",
"scoped_file.h",
"small_set.h",
"string_splitter.h",
@@ -40,7 +38,6 @@
"thread_annotations.h",
"thread_checker.h",
"thread_task_runner.h",
- "thread_utils.h",
"unix_task_runner.h",
"utils.h",
"uuid.h",
@@ -54,7 +51,5 @@
sources += [ "unix_socket.h" ]
}
public_configs = [ "../../../../gn:asan_instrumentation" ]
- public_deps = [
- "../../base",
- ]
+ public_deps = [ "../../base" ]
}
diff --git a/include/perfetto/ext/base/metatrace.h b/include/perfetto/ext/base/metatrace.h
index 2c587c3..f5eb057 100644
--- a/include/perfetto/ext/base/metatrace.h
+++ b/include/perfetto/ext/base/metatrace.h
@@ -23,10 +23,10 @@
#include <string>
#include "perfetto/base/logging.h"
+#include "perfetto/base/thread_utils.h"
#include "perfetto/base/time.h"
#include "perfetto/ext/base/metatrace_events.h"
#include "perfetto/ext/base/thread_annotations.h"
-#include "perfetto/ext/base/thread_utils.h"
#include "perfetto/ext/base/utils.h"
// A facility to trace execution of the perfetto codebase itself.
diff --git a/include/perfetto/ext/base/metatrace_events.h b/include/perfetto/ext/base/metatrace_events.h
index 4f62244..e3cfb77 100644
--- a/include/perfetto/ext/base/metatrace_events.h
+++ b/include/perfetto/ext/base/metatrace_events.h
@@ -59,7 +59,8 @@
F(TRACE_WRITER_COMMIT_STARTUP_WRITER_BATCH), \
F(FTRACE_READ_TICK), \
F(FTRACE_CPU_READ_CYCLE), \
- F(FTRACE_CPU_READ_BATCH)
+ F(FTRACE_CPU_READ_BATCH), \
+ F(KALLSYMS_PARSE)
// Append only, see above.
//
diff --git a/include/perfetto/ext/base/string_writer.h b/include/perfetto/ext/base/string_writer.h
index 681324f..428b17e 100644
--- a/include/perfetto/ext/base/string_writer.h
+++ b/include/perfetto/ext/base/string_writer.h
@@ -19,8 +19,9 @@
#include <inttypes.h>
#include <math.h>
-#include <stdlib.h>
#include <string.h>
+#include <cmath>
+#include <cstdlib>
#include <limits>
#include "perfetto/base/logging.h"
@@ -69,7 +70,7 @@
// digits of the integer is less than |padding|.
template <char padchar, uint64_t padding>
void AppendPaddedInt(int64_t sign_value) {
- const bool negate = signbit(static_cast<double>(sign_value));
+ const bool negate = std::signbit(static_cast<double>(sign_value));
uint64_t absolute_value = static_cast<uint64_t>(std::abs(sign_value));
AppendPaddedInt<padchar, padding>(absolute_value, negate);
}
diff --git a/include/perfetto/ext/base/thread_task_runner.h b/include/perfetto/ext/base/thread_task_runner.h
index fac4553..6579fa5 100644
--- a/include/perfetto/ext/base/thread_task_runner.h
+++ b/include/perfetto/ext/base/thread_task_runner.h
@@ -34,7 +34,9 @@
//
class ThreadTaskRunner {
public:
- static ThreadTaskRunner CreateAndStart() { return ThreadTaskRunner(); }
+ static ThreadTaskRunner CreateAndStart(const std::string& name = "") {
+ return ThreadTaskRunner(name);
+ }
ThreadTaskRunner(const ThreadTaskRunner&) = delete;
ThreadTaskRunner& operator=(const ThreadTaskRunner&) = delete;
@@ -43,6 +45,14 @@
ThreadTaskRunner& operator=(ThreadTaskRunner&&);
~ThreadTaskRunner();
+ // Executes the given function on the task runner thread and blocks the caller
+ // thread until the function has run.
+ void PostTaskAndWaitForTesting(std::function<void()>);
+
+ // Can be called from another thread to get the CPU time of the thread the
+ // task-runner is executing on.
+ uint64_t GetThreadCPUTimeNsForTesting();
+
// Returns a pointer to the UnixTaskRunner, which is valid for the lifetime of
// this ThreadTaskRunner object (unless this object is moved-from, in which
// case the pointer remains valid for the lifetime of the new owning
@@ -53,10 +63,11 @@
UnixTaskRunner* get() const { return task_runner_; }
private:
- ThreadTaskRunner();
+ explicit ThreadTaskRunner(const std::string& name);
void RunTaskThread(std::function<void(UnixTaskRunner*)> initializer);
std::thread thread_;
+ std::string name_;
UnixTaskRunner* task_runner_ = nullptr;
};
diff --git a/include/perfetto/ext/base/unix_socket.h b/include/perfetto/ext/base/unix_socket.h
index a0dac27..07e0f58 100644
--- a/include/perfetto/ext/base/unix_socket.h
+++ b/include/perfetto/ext/base/unix_socket.h
@@ -48,9 +48,7 @@
class UnixSocketRaw {
public:
// Creates a new unconnected unix socket.
- static UnixSocketRaw CreateMayFail(SockFamily family, SockType type) {
- return UnixSocketRaw(family, type);
- }
+ static UnixSocketRaw CreateMayFail(SockFamily family, SockType type);
// Crates a pair of connected sockets.
static std::pair<UnixSocketRaw, UnixSocketRaw> CreatePair(SockFamily,
diff --git a/include/perfetto/ext/base/unix_task_runner.h b/include/perfetto/ext/base/unix_task_runner.h
index 9ced3b9..386c01f 100644
--- a/include/perfetto/ext/base/unix_task_runner.h
+++ b/include/perfetto/ext/base/unix_task_runner.h
@@ -19,11 +19,11 @@
#include "perfetto/base/build_config.h"
#include "perfetto/base/task_runner.h"
+#include "perfetto/base/thread_utils.h"
#include "perfetto/base/time.h"
#include "perfetto/ext/base/event_fd.h"
#include "perfetto/ext/base/scoped_file.h"
#include "perfetto/ext/base/thread_checker.h"
-#include "perfetto/ext/base/thread_utils.h"
#include <poll.h>
#include <chrono>
@@ -87,7 +87,7 @@
void RunFileDescriptorWatch(int fd);
ThreadChecker thread_checker_;
- PlatformThreadID created_thread_id_ = GetThreadId();
+ PlatformThreadId created_thread_id_ = GetThreadId();
// On Linux, an eventfd(2) used to waking up the task runner when a new task
// is posted. Otherwise the read end of a pipe used for the same purpose.
diff --git a/include/perfetto/ext/base/utils.h b/include/perfetto/ext/base/utils.h
index f7bfdcd..aadded6 100644
--- a/include/perfetto/ext/base/utils.h
+++ b/include/perfetto/ext/base/utils.h
@@ -28,13 +28,13 @@
#endif
#define PERFETTO_EINTR(x) \
- ({ \
+ ([&] { \
decltype(x) eintr_wrapper_result; \
do { \
eintr_wrapper_result = (x); \
} while (eintr_wrapper_result == -1 && errno == EINTR); \
- eintr_wrapper_result; \
- })
+ return eintr_wrapper_result; \
+ }())
#if PERFETTO_BUILDFLAG(PERFETTO_OS_WIN)
// TODO(brucedawson) - create a ::perfetto::base::IOSize to replace this.
diff --git a/include/perfetto/ext/base/uuid.h b/include/perfetto/ext/base/uuid.h
index 8d13751..1b4c538 100644
--- a/include/perfetto/ext/base/uuid.h
+++ b/include/perfetto/ext/base/uuid.h
@@ -54,13 +54,13 @@
set_lsb(lsb);
set_msb(msb);
}
+ void set_msb(int64_t msb) { memcpy(data_.data() + 8, &msb, 8); }
+ void set_lsb(int64_t lsb) { memcpy(data_.data(), &lsb, 8); }
std::string ToString() const;
std::string ToPrettyString() const;
private:
- void set_msb(int64_t msb) { memcpy(data_.data() + 8, &msb, 8); }
- void set_lsb(int64_t lsb) { memcpy(data_.data(), &lsb, 8); }
std::array<uint8_t, 16> data_{};
};
diff --git a/include/perfetto/ext/ipc/service_proxy.h b/include/perfetto/ext/ipc/service_proxy.h
index 98f111c..02c2dc2 100644
--- a/include/perfetto/ext/ipc/service_proxy.h
+++ b/include/perfetto/ext/ipc/service_proxy.h
@@ -26,6 +26,7 @@
#include <memory>
#include <string>
+#include "perfetto/base/export.h"
#include "perfetto/ext/base/weak_ptr.h"
#include "perfetto/ext/ipc/deferred.h"
@@ -38,7 +39,7 @@
// The base class for the client-side autogenerated stubs that forward method
// invocations to the host. All the methods of this class are meant to be called
// only by the autogenerated code.
-class ServiceProxy {
+class PERFETTO_EXPORT ServiceProxy {
public:
class EventListener {
public:
diff --git a/include/perfetto/ext/traced/BUILD.gn b/include/perfetto/ext/traced/BUILD.gn
index 1f58ac2..631202c 100644
--- a/include/perfetto/ext/traced/BUILD.gn
+++ b/include/perfetto/ext/traced/BUILD.gn
@@ -25,7 +25,5 @@
"../../../../protos/perfetto/common:zero",
"../base",
]
- sources = [
- "sys_stats_counters.h",
- ]
+ sources = [ "sys_stats_counters.h" ]
}
diff --git a/include/perfetto/ext/tracing/core/tracing_service.h b/include/perfetto/ext/tracing/core/tracing_service.h
index c097a6e..695d78e 100644
--- a/include/perfetto/ext/tracing/core/tracing_service.h
+++ b/include/perfetto/ext/tracing/core/tracing_service.h
@@ -106,11 +106,12 @@
BufferExhaustedPolicy buffer_exhausted_policy =
BufferExhaustedPolicy::kDefault) = 0;
- // If TracingService::ConnectProducer is called with |in_process=true|,
- // this returns the producer's SharedMemoryArbiter which can be used
- // to create TraceWriters which is able to directly commit chunks
- // without going through an IPC layer.
- virtual SharedMemoryArbiter* GetInProcessShmemArbiter() = 0;
+ // In some cases you can access the producer's SharedMemoryArbiter (for
+ // example if TracingService::ConnectProducer is called with
+ // |in_process=true|). The SharedMemoryArbiter can be used to create
+ // TraceWriters which is able to directly commit chunks. For the
+ // |in_process=true| case this can be done without going through an IPC layer.
+ virtual SharedMemoryArbiter* MaybeSharedMemoryArbiter() = 0;
// Called in response to a Producer::Flush(request_id) call after all data
// for the flush request has been committed.
diff --git a/include/perfetto/ext/tracing/ipc/consumer_ipc_client.h b/include/perfetto/ext/tracing/ipc/consumer_ipc_client.h
index b39d17c..bb88073 100644
--- a/include/perfetto/ext/tracing/ipc/consumer_ipc_client.h
+++ b/include/perfetto/ext/tracing/ipc/consumer_ipc_client.h
@@ -20,6 +20,7 @@
#include <memory>
#include <string>
+#include "perfetto/base/export.h"
#include "perfetto/ext/tracing/core/tracing_service.h"
namespace perfetto {
@@ -31,7 +32,7 @@
// Consumer(s) of the tracing library.
// Implemented in:
// src/tracing/ipc/consumer/consumer_ipc_client_impl.cc
-class ConsumerIPCClient {
+class PERFETTO_EXPORT ConsumerIPCClient {
public:
// Connects to the producer port of the Service listening on the given
// |service_sock_name|. If the connection is successful, the OnConnect()
diff --git a/include/perfetto/ext/tracing/ipc/default_socket.h b/include/perfetto/ext/tracing/ipc/default_socket.h
index 85a1de0..6f1fafb 100644
--- a/include/perfetto/ext/tracing/ipc/default_socket.h
+++ b/include/perfetto/ext/tracing/ipc/default_socket.h
@@ -17,10 +17,12 @@
#ifndef INCLUDE_PERFETTO_EXT_TRACING_IPC_DEFAULT_SOCKET_H_
#define INCLUDE_PERFETTO_EXT_TRACING_IPC_DEFAULT_SOCKET_H_
+#include "perfetto/base/export.h"
+
namespace perfetto {
-const char* GetConsumerSocket();
-const char* GetProducerSocket();
+PERFETTO_EXPORT const char* GetConsumerSocket();
+PERFETTO_EXPORT const char* GetProducerSocket();
} // namespace perfetto
diff --git a/include/perfetto/ext/tracing/ipc/producer_ipc_client.h b/include/perfetto/ext/tracing/ipc/producer_ipc_client.h
index e6092e8..6c1bdba 100644
--- a/include/perfetto/ext/tracing/ipc/producer_ipc_client.h
+++ b/include/perfetto/ext/tracing/ipc/producer_ipc_client.h
@@ -20,6 +20,7 @@
#include <memory>
#include <string>
+#include "perfetto/base/export.h"
#include "perfetto/ext/tracing/core/tracing_service.h"
namespace perfetto {
@@ -31,7 +32,7 @@
// Producer(s) of the tracing library.
// Implemented in:
// src/tracing/ipc/producer/producer_ipc_client_impl.cc
-class ProducerIPCClient {
+class PERFETTO_EXPORT ProducerIPCClient {
public:
// Connects to the producer port of the Service listening on the given
// |service_sock_name|. If the connection is successful, the OnConnect()
diff --git a/include/perfetto/ext/tracing/ipc/service_ipc_host.h b/include/perfetto/ext/tracing/ipc/service_ipc_host.h
index 86915af..ed3deb9 100644
--- a/include/perfetto/ext/tracing/ipc/service_ipc_host.h
+++ b/include/perfetto/ext/tracing/ipc/service_ipc_host.h
@@ -19,6 +19,7 @@
#include <memory>
+#include "perfetto/base/export.h"
#include "perfetto/ext/base/scoped_file.h"
#include "perfetto/ext/tracing/core/basic_types.h"
@@ -34,7 +35,7 @@
// The code in the tracing client that will host the service e.g., traced.
// Implemented in:
// src/tracing/ipc/service/service_ipc_host_impl.cc
-class ServiceIPCHost {
+class PERFETTO_EXPORT ServiceIPCHost {
public:
static std::unique_ptr<ServiceIPCHost> CreateInstance(base::TaskRunner*);
virtual ~ServiceIPCHost();
diff --git a/include/perfetto/profiling/BUILD.gn b/include/perfetto/profiling/BUILD.gn
index ce7c188..17dc5db 100644
--- a/include/perfetto/profiling/BUILD.gn
+++ b/include/perfetto/profiling/BUILD.gn
@@ -13,19 +13,13 @@
# limitations under the License.
source_set("pprof_builder") {
- sources = [
- "pprof_builder.h",
- ]
+ sources = [ "pprof_builder.h" ]
}
source_set("normalize") {
- sources = [
- "normalize.h",
- ]
+ sources = [ "normalize.h" ]
}
source_set("deobfuscator") {
- sources = [
- "deobfuscator.h",
- ]
+ sources = [ "deobfuscator.h" ]
}
diff --git a/include/perfetto/protozero/BUILD.gn b/include/perfetto/protozero/BUILD.gn
index b528a5b..ee0f77a 100644
--- a/include/perfetto/protozero/BUILD.gn
+++ b/include/perfetto/protozero/BUILD.gn
@@ -13,9 +13,7 @@
# limitations under the License.
source_set("protozero") {
- public_deps = [
- "../base",
- ]
+ public_deps = [ "../base" ]
sources = [
"contiguous_memory_range.h",
"copyable_ptr.h",
diff --git a/include/perfetto/public/BUILD.gn b/include/perfetto/public/BUILD.gn
index 0ec88f1..13eb6c1 100644
--- a/include/perfetto/public/BUILD.gn
+++ b/include/perfetto/public/BUILD.gn
@@ -13,7 +13,5 @@
# limitations under the License.
source_set("public") {
- sources = [
- "consumer_api.h",
- ]
+ sources = [ "consumer_api.h" ]
}
diff --git a/include/perfetto/trace_processor/BUILD.gn b/include/perfetto/trace_processor/BUILD.gn
index 1c419f9..8db2a2f 100644
--- a/include/perfetto/trace_processor/BUILD.gn
+++ b/include/perfetto/trace_processor/BUILD.gn
@@ -24,12 +24,8 @@
}
source_set("storage") {
- sources = [
- "trace_processor_storage.h",
- ]
- public_deps = [
- ":basic_types",
- ]
+ sources = [ "trace_processor_storage.h" ]
+ public_deps = [ ":basic_types" ]
}
source_set("basic_types") {
diff --git a/include/perfetto/trace_processor/basic_types.h b/include/perfetto/trace_processor/basic_types.h
index db67e79..b584126 100644
--- a/include/perfetto/trace_processor/basic_types.h
+++ b/include/perfetto/trace_processor/basic_types.h
@@ -40,9 +40,15 @@
// sort ignoring any internal heureustics to skip sorting parts of the data.
bool force_full_sort = false;
- // When set to a non-zero value, this overrides the default block size used
- // by the StringPool. For defaults, see kDefaultBlockSize in string_pool.h.
- size_t string_pool_block_size_bytes = 0;
+ // When set to false, this option makes the trace processor not include ftrace
+ // events in the raw table; this makes converting events back to the systrace
+ // text format impossible. On the other hand, it also saves ~50% of memory
+ // usage of trace processor. For reference, Studio intends to use this option.
+ //
+ // Note: "generic" ftrace events will be parsed into the raw table even if
+ // this flag is false and all other events which parse into the raw table are
+ // unaffected by this flag.
+ bool ingest_ftrace_in_raw_table = true;
};
// Represents a dynamically typed value returned by SQL.
diff --git a/include/perfetto/tracing.h b/include/perfetto/tracing.h
index be9ef6d..fca7c70 100644
--- a/include/perfetto/tracing.h
+++ b/include/perfetto/tracing.h
@@ -33,5 +33,6 @@
#include "perfetto/tracing/tracing_backend.h"
#include "perfetto/tracing/track_event.h"
#include "perfetto/tracing/track_event_interned_data_index.h"
+#include "perfetto/tracing/track_event_legacy.h"
#endif // INCLUDE_PERFETTO_TRACING_H_
diff --git a/include/perfetto/tracing/BUILD.gn b/include/perfetto/tracing/BUILD.gn
index 01294bd..e6c68c4 100644
--- a/include/perfetto/tracing/BUILD.gn
+++ b/include/perfetto/tracing/BUILD.gn
@@ -14,7 +14,6 @@
source_set("tracing") {
public_deps = [
- "../../../gn:default_deps",
"../../../protos/perfetto/common:cpp",
"../../../protos/perfetto/trace:zero",
"../../../protos/perfetto/trace/interned_data:zero",
@@ -41,8 +40,10 @@
"trace_writer_base.h",
"tracing.h",
"tracing_backend.h",
+ "track.h",
"track_event.h",
"track_event_category_registry.h",
"track_event_interned_data_index.h",
+ "track_event_legacy.h",
]
}
diff --git a/include/perfetto/tracing/core/BUILD.gn b/include/perfetto/tracing/core/BUILD.gn
index a7f4a4c..a359f63 100644
--- a/include/perfetto/tracing/core/BUILD.gn
+++ b/include/perfetto/tracing/core/BUILD.gn
@@ -31,7 +31,5 @@
# forward_decls.h without polluting their public_deps with the proto-generated
# {common,config}:cpp, which would slow-down build time.
source_set("forward_decls") {
- sources = [
- "forward_decls.h",
- ]
+ sources = [ "forward_decls.h" ]
}
diff --git a/include/perfetto/tracing/data_source.h b/include/perfetto/tracing/data_source.h
index 923e176..1a2f57e 100644
--- a/include/perfetto/tracing/data_source.h
+++ b/include/perfetto/tracing/data_source.h
@@ -369,8 +369,6 @@
// Setup/Start/Stop notifications and makes the Trace() method work when
// tracing is enabled and the data source is selected.
// This must be called after Tracing::Initialize().
- // The caller must also use the DEFINE_DATA_SOURCE_STATIC_MEMBERS() macro
- // documented below.
// Can return false to signal failure if attemping to register more than
// kMaxDataSources (32) data sources types.
static bool Register(const DataSourceDescriptor& descriptor) {
@@ -455,19 +453,20 @@
} // namespace perfetto
+// If placed at the end of a macro declaration, eats the semicolon at the end of
+// the macro invocation (e.g., "MACRO(...);") to avoid warnings about extra
+// semicolons.
+#define PERFETTO_INTERNAL_SWALLOW_SEMICOLON() \
+ extern int perfetto_internal_unused
+
// Not needed -- only here for backwards compatibility.
// TODO(skyostil): Remove this macro.
-#define PERFETTO_DECLARE_DATA_SOURCE_STATIC_MEMBERS(...)
+#define PERFETTO_DECLARE_DATA_SOURCE_STATIC_MEMBERS(...) \
+ PERFETTO_INTERNAL_SWALLOW_SEMICOLON()
-// The API client must use this in a translation unit. This is because it needs
-// to instantiate the static storage for the datasource to allow the fastpath
-// enabled check.
-#define PERFETTO_DEFINE_DATA_SOURCE_STATIC_MEMBERS(...) \
- template <> \
- perfetto::internal::DataSourceStaticState \
- perfetto::DataSource<__VA_ARGS__>::static_state_{}; \
- template <> \
- thread_local perfetto::internal::DataSourceThreadLocalState* \
- perfetto::DataSource<__VA_ARGS__>::tls_state_ = nullptr
+// Not needed -- only here for backwards compatibility.
+// TODO(skyostil): Remove this macro.
+#define PERFETTO_DEFINE_DATA_SOURCE_STATIC_MEMBERS(...) \
+ PERFETTO_INTERNAL_SWALLOW_SEMICOLON()
#endif // INCLUDE_PERFETTO_TRACING_DATA_SOURCE_H_
diff --git a/include/perfetto/tracing/debug_annotation.h b/include/perfetto/tracing/debug_annotation.h
index 996861c..f13fbd9 100644
--- a/include/perfetto/tracing/debug_annotation.h
+++ b/include/perfetto/tracing/debug_annotation.h
@@ -21,6 +21,7 @@
#include <stdint.h>
+#include <memory>
#include <string>
namespace perfetto {
@@ -56,6 +57,12 @@
void WriteDebugAnnotation(protos::pbzero::DebugAnnotation*,
const DebugAnnotation&);
+template <typename T>
+void WriteDebugAnnotation(protos::pbzero::DebugAnnotation* annotation,
+ const std::unique_ptr<T>& value) {
+ WriteDebugAnnotation(annotation, *value);
+}
+
} // namespace internal
} // namespace perfetto
diff --git a/include/perfetto/tracing/event_context.h b/include/perfetto/tracing/event_context.h
index da1607b..fe9c4bb 100644
--- a/include/perfetto/tracing/event_context.h
+++ b/include/perfetto/tracing/event_context.h
@@ -35,9 +35,15 @@
// dbg->set_int_value(1234);
// });
//
-class EventContext {
+class PERFETTO_EXPORT EventContext {
public:
EventContext(EventContext&&) = default;
+
+ // For Chromium during the transition phase to the client library.
+ // TODO(eseckler): Remove once Chromium has switched to client lib entirely.
+ explicit EventContext(protos::pbzero::TrackEvent* event)
+ : event_(event), incremental_state_(nullptr) {}
+
~EventContext();
protos::pbzero::TrackEvent* event() const { return event_; }
diff --git a/include/perfetto/tracing/internal/track_event_data_source.h b/include/perfetto/tracing/internal/track_event_data_source.h
index 1debee3..e835155 100644
--- a/include/perfetto/tracing/internal/track_event_data_source.h
+++ b/include/perfetto/tracing/internal/track_event_data_source.h
@@ -22,6 +22,7 @@
#include "perfetto/tracing/data_source.h"
#include "perfetto/tracing/event_context.h"
#include "perfetto/tracing/internal/track_event_internal.h"
+#include "perfetto/tracing/track.h"
#include "perfetto/tracing/track_event_category_registry.h"
#include "protos/perfetto/trace/track_event/track_event.pbzero.h"
@@ -30,6 +31,34 @@
namespace perfetto {
namespace internal {
+namespace {
+
+// A template helper for determining whether a type can be used as a track event
+// lambda, i.e., it has the signature "void(EventContext)". This is achieved by
+// checking that we can pass an EventContext value (the inner declval) into a T
+// instance (the outer declval). If this is a valid expression, the result
+// evaluates to sizeof(0), i.e., true.
+// TODO(skyostil): Replace this with std::is_convertible<std::function<...>>
+// once we have C++14.
+template <typename T>
+static constexpr bool IsValidTraceLambdaImpl(
+ typename std::enable_if<static_cast<bool>(
+ sizeof(std::declval<T>()(std::declval<EventContext>()), 0))>::type* =
+ nullptr) {
+ return true;
+}
+
+template <typename T>
+static constexpr bool IsValidTraceLambdaImpl(...) {
+ return false;
+}
+
+template <typename T>
+static constexpr bool IsValidTraceLambda() {
+ return IsValidTraceLambdaImpl<T>(nullptr);
+}
+
+} // namespace
struct TrackEventDataSourceTraits : public perfetto::DefaultDataSourceTraits {
using IncrementalStateType = TrackEventIncrementalState;
@@ -87,24 +116,73 @@
}
// Once we've determined tracing to be enabled for this category, actually
- // write a trace event. Outlined to avoid bloating code at the actual trace
- // point.
- // TODO(skyostil): Investigate whether this should be fully outlined to reduce
- // binary size.
+ // write a trace event onto this thread's default track. Outlined to avoid
+ // bloating code (mostly stack depth) at the actual trace point.
+ //
+ // To minimize call overhead at each trace point, we provide the following
+ // trace point argument variants:
+ //
+ // - None
+ // - Lambda
+ // - One debug annotation
+ // - Two debug annotations
+ // - Track
+ // - Track + Lambda
+ // - Track + one debug annotation
+ // - Track + two debug annotations
+
+ // Trace point which takes no arguments.
+ template <size_t CategoryIndex>
+ static void TraceForCategory(uint32_t instances,
+ const char* event_name,
+ perfetto::protos::pbzero::TrackEvent::Type type)
+ PERFETTO_NO_INLINE {
+ TraceForCategoryImpl<CategoryIndex>(instances, event_name, type);
+ }
+
+ // Trace point which takes a lambda function argument.
template <size_t CategoryIndex,
- typename ArgumentFunction = void (*)(EventContext)>
- static void TraceForCategory(
- uint32_t instances,
- const char* event_name,
- perfetto::protos::pbzero::TrackEvent::Type type,
- ArgumentFunction arg_function = [](EventContext) {}) PERFETTO_NO_INLINE {
- Base::template TraceWithInstances<CategoryTracePointTraits<CategoryIndex>>(
- instances, [&](typename Base::TraceContext ctx) {
- // TODO(skyostil): Intern categories at compile time.
- arg_function(TrackEventInternal::WriteEvent(
- ctx.tls_inst_->trace_writer.get(), ctx.GetIncrementalState(),
- Registry->GetCategory(CategoryIndex)->name, event_name, type));
- });
+ typename ArgumentFunction = void (*)(EventContext),
+ typename ArgumentFunctionCheck = typename std::enable_if<
+ IsValidTraceLambda<ArgumentFunction>()>::type>
+ static void TraceForCategory(uint32_t instances,
+ const char* event_name,
+ perfetto::protos::pbzero::TrackEvent::Type type,
+ ArgumentFunction arg_function)
+ PERFETTO_NO_INLINE {
+ TraceForCategoryImpl<CategoryIndex>(instances, event_name, type, Track(),
+ std::move(arg_function));
+ }
+
+ // This variant of the inner trace point takes a Track argument which can be
+ // used to emit events on a non-default track.
+ template <size_t CategoryIndex,
+ typename TrackType,
+ typename TrackTypeCheck = typename std::enable_if<
+ std::is_convertible<TrackType, Track>::value>::type>
+ static void TraceForCategory(uint32_t instances,
+ const char* event_name,
+ perfetto::protos::pbzero::TrackEvent::Type type,
+ const TrackType& track) PERFETTO_NO_INLINE {
+ TraceForCategoryImpl<CategoryIndex>(instances, event_name, type, track);
+ }
+
+ // Trace point with a track and a lambda function.
+ template <size_t CategoryIndex,
+ typename TrackType,
+ typename ArgumentFunction = void (*)(EventContext),
+ typename ArgumentFunctionCheck = typename std::enable_if<
+ IsValidTraceLambda<ArgumentFunction>()>::type,
+ typename TrackTypeCheck = typename std::enable_if<
+ std::is_convertible<TrackType, Track>::value>::type>
+ static void TraceForCategory(uint32_t instances,
+ const char* event_name,
+ perfetto::protos::pbzero::TrackEvent::Type type,
+ const TrackType& track,
+ ArgumentFunction arg_function)
+ PERFETTO_NO_INLINE {
+ TraceForCategoryImpl<CategoryIndex>(instances, event_name, type, track,
+ std::move(arg_function));
}
// Trace point with one debug annotation.
@@ -124,27 +202,51 @@
perfetto::protos::pbzero::TrackEvent::Type type,
const char* arg_name,
ArgType&& arg_value) PERFETTO_ALWAYS_INLINE {
- TraceForCategoryWithDebugAnnotations<CategoryIndex, ArgType>(
- instances, event_name, type, arg_name,
+ TraceForCategoryWithDebugAnnotations<CategoryIndex, Track, ArgType>(
+ instances, event_name, type, Track(), arg_name,
std::forward<ArgType>(arg_value));
}
- template <size_t CategoryIndex, typename ArgType>
+ // A one argument trace point which takes an explicit track.
+ template <size_t CategoryIndex, typename TrackType, typename ArgType>
+ static void TraceForCategory(uint32_t instances,
+ const char* event_name,
+ perfetto::protos::pbzero::TrackEvent::Type type,
+ const TrackType& track,
+ const char* arg_name,
+ ArgType&& arg_value) PERFETTO_ALWAYS_INLINE {
+ PERFETTO_DCHECK(track);
+ TraceForCategoryWithDebugAnnotations<CategoryIndex, TrackType, ArgType>(
+ instances, event_name, type, track, arg_name,
+ std::forward<ArgType>(arg_value));
+ }
+
+ template <size_t CategoryIndex, typename TrackType, typename ArgType>
static void TraceForCategoryWithDebugAnnotations(
uint32_t instances,
const char* event_name,
perfetto::protos::pbzero::TrackEvent::Type type,
+ const TrackType& track,
const char* arg_name,
typename internal::DebugAnnotationArg<ArgType>::type arg_value)
PERFETTO_NO_INLINE {
Base::template TraceWithInstances<CategoryTracePointTraits<CategoryIndex>>(
instances, [&](typename Base::TraceContext ctx) {
- // TODO(skyostil): Intern categories at compile time.
- auto event_ctx = TrackEventInternal::WriteEvent(
- ctx.tls_inst_->trace_writer.get(), ctx.GetIncrementalState(),
- Registry->GetCategory(CategoryIndex)->name, event_name, type);
- TrackEventInternal::AddDebugAnnotation(&event_ctx, arg_name,
- arg_value);
+ {
+ // TODO(skyostil): Intern categories at compile time.
+ auto event_ctx = TrackEventInternal::WriteEvent(
+ ctx.tls_inst_->trace_writer.get(), ctx.GetIncrementalState(),
+ Registry->GetCategory(CategoryIndex)->name, event_name, type);
+ if (track)
+ event_ctx.event()->set_track_uuid(track.uuid);
+ TrackEventInternal::AddDebugAnnotation(&event_ctx, arg_name,
+ arg_value);
+ }
+ if (track) {
+ TrackEventInternal::WriteTrackDescriptorIfNeeded(
+ track, ctx.tls_inst_->trace_writer.get(),
+ ctx.GetIncrementalState());
+ }
});
}
@@ -160,16 +262,43 @@
ArgType&& arg_value,
const char* arg_name2,
ArgType2&& arg_value2) PERFETTO_ALWAYS_INLINE {
- TraceForCategoryWithDebugAnnotations<CategoryIndex, ArgType, ArgType2>(
- instances, event_name, type, arg_name, std::forward<ArgType>(arg_value),
- arg_name2, std::forward<ArgType2>(arg_value2));
+ TraceForCategoryWithDebugAnnotations<CategoryIndex, Track, ArgType,
+ ArgType2>(
+ instances, event_name, type, Track(), arg_name,
+ std::forward<ArgType>(arg_value), arg_name2,
+ std::forward<ArgType2>(arg_value2));
}
- template <size_t CategoryIndex, typename ArgType, typename ArgType2>
+ // A two argument trace point which takes an explicit track.
+ template <size_t CategoryIndex,
+ typename TrackType,
+ typename ArgType,
+ typename ArgType2>
+ static void TraceForCategory(uint32_t instances,
+ const char* event_name,
+ perfetto::protos::pbzero::TrackEvent::Type type,
+ const TrackType& track,
+ const char* arg_name,
+ ArgType&& arg_value,
+ const char* arg_name2,
+ ArgType2&& arg_value2) PERFETTO_ALWAYS_INLINE {
+ PERFETTO_DCHECK(track);
+ TraceForCategoryWithDebugAnnotations<CategoryIndex, TrackType, ArgType,
+ ArgType2>(
+ instances, event_name, type, track, arg_name,
+ std::forward<ArgType>(arg_value), arg_name2,
+ std::forward<ArgType2>(arg_value2));
+ }
+
+ template <size_t CategoryIndex,
+ typename TrackType,
+ typename ArgType,
+ typename ArgType2>
static void TraceForCategoryWithDebugAnnotations(
uint32_t instances,
const char* event_name,
perfetto::protos::pbzero::TrackEvent::Type type,
+ TrackType track,
const char* arg_name,
typename internal::DebugAnnotationArg<ArgType>::type arg_value,
const char* arg_name2,
@@ -178,16 +307,27 @@
Base::template TraceWithInstances<CategoryTracePointTraits<CategoryIndex>>(
instances, [&](typename Base::TraceContext ctx) {
// TODO(skyostil): Intern categories at compile time.
- auto event_ctx = TrackEventInternal::WriteEvent(
- ctx.tls_inst_->trace_writer.get(), ctx.GetIncrementalState(),
- Registry->GetCategory(CategoryIndex)->name, event_name, type);
- TrackEventInternal::AddDebugAnnotation(&event_ctx, arg_name,
- arg_value);
- TrackEventInternal::AddDebugAnnotation(&event_ctx, arg_name2,
- arg_value2);
+ {
+ auto event_ctx = TrackEventInternal::WriteEvent(
+ ctx.tls_inst_->trace_writer.get(), ctx.GetIncrementalState(),
+ Registry->GetCategory(CategoryIndex)->name, event_name, type);
+ if (track)
+ event_ctx.event()->set_track_uuid(track.uuid);
+ TrackEventInternal::AddDebugAnnotation(&event_ctx, arg_name,
+ arg_value);
+ TrackEventInternal::AddDebugAnnotation(&event_ctx, arg_name2,
+ arg_value2);
+ }
+ if (track) {
+ TrackEventInternal::WriteTrackDescriptorIfNeeded(
+ track, ctx.tls_inst_->trace_writer.get(),
+ ctx.GetIncrementalState());
+ }
});
}
+ // Initialize the track event library. Should be called before tracing is
+ // enabled.
static bool Register() {
// Registration is performed out-of-line so users don't need to depend on
// DataSourceDescriptor C++ bindings.
@@ -195,6 +335,29 @@
[](const DataSourceDescriptor& dsd) { return Base::Register(dsd); });
}
+ // Record metadata about different types of timeline tracks. See Track.
+ static void SetTrackDescriptor(
+ const Track& track,
+ std::function<void(protos::pbzero::TrackDescriptor*)> callback) {
+ SetTrackDescriptorImpl(track, std::move(callback));
+ }
+
+ static void SetProcessDescriptor(
+ std::function<void(protos::pbzero::TrackDescriptor*)> callback,
+ const ProcessTrack& track = ProcessTrack::Current()) {
+ SetTrackDescriptorImpl(std::move(track), std::move(callback));
+ }
+
+ static void SetThreadDescriptor(
+ std::function<void(protos::pbzero::TrackDescriptor*)> callback,
+ const ThreadTrack& track = ThreadTrack::Current()) {
+ SetTrackDescriptorImpl(std::move(track), std::move(callback));
+ }
+
+ static void EraseTrackDescriptor(const Track& track) {
+ TrackRegistry::Get()->EraseTrack(track);
+ }
+
private:
// Each category has its own enabled/disabled state, stored in the category
// registry.
@@ -204,6 +367,55 @@
return Registry->GetCategoryState(CategoryIndex);
}
};
+
+ // TODO(skyostil): Make |CategoryIndex| a regular parameter to reuse trace
+ // point code across different categories.
+ template <size_t CategoryIndex,
+ typename TrackType = Track,
+ typename ArgumentFunction = void (*)(EventContext),
+ typename ArgumentFunctionCheck = typename std::enable_if<
+ IsValidTraceLambda<ArgumentFunction>()>::type,
+ typename TrackTypeCheck = typename std::enable_if<
+ std::is_convertible<TrackType, Track>::value>::type>
+ static void TraceForCategoryImpl(
+ uint32_t instances,
+ const char* event_name,
+ perfetto::protos::pbzero::TrackEvent::Type type,
+ const TrackType& track = Track(),
+ ArgumentFunction arg_function = [](EventContext) {
+ }) PERFETTO_ALWAYS_INLINE {
+ Base::template TraceWithInstances<CategoryTracePointTraits<CategoryIndex>>(
+ instances, [&](typename Base::TraceContext ctx) {
+ {
+ // TODO(skyostil): Intern categories at compile time.
+ auto event_ctx = TrackEventInternal::WriteEvent(
+ ctx.tls_inst_->trace_writer.get(), ctx.GetIncrementalState(),
+ Registry->GetCategory(CategoryIndex)->name, event_name, type);
+ if (track)
+ event_ctx.event()->set_track_uuid(track.uuid);
+ arg_function(std::move(event_ctx));
+ }
+ if (track) {
+ TrackEventInternal::WriteTrackDescriptorIfNeeded(
+ track, ctx.tls_inst_->trace_writer.get(),
+ ctx.GetIncrementalState());
+ }
+ });
+ }
+
+ // Records a track descriptor into the track descriptor registry and, if we
+ // are tracing, also mirrors the descriptor into the trace.
+ template <typename TrackType>
+ static void SetTrackDescriptorImpl(
+ const TrackType& track,
+ std::function<void(protos::pbzero::TrackDescriptor*)> callback) {
+ TrackRegistry::Get()->UpdateTrack(
+ track, [&](protos::pbzero::TrackDescriptor* desc) { callback(desc); });
+ Base::template Trace([&](typename Base::TraceContext ctx) {
+ TrackEventInternal::WriteTrackDescriptor(
+ track, ctx.tls_inst_->trace_writer.get());
+ });
+ }
};
} // namespace internal
diff --git a/include/perfetto/tracing/internal/track_event_internal.h b/include/perfetto/tracing/internal/track_event_internal.h
index e37a30b..a4ee050 100644
--- a/include/perfetto/tracing/internal/track_event_internal.h
+++ b/include/perfetto/tracing/internal/track_event_internal.h
@@ -17,15 +17,17 @@
#ifndef INCLUDE_PERFETTO_TRACING_INTERNAL_TRACK_EVENT_INTERNAL_H_
#define INCLUDE_PERFETTO_TRACING_INTERNAL_TRACK_EVENT_INTERNAL_H_
-#include <unordered_map>
-
+#include "perfetto/base/flat_set.h"
#include "perfetto/protozero/scattered_heap_buffer.h"
#include "perfetto/tracing/core/forward_decls.h"
#include "perfetto/tracing/debug_annotation.h"
#include "perfetto/tracing/trace_writer_base.h"
+#include "perfetto/tracing/track.h"
#include "protos/perfetto/trace/interned_data/interned_data.pbzero.h"
#include "protos/perfetto/trace/track_event/track_event.pbzero.h"
+#include <set>
+
namespace perfetto {
class EventContext;
namespace protos {
@@ -70,6 +72,11 @@
std::unique_ptr<BaseTrackEventInternedDataIndex>>;
std::array<InternedDataIndex, kMaxInternedDataFields> interned_data_indices =
{};
+
+ // Track uuids for which we have written descriptors into the trace. If a
+ // trace event uses a track which is not in this set, we'll write out a
+ // descriptor for it.
+ base::FlatSet<uint64_t> seen_tracks;
};
// The backend portion of the track event trace point implemention. Outlined to
@@ -101,7 +108,36 @@
WriteDebugAnnotation(annotation, value);
}
+ // If the given track hasn't been seen by the trace writer yet, write a
+ // descriptor for it into the trace. Doesn't take a lock unless the track
+ // descriptor is new.
+ template <typename TrackType>
+ static void WriteTrackDescriptorIfNeeded(
+ const TrackType& track,
+ TraceWriterBase* trace_writer,
+ TrackEventIncrementalState* incr_state) {
+ auto it_and_inserted = incr_state->seen_tracks.insert(track.uuid);
+ if (PERFETTO_LIKELY(!it_and_inserted.second))
+ return;
+ WriteTrackDescriptor(track, trace_writer);
+ }
+
+ // Unconditionally write a track descriptor into the trace.
+ template <typename TrackType>
+ static void WriteTrackDescriptor(const TrackType& track,
+ TraceWriterBase* trace_writer) {
+ TrackRegistry::Get()->SerializeTrack(
+ track, NewTracePacket(trace_writer, GetTimeNs()));
+ }
+
private:
+ static uint64_t GetTimeNs();
+ static void ResetIncrementalState(TraceWriterBase*, uint64_t timestamp);
+ static protozero::MessageHandle<protos::pbzero::TracePacket> NewTracePacket(
+ TraceWriterBase*,
+ uint64_t timestamp,
+ uint32_t seq_flags =
+ protos::pbzero::TracePacket::SEQ_NEEDS_INCREMENTAL_STATE);
static protos::pbzero::DebugAnnotation* AddDebugAnnotation(
perfetto::EventContext*,
const char* name);
diff --git a/include/perfetto/tracing/internal/track_event_macros.h b/include/perfetto/tracing/internal/track_event_macros.h
index f291186..bfe6692 100644
--- a/include/perfetto/tracing/internal/track_event_macros.h
+++ b/include/perfetto/tracing/internal/track_event_macros.h
@@ -25,6 +25,9 @@
#include "perfetto/tracing/internal/track_event_data_source.h"
#include "perfetto/tracing/track_event_category_registry.h"
+// Ignore GCC warning about a missing argument for a variadic macro parameter.
+#pragma GCC system_header
+
// Defines data structures for backing a category registry.
//
// Each category has one enabled/disabled bit per possible data source instance.
diff --git a/include/perfetto/tracing/tracing.h b/include/perfetto/tracing/tracing.h
index 023e6f0..61e805c 100644
--- a/include/perfetto/tracing/tracing.h
+++ b/include/perfetto/tracing/tracing.h
@@ -75,6 +75,14 @@
// Must be one of [4, 8, 16, 32].
uint32_t shmem_page_size_hint_kb = 0;
+ bool operator==(const TracingInitArgs& other) const {
+ return std::tie(backends, custom_backend, platform, shmem_size_hint_kb,
+ shmem_page_size_hint_kb, dcheck_is_on_) ==
+ std::tie(other.backends, other.custom_backend, other.platform,
+ other.shmem_size_hint_kb, other.shmem_page_size_hint_kb,
+ other.dcheck_is_on_);
+ }
+
protected:
friend class Tracing;
bool dcheck_is_on_ = PERFETTO_DCHECK_IS_ON();
@@ -84,7 +92,7 @@
class PERFETTO_EXPORT Tracing {
public:
// Initializes Perfetto with the given backends in the calling process and/or
- // with a user-provided backend. Can only be called once.
+ // with a user-provided backend. No-op if called more than once.
static void Initialize(const TracingInitArgs&);
// Start a new tracing session using the given tracing backend. Use
diff --git a/include/perfetto/tracing/track.h b/include/perfetto/tracing/track.h
new file mode 100644
index 0000000..7e56de4
--- /dev/null
+++ b/include/perfetto/tracing/track.h
@@ -0,0 +1,217 @@
+/*
+ * Copyright (C) 2019 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.
+ */
+
+#ifndef INCLUDE_PERFETTO_TRACING_TRACK_H_
+#define INCLUDE_PERFETTO_TRACING_TRACK_H_
+
+#include "perfetto/base/export.h"
+#include "perfetto/base/proc_utils.h"
+#include "perfetto/base/thread_utils.h"
+#include "perfetto/protozero/message_handle.h"
+#include "perfetto/protozero/scattered_heap_buffer.h"
+#include "protos/perfetto/trace/trace_packet.pbzero.h"
+#include "protos/perfetto/trace/track_event/track_descriptor.pbzero.h"
+
+#include <stdint.h>
+#include <map>
+#include <mutex>
+
+namespace perfetto {
+namespace internal {
+class TrackRegistry;
+}
+
+// Track events are recorded on a timeline track, which maintains the relative
+// time ordering of all events on that track. Each thread has its own default
+// track (ThreadTrack), which is by default where all track events are written.
+// Thread tracks are grouped under their hosting process (ProcessTrack).
+
+// Events which aren't strictly scoped to a thread or a process, or don't
+// correspond to synchronous code execution on a thread can use a custom
+// track (Track, ThreadTrack or ProcessTrack). A Track object can also
+// optionally be parented to a thread or a process.
+//
+// A track is represented by a uuid, which must be unique across the entire
+// recorded trace.
+//
+// For example, to record an event that begins and ends on different threads,
+// use a matching id to tie the begin and end events together:
+//
+// TRACE_EVENT_BEGIN("category", "AsyncEvent", perfetto::Track(8086));
+// ...
+// TRACE_EVENT_END("category", perfetto::Track(8086));
+//
+// Tracks can also be annotated with metadata:
+//
+// perfetto::TrackEvent::SetTrackDescriptor(
+// track, [](perfetto::protos::pbzero::TrackDescriptor* desc) {
+// desc->set_name("MyTrack");
+// });
+//
+// The metadata remains valid between tracing sessions. To free up data for a
+// track, call EraseTrackDescriptor:
+//
+// perfetto::TrackEvent::EraseTrackDescriptor(track);
+//
+struct PERFETTO_EXPORT Track {
+ const uint64_t uuid;
+ const uint64_t parent_uuid;
+ constexpr Track() : uuid(0), parent_uuid(0) {}
+
+ // Construct a track with identifier |id|, optionally parented under |parent|.
+ // If no parent is specified, the track's parent is the current process's
+ // track.
+ //
+ // To minimize the chances for accidental id collisions across processes, the
+ // track's effective uuid is generated by xorring |id| with a random,
+ // per-process cookie.
+ explicit Track(uint64_t id, Track parent = MakeProcessTrack())
+ : uuid(id ^ parent.uuid), parent_uuid(parent.uuid) {}
+
+ explicit operator bool() const { return uuid; }
+ void Serialize(protos::pbzero::TrackDescriptor*) const;
+
+ protected:
+ static Track MakeThreadTrack(base::PlatformThreadId tid_) {
+ return Track(static_cast<uint64_t>(tid_), MakeProcessTrack());
+ }
+
+ static Track MakeProcessTrack() { return Track(process_uuid, Track()); }
+
+ private:
+ friend class internal::TrackRegistry;
+ static uint64_t process_uuid;
+};
+
+// A process track represents events that describe the state of the entire
+// application (e.g., counter events). Currently a ProcessTrack can only
+// represent the current process.
+struct PERFETTO_EXPORT ProcessTrack : public Track {
+ const base::PlatformProcessId pid;
+
+ static ProcessTrack Current() { return ProcessTrack(); }
+
+ void Serialize(protos::pbzero::TrackDescriptor*) const;
+
+ private:
+ ProcessTrack() : Track(MakeProcessTrack()), pid(base::GetProcessId()) {}
+};
+
+// A thread track is associated with a specific thread of execution. Currently
+// only threads in the current process can be referenced.
+struct PERFETTO_EXPORT ThreadTrack : public Track {
+ const base::PlatformProcessId pid;
+ const base::PlatformThreadId tid;
+
+ static ThreadTrack Current() { return ThreadTrack(base::GetThreadId()); }
+
+ // Represents a thread in the current process.
+ static ThreadTrack ForThread(base::PlatformThreadId tid_) {
+ return ThreadTrack(tid_);
+ }
+
+ void Serialize(protos::pbzero::TrackDescriptor*) const;
+
+ private:
+ explicit ThreadTrack(base::PlatformThreadId tid_)
+ : Track(MakeThreadTrack(tid_)),
+ pid(ProcessTrack::Current().pid),
+ tid(tid_) {}
+};
+
+namespace internal {
+
+// Keeps a map of uuids to serialized track descriptors and provides a
+// thread-safe way to read and write them. Each trace writer keeps a TLS set of
+// the tracks it has seen (see TrackEventIncrementalState). In the common case,
+// this registry is not consulted (and no locks are taken). However when a new
+// track is seen, this registry is used to write either 1) the default
+// descriptor for that track (see *Track::Serialize) or 2) a serialized
+// descriptor stored in the registry which may have additional metadata (e.g.,
+// track name).
+// TODO(eseckler): Remove PERFETTO_EXPORT once Chromium no longer calls
+// TrackRegistry::InitializeInstance() directly.
+class PERFETTO_EXPORT TrackRegistry {
+ public:
+ using SerializedTrackDescriptor = std::string;
+
+ TrackRegistry();
+ ~TrackRegistry();
+
+ static void InitializeInstance();
+ static TrackRegistry* Get() { return instance_; }
+
+ void EraseTrack(Track);
+
+ // Store metadata for |track| in the registry. |fill_function| is called
+ // synchronously to record additional properties for the track.
+ template <typename TrackType>
+ void UpdateTrack(
+ const TrackType& track,
+ std::function<void(protos::pbzero::TrackDescriptor*)> fill_function) {
+ UpdateTrackImpl(track, [&](protos::pbzero::TrackDescriptor* desc) {
+ track.Serialize(desc);
+ fill_function(desc);
+ });
+ }
+
+ // If |track| exists in the registry, write out the serialized track
+ // descriptor for it into |packet|. Otherwise just the ephemeral track object
+ // is serialized without any additional metadata.
+ template <typename TrackType>
+ void SerializeTrack(
+ const TrackType& track,
+ protozero::MessageHandle<protos::pbzero::TracePacket> packet) {
+ // If the track has extra metadata (recorded with UpdateTrack), it will be
+ // found in the registry. To minimize the time the lock is held, make a copy
+ // of the data held in the registry and write it outside the lock.
+ std::string desc_copy;
+ {
+ std::lock_guard<std::mutex> lock(mutex_);
+ const auto& it = tracks_.find(track.uuid);
+ if (it != tracks_.end()) {
+ desc_copy = it->second;
+ PERFETTO_DCHECK(!desc_copy.empty());
+ }
+ }
+ if (!desc_copy.empty()) {
+ WriteTrackDescriptor(std::move(desc_copy), std::move(packet));
+ } else {
+ // Otherwise we just write the basic descriptor for this type of track
+ // (e.g., just uuid, no name).
+ track.Serialize(packet->set_track_descriptor());
+ }
+ }
+
+ static void WriteTrackDescriptor(
+ const SerializedTrackDescriptor& desc,
+ protozero::MessageHandle<protos::pbzero::TracePacket> packet);
+
+ private:
+ void UpdateTrackImpl(
+ Track,
+ std::function<void(protos::pbzero::TrackDescriptor*)> fill_function);
+
+ std::mutex mutex_;
+ std::map<uint64_t /* uuid */, SerializedTrackDescriptor> tracks_;
+
+ static TrackRegistry* instance_;
+};
+
+} // namespace internal
+} // namespace perfetto
+
+#endif // INCLUDE_PERFETTO_TRACING_TRACK_H_
diff --git a/include/perfetto/tracing/track_event.h b/include/perfetto/tracing/track_event.h
index fa4776b..3d8e02f 100644
--- a/include/perfetto/tracing/track_event.h
+++ b/include/perfetto/tracing/track_event.h
@@ -21,6 +21,7 @@
#include "perfetto/tracing/internal/track_event_data_source.h"
#include "perfetto/tracing/internal/track_event_internal.h"
#include "perfetto/tracing/internal/track_event_macros.h"
+#include "perfetto/tracing/track.h"
#include "perfetto/tracing/track_event_category_registry.h"
#include "protos/perfetto/trace/track_event/track_event.pbzero.h"
@@ -68,6 +69,14 @@
// });
// }
//
+// Note that track events must be nested consistently, i.e., the following is
+// not allowed:
+//
+// TRACE_EVENT_BEGIN("a", "bar", ...);
+// TRACE_EVENT_BEGIN("b", "foo", ...);
+// TRACE_EVENT_END("a"); // "foo" must be closed before "bar".
+// TRACE_EVENT_END("b");
+//
// ====================
// Implementation notes
// ====================
@@ -129,23 +138,31 @@
PERFETTO_INTERNAL_DECLARE_CATEGORIES(__VA_ARGS__) \
/* The track event data source for this set of categories */ \
PERFETTO_INTERNAL_DECLARE_TRACK_EVENT_DATA_SOURCE(); \
- } // namespace PERFETTO_TRACK_EVENT_NAMESPACE
+ } /* namespace PERFETTO_TRACK_EVENT_NAMESPACE */ \
+ PERFETTO_INTERNAL_SWALLOW_SEMICOLON()
// Allocate storage for each category by using this macro once per track event
// namespace.
-#define PERFETTO_TRACK_EVENT_STATIC_STORAGE() \
- namespace PERFETTO_TRACK_EVENT_NAMESPACE { \
- PERFETTO_INTERNAL_CATEGORY_STORAGE() \
- } // namespace PERFETTO_TRACK_EVENT_NAMESPACE
+#define PERFETTO_TRACK_EVENT_STATIC_STORAGE() \
+ namespace PERFETTO_TRACK_EVENT_NAMESPACE { \
+ PERFETTO_INTERNAL_CATEGORY_STORAGE() \
+ } /* namespace PERFETTO_TRACK_EVENT_NAMESPACE */ \
+ PERFETTO_INTERNAL_SWALLOW_SEMICOLON()
-// Begin a thread-scoped slice under |category| with the title |name|. Both
-// strings must be static constants. The track event is only recorded if
-// |category| is enabled for a tracing session.
+// Ignore GCC warning about a missing argument for a variadic macro parameter.
+#pragma GCC system_header
+
+// Begin a slice under |category| with the title |name|. Both strings must be
+// static constants. The track event is only recorded if |category| is enabled
+// for a tracing session.
//
// |name| must be a string with static lifetime (i.e., the same
// address must not be used for a different event name in the future). If you
// want to use a dynamically allocated name, do this:
//
+// The slice is thread-scoped (i.e., written to the default track of the current
+// thread) unless overridden with a custom track object (see Track).
+//
// TRACE_EVENT("category", nullptr, [&](perfetto::EventContext ctx) {
// ctx.event()->set_name(dynamic_name);
// });
@@ -155,18 +172,17 @@
category, name, \
::perfetto::protos::pbzero::TrackEvent::TYPE_SLICE_BEGIN, ##__VA_ARGS__)
-// End a thread-scoped slice under |category|.
+// End a slice under |category|.
#define TRACE_EVENT_END(category, ...) \
PERFETTO_INTERNAL_TRACK_EVENT( \
category, nullptr, \
::perfetto::protos::pbzero::TrackEvent::TYPE_SLICE_END, ##__VA_ARGS__)
-// Begin a thread-scoped slice which gets automatically closed when going out of
-// scope.
+// Begin a slice which gets automatically closed when going out of scope.
#define TRACE_EVENT(category, name, ...) \
PERFETTO_INTERNAL_SCOPED_TRACK_EVENT(category, name, ##__VA_ARGS__)
-// Emit a thread-scoped slice which has zero duration.
+// Emit a slice which has zero duration.
// TODO(skyostil): Add support for process-wide and global instant events.
#define TRACE_EVENT_INSTANT(category, name, ...) \
PERFETTO_INTERNAL_TRACK_EVENT( \
diff --git a/include/perfetto/tracing/track_event_legacy.h b/include/perfetto/tracing/track_event_legacy.h
new file mode 100644
index 0000000..bf83ca4
--- /dev/null
+++ b/include/perfetto/tracing/track_event_legacy.h
@@ -0,0 +1,936 @@
+/*
+ * Copyright (C) 2020 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.
+ */
+
+#ifndef INCLUDE_PERFETTO_TRACING_TRACK_EVENT_LEGACY_H_
+#define INCLUDE_PERFETTO_TRACING_TRACK_EVENT_LEGACY_H_
+
+// This file defines a compatibility shim between legacy (Chrome, V8) trace
+// event macros and track events. To avoid accidentally introducing legacy
+// events in new code, the PERFETTO_ENABLE_LEGACY_TRACE_EVENTS macro must be set
+// to 1 activate the compatibility layer.
+
+#include "perfetto/base/compiler.h"
+#include "perfetto/tracing/track_event.h"
+
+#include <stdint.h>
+
+#ifndef PERFETTO_ENABLE_LEGACY_TRACE_EVENTS
+#define PERFETTO_ENABLE_LEGACY_TRACE_EVENTS 0
+#endif
+
+#if PERFETTO_ENABLE_LEGACY_TRACE_EVENTS
+
+// Ignore GCC warning about a missing argument for a variadic macro parameter.
+#pragma GCC system_header
+
+// ----------------------------------------------------------------------------
+// Constants.
+// ----------------------------------------------------------------------------
+
+// The following constants are defined in the global namespace, since they were
+// originally implemented as macros.
+
+// Event phases.
+static constexpr char TRACE_EVENT_PHASE_BEGIN = 'B';
+static constexpr char TRACE_EVENT_PHASE_END = 'E';
+static constexpr char TRACE_EVENT_PHASE_COMPLETE = 'X';
+static constexpr char TRACE_EVENT_PHASE_INSTANT = 'I';
+static constexpr char TRACE_EVENT_PHASE_ASYNC_BEGIN = 'S';
+static constexpr char TRACE_EVENT_PHASE_ASYNC_STEP_INTO = 'T';
+static constexpr char TRACE_EVENT_PHASE_ASYNC_STEP_PAST = 'p';
+static constexpr char TRACE_EVENT_PHASE_ASYNC_END = 'F';
+static constexpr char TRACE_EVENT_PHASE_NESTABLE_ASYNC_BEGIN = 'b';
+static constexpr char TRACE_EVENT_PHASE_NESTABLE_ASYNC_END = 'e';
+static constexpr char TRACE_EVENT_PHASE_NESTABLE_ASYNC_INSTANT = 'n';
+static constexpr char TRACE_EVENT_PHASE_FLOW_BEGIN = 's';
+static constexpr char TRACE_EVENT_PHASE_FLOW_STEP = 't';
+static constexpr char TRACE_EVENT_PHASE_FLOW_END = 'f';
+static constexpr char TRACE_EVENT_PHASE_METADATA = 'M';
+static constexpr char TRACE_EVENT_PHASE_COUNTER = 'C';
+static constexpr char TRACE_EVENT_PHASE_SAMPLE = 'P';
+static constexpr char TRACE_EVENT_PHASE_CREATE_OBJECT = 'N';
+static constexpr char TRACE_EVENT_PHASE_SNAPSHOT_OBJECT = 'O';
+static constexpr char TRACE_EVENT_PHASE_DELETE_OBJECT = 'D';
+static constexpr char TRACE_EVENT_PHASE_MEMORY_DUMP = 'v';
+static constexpr char TRACE_EVENT_PHASE_MARK = 'R';
+static constexpr char TRACE_EVENT_PHASE_CLOCK_SYNC = 'c';
+static constexpr char TRACE_EVENT_PHASE_ENTER_CONTEXT = '(';
+static constexpr char TRACE_EVENT_PHASE_LEAVE_CONTEXT = ')';
+
+// Flags for changing the behavior of TRACE_EVENT_API_ADD_TRACE_EVENT.
+static constexpr uint32_t TRACE_EVENT_FLAG_NONE = 0;
+static constexpr uint32_t TRACE_EVENT_FLAG_COPY = 1u << 0;
+static constexpr uint32_t TRACE_EVENT_FLAG_HAS_ID = 1u << 1;
+// TODO(crbug.com/639003): Free this bit after ID mangling is deprecated.
+static constexpr uint32_t TRACE_EVENT_FLAG_MANGLE_ID = 1u << 2;
+static constexpr uint32_t TRACE_EVENT_FLAG_SCOPE_OFFSET = 1u << 3;
+static constexpr uint32_t TRACE_EVENT_FLAG_SCOPE_EXTRA = 1u << 4;
+static constexpr uint32_t TRACE_EVENT_FLAG_EXPLICIT_TIMESTAMP = 1u << 5;
+static constexpr uint32_t TRACE_EVENT_FLAG_ASYNC_TTS = 1u << 6;
+static constexpr uint32_t TRACE_EVENT_FLAG_BIND_TO_ENCLOSING = 1u << 7;
+static constexpr uint32_t TRACE_EVENT_FLAG_FLOW_IN = 1u << 8;
+static constexpr uint32_t TRACE_EVENT_FLAG_FLOW_OUT = 1u << 9;
+static constexpr uint32_t TRACE_EVENT_FLAG_HAS_CONTEXT_ID = 1u << 10;
+static constexpr uint32_t TRACE_EVENT_FLAG_HAS_PROCESS_ID = 1u << 11;
+static constexpr uint32_t TRACE_EVENT_FLAG_HAS_LOCAL_ID = 1u << 12;
+static constexpr uint32_t TRACE_EVENT_FLAG_HAS_GLOBAL_ID = 1u << 13;
+// TODO(eseckler): Remove once we have native support for typed proto events in
+// TRACE_EVENT macros.
+static constexpr uint32_t TRACE_EVENT_FLAG_TYPED_PROTO_ARGS = 1u << 15;
+static constexpr uint32_t TRACE_EVENT_FLAG_JAVA_STRING_LITERALS = 1u << 16;
+
+static constexpr uint32_t TRACE_EVENT_FLAG_SCOPE_MASK =
+ TRACE_EVENT_FLAG_SCOPE_OFFSET | TRACE_EVENT_FLAG_SCOPE_EXTRA;
+
+// Type values for identifying types in the TraceValue union.
+static constexpr uint8_t TRACE_VALUE_TYPE_BOOL = 1;
+static constexpr uint8_t TRACE_VALUE_TYPE_UINT = 2;
+static constexpr uint8_t TRACE_VALUE_TYPE_INT = 3;
+static constexpr uint8_t TRACE_VALUE_TYPE_DOUBLE = 4;
+static constexpr uint8_t TRACE_VALUE_TYPE_POINTER = 5;
+static constexpr uint8_t TRACE_VALUE_TYPE_STRING = 6;
+static constexpr uint8_t TRACE_VALUE_TYPE_COPY_STRING = 7;
+static constexpr uint8_t TRACE_VALUE_TYPE_CONVERTABLE = 8;
+
+// Enum reflecting the scope of an INSTANT event. Must fit within
+// TRACE_EVENT_FLAG_SCOPE_MASK.
+static constexpr uint8_t TRACE_EVENT_SCOPE_GLOBAL = 0u << 3;
+static constexpr uint8_t TRACE_EVENT_SCOPE_PROCESS = 1u << 3;
+static constexpr uint8_t TRACE_EVENT_SCOPE_THREAD = 2u << 3;
+
+static constexpr char TRACE_EVENT_SCOPE_NAME_GLOBAL = 'g';
+static constexpr char TRACE_EVENT_SCOPE_NAME_PROCESS = 'p';
+static constexpr char TRACE_EVENT_SCOPE_NAME_THREAD = 't';
+
+// ----------------------------------------------------------------------------
+// Internal legacy trace point implementation.
+// ----------------------------------------------------------------------------
+
+namespace perfetto {
+namespace internal {
+
+class TrackEventLegacy {
+ public:
+ static constexpr protos::pbzero::TrackEvent::Type PhaseToType(char phase) {
+ // clang-format off
+ return (phase == TRACE_EVENT_PHASE_BEGIN) ?
+ protos::pbzero::TrackEvent::TYPE_SLICE_BEGIN :
+ (phase == TRACE_EVENT_PHASE_END) ?
+ protos::pbzero::TrackEvent::TYPE_SLICE_END :
+ (phase == TRACE_EVENT_PHASE_INSTANT) ?
+ protos::pbzero::TrackEvent::TYPE_INSTANT :
+ protos::pbzero::TrackEvent::TYPE_UNSPECIFIED;
+ // clang-format on
+ }
+
+ // Reduce binary size overhead by outlining most of the code for writing a
+ // legacy trace event.
+ template <typename... Args>
+ static void WriteLegacyEvent(EventContext ctx,
+ char phase,
+ uint32_t flags,
+ Args&&... args) PERFETTO_NO_INLINE {
+ AddDebugAnnotations(&ctx, std::forward<Args>(args)...);
+ SetTrackIfNeeded(&ctx, flags);
+ if (PhaseToType(phase) == protos::pbzero::TrackEvent::TYPE_UNSPECIFIED) {
+ auto legacy_event = ctx.event()->set_legacy_event();
+ legacy_event->set_phase(phase);
+ }
+ }
+
+ // No arguments.
+ static void AddDebugAnnotations(EventContext*) {}
+
+ // One argument.
+ template <typename ArgType>
+ static void AddDebugAnnotations(EventContext* ctx,
+ const char* arg_name,
+ ArgType&& arg_value) {
+ TrackEventInternal::AddDebugAnnotation(ctx, arg_name, arg_value);
+ }
+
+ // Two arguments.
+ template <typename ArgType, typename ArgType2>
+ static void AddDebugAnnotations(EventContext* ctx,
+ const char* arg_name,
+ ArgType&& arg_value,
+ const char* arg_name2,
+ ArgType2&& arg_value2) {
+ TrackEventInternal::AddDebugAnnotation(ctx, arg_name, arg_value);
+ TrackEventInternal::AddDebugAnnotation(ctx, arg_name2, arg_value2);
+ }
+
+ private:
+ static void SetTrackIfNeeded(EventContext* ctx, uint32_t flags) {
+ auto scope = flags & TRACE_EVENT_FLAG_SCOPE_MASK;
+ switch (scope) {
+ case TRACE_EVENT_SCOPE_GLOBAL:
+ ctx->event()->set_track_uuid(0);
+ break;
+ case TRACE_EVENT_SCOPE_PROCESS:
+ ctx->event()->set_track_uuid(ProcessTrack::Current().uuid);
+ break;
+ default:
+ case TRACE_EVENT_SCOPE_THREAD:
+ // Thread scope is already the default.
+ break;
+ }
+ }
+};
+
+} // namespace internal
+} // namespace perfetto
+
+// A black hole trace point where unsupported trace events are routed.
+#define PERFETTO_INTERNAL_EVENT_NOOP(cat, name, ...) \
+ do { \
+ if (false) { \
+ ::perfetto::base::ignore_result(cat); \
+ ::perfetto::base::ignore_result(name); \
+ } \
+ } while (false)
+
+// Implementations for the INTERNAL_* adapter macros used by the trace points
+// below.
+#define INTERNAL_TRACE_EVENT_ADD(phase, category, name, flags, ...) \
+ PERFETTO_INTERNAL_TRACK_EVENT( \
+ category, name, \
+ ::perfetto::internal::TrackEventLegacy::PhaseToType(phase), \
+ [&](perfetto::EventContext ctx) { \
+ using ::perfetto::internal::TrackEventLegacy; \
+ TrackEventLegacy::WriteLegacyEvent(std::move(ctx), phase, flags, \
+ ##__VA_ARGS__); \
+ })
+
+#define INTERNAL_TRACE_EVENT_ADD_SCOPED(category, name, ...) \
+ PERFETTO_INTERNAL_SCOPED_TRACK_EVENT( \
+ category, name, [&](perfetto::EventContext ctx) { \
+ using ::perfetto::internal::TrackEventLegacy; \
+ TrackEventLegacy::AddDebugAnnotations(&ctx, ##__VA_ARGS__); \
+ })
+
+#define INTERNAL_TRACE_EVENT_ADD_SCOPED_WITH_FLOW(...) \
+ PERFETTO_INTERNAL_EVENT_NOOP(__VA_ARGS__)
+#define INTERNAL_TRACE_EVENT_ADD_WITH_TIMESTAMP(...) \
+ PERFETTO_INTERNAL_EVENT_NOOP(__VA_ARGS__)
+#define INTERNAL_TRACE_EVENT_ADD_WITH_ID_TID_AND_TIMESTAMP(...) \
+ PERFETTO_INTERNAL_EVENT_NOOP(__VA_ARGS__)
+#define INTERNAL_TRACE_EVENT_ADD_WITH_ID(...) \
+ PERFETTO_INTERNAL_EVENT_NOOP(__VA_ARGS__)
+#define INTERNAL_TRACE_EVENT_METADATA_ADD(...) \
+ PERFETTO_INTERNAL_EVENT_NOOP(__VA_ARGS__)
+
+#define INTERNAL_TRACE_TIME_TICKS_NOW() 0
+#define INTERNAL_TRACE_TIME_NOW() 0
+
+// ----------------------------------------------------------------------------
+// Legacy tracing common API (adapted from trace_event_common.h).
+// ----------------------------------------------------------------------------
+
+#define TRACE_DISABLED_BY_DEFAULT(name) "disabled-by-default-" name
+
+// Scoped events.
+#define TRACE_EVENT0(category_group, name) \
+ INTERNAL_TRACE_EVENT_ADD_SCOPED(category_group, name)
+#define TRACE_EVENT_WITH_FLOW0(category_group, name, bind_id, flow_flags) \
+ INTERNAL_TRACE_EVENT_ADD_SCOPED_WITH_FLOW(category_group, name, bind_id, \
+ flow_flags)
+#define TRACE_EVENT1(category_group, name, arg1_name, arg1_val) \
+ INTERNAL_TRACE_EVENT_ADD_SCOPED(category_group, name, arg1_name, arg1_val)
+#define TRACE_EVENT_WITH_FLOW1(category_group, name, bind_id, flow_flags, \
+ arg1_name, arg1_val) \
+ INTERNAL_TRACE_EVENT_ADD_SCOPED_WITH_FLOW(category_group, name, bind_id, \
+ flow_flags, arg1_name, arg1_val)
+#define TRACE_EVENT2(category_group, name, arg1_name, arg1_val, arg2_name, \
+ arg2_val) \
+ INTERNAL_TRACE_EVENT_ADD_SCOPED(category_group, name, arg1_name, arg1_val, \
+ arg2_name, arg2_val)
+#define TRACE_EVENT_WITH_FLOW2(category_group, name, bind_id, flow_flags, \
+ arg1_name, arg1_val, arg2_name, arg2_val) \
+ INTERNAL_TRACE_EVENT_ADD_SCOPED_WITH_FLOW(category_group, name, bind_id, \
+ flow_flags, arg1_name, arg1_val, \
+ arg2_name, arg2_val)
+
+// Instant events.
+#define TRACE_EVENT_INSTANT0(category_group, name, scope) \
+ INTERNAL_TRACE_EVENT_ADD(TRACE_EVENT_PHASE_INSTANT, category_group, name, \
+ TRACE_EVENT_FLAG_NONE | scope)
+#define TRACE_EVENT_INSTANT1(category_group, name, scope, arg1_name, arg1_val) \
+ INTERNAL_TRACE_EVENT_ADD(TRACE_EVENT_PHASE_INSTANT, category_group, name, \
+ TRACE_EVENT_FLAG_NONE | scope, arg1_name, arg1_val)
+#define TRACE_EVENT_INSTANT2(category_group, name, scope, arg1_name, arg1_val, \
+ arg2_name, arg2_val) \
+ INTERNAL_TRACE_EVENT_ADD(TRACE_EVENT_PHASE_INSTANT, category_group, name, \
+ TRACE_EVENT_FLAG_NONE | scope, arg1_name, arg1_val, \
+ arg2_name, arg2_val)
+#define TRACE_EVENT_COPY_INSTANT0(category_group, name, scope) \
+ INTERNAL_TRACE_EVENT_ADD(TRACE_EVENT_PHASE_INSTANT, category_group, name, \
+ TRACE_EVENT_FLAG_COPY | scope)
+#define TRACE_EVENT_COPY_INSTANT1(category_group, name, scope, arg1_name, \
+ arg1_val) \
+ INTERNAL_TRACE_EVENT_ADD(TRACE_EVENT_PHASE_INSTANT, category_group, name, \
+ TRACE_EVENT_FLAG_COPY | scope, arg1_name, arg1_val)
+#define TRACE_EVENT_COPY_INSTANT2(category_group, name, scope, arg1_name, \
+ arg1_val, arg2_name, arg2_val) \
+ INTERNAL_TRACE_EVENT_ADD(TRACE_EVENT_PHASE_INSTANT, category_group, name, \
+ TRACE_EVENT_FLAG_COPY | scope, arg1_name, arg1_val, \
+ arg2_name, arg2_val)
+#define TRACE_EVENT_INSTANT_WITH_FLAGS0(category_group, name, scope_and_flags) \
+ INTERNAL_TRACE_EVENT_ADD(TRACE_EVENT_PHASE_INSTANT, category_group, name, \
+ scope_and_flags)
+#define TRACE_EVENT_INSTANT_WITH_FLAGS1(category_group, name, scope_and_flags, \
+ arg1_name, arg1_val) \
+ INTERNAL_TRACE_EVENT_ADD(TRACE_EVENT_PHASE_INSTANT, category_group, name, \
+ scope_and_flags, arg1_name, arg1_val)
+
+// Instant events with explicit timestamps.
+#define TRACE_EVENT_INSTANT_WITH_TIMESTAMP0(category_group, name, scope, \
+ timestamp) \
+ INTERNAL_TRACE_EVENT_ADD_WITH_TIMESTAMP(TRACE_EVENT_PHASE_INSTANT, \
+ category_group, name, timestamp, \
+ TRACE_EVENT_FLAG_NONE | scope)
+
+#define TRACE_EVENT_INSTANT_WITH_TIMESTAMP1(category_group, name, scope, \
+ timestamp, arg_name, arg_val) \
+ INTERNAL_TRACE_EVENT_ADD_WITH_TIMESTAMP( \
+ TRACE_EVENT_PHASE_INSTANT, category_group, name, timestamp, \
+ TRACE_EVENT_FLAG_NONE | scope, arg_name, arg_val)
+
+// Begin events.
+#define TRACE_EVENT_BEGIN0(category_group, name) \
+ INTERNAL_TRACE_EVENT_ADD(TRACE_EVENT_PHASE_BEGIN, category_group, name, \
+ TRACE_EVENT_FLAG_NONE)
+#define TRACE_EVENT_BEGIN1(category_group, name, arg1_name, arg1_val) \
+ INTERNAL_TRACE_EVENT_ADD(TRACE_EVENT_PHASE_BEGIN, category_group, name, \
+ TRACE_EVENT_FLAG_NONE, arg1_name, arg1_val)
+#define TRACE_EVENT_BEGIN2(category_group, name, arg1_name, arg1_val, \
+ arg2_name, arg2_val) \
+ INTERNAL_TRACE_EVENT_ADD(TRACE_EVENT_PHASE_BEGIN, category_group, name, \
+ TRACE_EVENT_FLAG_NONE, arg1_name, arg1_val, \
+ arg2_name, arg2_val)
+#define TRACE_EVENT_BEGIN_WITH_FLAGS0(category_group, name, flags) \
+ INTERNAL_TRACE_EVENT_ADD(TRACE_EVENT_PHASE_BEGIN, category_group, name, flags)
+#define TRACE_EVENT_BEGIN_WITH_FLAGS1(category_group, name, flags, arg1_name, \
+ arg1_val) \
+ INTERNAL_TRACE_EVENT_ADD(TRACE_EVENT_PHASE_BEGIN, category_group, name, \
+ flags, arg1_name, arg1_val)
+#define TRACE_EVENT_COPY_BEGIN2(category_group, name, arg1_name, arg1_val, \
+ arg2_name, arg2_val) \
+ INTERNAL_TRACE_EVENT_ADD(TRACE_EVENT_PHASE_BEGIN, category_group, name, \
+ TRACE_EVENT_FLAG_COPY, arg1_name, arg1_val, \
+ arg2_name, arg2_val)
+
+// Begin events with explicit timestamps.
+#define TRACE_EVENT_BEGIN_WITH_ID_TID_AND_TIMESTAMP0(category_group, name, id, \
+ thread_id, timestamp) \
+ INTERNAL_TRACE_EVENT_ADD_WITH_ID_TID_AND_TIMESTAMP( \
+ TRACE_EVENT_PHASE_ASYNC_BEGIN, category_group, name, id, thread_id, \
+ timestamp, TRACE_EVENT_FLAG_NONE)
+#define TRACE_EVENT_COPY_BEGIN_WITH_ID_TID_AND_TIMESTAMP0( \
+ category_group, name, id, thread_id, timestamp) \
+ INTERNAL_TRACE_EVENT_ADD_WITH_ID_TID_AND_TIMESTAMP( \
+ TRACE_EVENT_PHASE_ASYNC_BEGIN, category_group, name, id, thread_id, \
+ timestamp, TRACE_EVENT_FLAG_COPY)
+#define TRACE_EVENT_COPY_BEGIN_WITH_ID_TID_AND_TIMESTAMP1( \
+ category_group, name, id, thread_id, timestamp, arg1_name, arg1_val) \
+ INTERNAL_TRACE_EVENT_ADD_WITH_ID_TID_AND_TIMESTAMP( \
+ TRACE_EVENT_PHASE_ASYNC_BEGIN, category_group, name, id, thread_id, \
+ timestamp, TRACE_EVENT_FLAG_COPY, arg1_name, arg1_val)
+#define TRACE_EVENT_COPY_BEGIN_WITH_ID_TID_AND_TIMESTAMP2( \
+ category_group, name, id, thread_id, timestamp, arg1_name, arg1_val, \
+ arg2_name, arg2_val) \
+ INTERNAL_TRACE_EVENT_ADD_WITH_ID_TID_AND_TIMESTAMP( \
+ TRACE_EVENT_PHASE_ASYNC_BEGIN, category_group, name, id, thread_id, \
+ timestamp, TRACE_EVENT_FLAG_COPY, arg1_name, arg1_val, arg2_name, \
+ arg2_val)
+
+// End events.
+#define TRACE_EVENT_END0(category_group, name) \
+ INTERNAL_TRACE_EVENT_ADD(TRACE_EVENT_PHASE_END, category_group, name, \
+ TRACE_EVENT_FLAG_NONE)
+#define TRACE_EVENT_END1(category_group, name, arg1_name, arg1_val) \
+ INTERNAL_TRACE_EVENT_ADD(TRACE_EVENT_PHASE_END, category_group, name, \
+ TRACE_EVENT_FLAG_NONE, arg1_name, arg1_val)
+#define TRACE_EVENT_END2(category_group, name, arg1_name, arg1_val, arg2_name, \
+ arg2_val) \
+ INTERNAL_TRACE_EVENT_ADD(TRACE_EVENT_PHASE_END, category_group, name, \
+ TRACE_EVENT_FLAG_NONE, arg1_name, arg1_val, \
+ arg2_name, arg2_val)
+#define TRACE_EVENT_END_WITH_FLAGS0(category_group, name, flags) \
+ INTERNAL_TRACE_EVENT_ADD(TRACE_EVENT_PHASE_END, category_group, name, flags)
+#define TRACE_EVENT_END_WITH_FLAGS1(category_group, name, flags, arg1_name, \
+ arg1_val) \
+ INTERNAL_TRACE_EVENT_ADD(TRACE_EVENT_PHASE_END, category_group, name, flags, \
+ arg1_name, arg1_val)
+#define TRACE_EVENT_COPY_END2(category_group, name, arg1_name, arg1_val, \
+ arg2_name, arg2_val) \
+ INTERNAL_TRACE_EVENT_ADD(TRACE_EVENT_PHASE_END, category_group, name, \
+ TRACE_EVENT_FLAG_COPY, arg1_name, arg1_val, \
+ arg2_name, arg2_val)
+
+// Mark events.
+#define TRACE_EVENT_MARK_WITH_TIMESTAMP0(category_group, name, timestamp) \
+ INTERNAL_TRACE_EVENT_ADD_WITH_TIMESTAMP(TRACE_EVENT_PHASE_MARK, \
+ category_group, name, timestamp, \
+ TRACE_EVENT_FLAG_NONE)
+
+#define TRACE_EVENT_MARK_WITH_TIMESTAMP1(category_group, name, timestamp, \
+ arg1_name, arg1_val) \
+ INTERNAL_TRACE_EVENT_ADD_WITH_TIMESTAMP( \
+ TRACE_EVENT_PHASE_MARK, category_group, name, timestamp, \
+ TRACE_EVENT_FLAG_NONE, arg1_name, arg1_val)
+
+#define TRACE_EVENT_MARK_WITH_TIMESTAMP2( \
+ category_group, name, timestamp, arg1_name, arg1_val, arg2_name, arg2_val) \
+ INTERNAL_TRACE_EVENT_ADD_WITH_TIMESTAMP( \
+ TRACE_EVENT_PHASE_MARK, category_group, name, timestamp, \
+ TRACE_EVENT_FLAG_NONE, arg1_name, arg1_val, arg2_name, arg2_val)
+
+#define TRACE_EVENT_COPY_MARK(category_group, name) \
+ INTERNAL_TRACE_EVENT_ADD(TRACE_EVENT_PHASE_MARK, category_group, name, \
+ TRACE_EVENT_FLAG_COPY)
+
+#define TRACE_EVENT_COPY_MARK1(category_group, name, arg1_name, arg1_val) \
+ INTERNAL_TRACE_EVENT_ADD(TRACE_EVENT_PHASE_MARK, category_group, name, \
+ TRACE_EVENT_FLAG_COPY, arg1_name, arg1_val)
+
+#define TRACE_EVENT_COPY_MARK_WITH_TIMESTAMP(category_group, name, timestamp) \
+ INTERNAL_TRACE_EVENT_ADD_WITH_TIMESTAMP(TRACE_EVENT_PHASE_MARK, \
+ category_group, name, timestamp, \
+ TRACE_EVENT_FLAG_COPY)
+
+// End events with explicit thread and timestamp.
+#define TRACE_EVENT_END_WITH_ID_TID_AND_TIMESTAMP0(category_group, name, id, \
+ thread_id, timestamp) \
+ INTERNAL_TRACE_EVENT_ADD_WITH_ID_TID_AND_TIMESTAMP( \
+ TRACE_EVENT_PHASE_ASYNC_END, category_group, name, id, thread_id, \
+ timestamp, TRACE_EVENT_FLAG_NONE)
+#define TRACE_EVENT_COPY_END_WITH_ID_TID_AND_TIMESTAMP0( \
+ category_group, name, id, thread_id, timestamp) \
+ INTERNAL_TRACE_EVENT_ADD_WITH_ID_TID_AND_TIMESTAMP( \
+ TRACE_EVENT_PHASE_ASYNC_END, category_group, name, id, thread_id, \
+ timestamp, TRACE_EVENT_FLAG_COPY)
+#define TRACE_EVENT_COPY_END_WITH_ID_TID_AND_TIMESTAMP1( \
+ category_group, name, id, thread_id, timestamp, arg1_name, arg1_val) \
+ INTERNAL_TRACE_EVENT_ADD_WITH_ID_TID_AND_TIMESTAMP( \
+ TRACE_EVENT_PHASE_ASYNC_END, category_group, name, id, thread_id, \
+ timestamp, TRACE_EVENT_FLAG_COPY, arg1_name, arg1_val)
+#define TRACE_EVENT_COPY_END_WITH_ID_TID_AND_TIMESTAMP2( \
+ category_group, name, id, thread_id, timestamp, arg1_name, arg1_val, \
+ arg2_name, arg2_val) \
+ INTERNAL_TRACE_EVENT_ADD_WITH_ID_TID_AND_TIMESTAMP( \
+ TRACE_EVENT_PHASE_ASYNC_END, category_group, name, id, thread_id, \
+ timestamp, TRACE_EVENT_FLAG_COPY, arg1_name, arg1_val, arg2_name, \
+ arg2_val)
+
+// Counters.
+#define TRACE_COUNTER1(category_group, name, value) \
+ INTERNAL_TRACE_EVENT_ADD(TRACE_EVENT_PHASE_COUNTER, category_group, name, \
+ TRACE_EVENT_FLAG_NONE, "value", \
+ static_cast<int>(value))
+#define TRACE_COUNTER_WITH_FLAG1(category_group, name, flag, value) \
+ INTERNAL_TRACE_EVENT_ADD(TRACE_EVENT_PHASE_COUNTER, category_group, name, \
+ flag, "value", static_cast<int>(value))
+#define TRACE_COPY_COUNTER1(category_group, name, value) \
+ INTERNAL_TRACE_EVENT_ADD(TRACE_EVENT_PHASE_COUNTER, category_group, name, \
+ TRACE_EVENT_FLAG_COPY, "value", \
+ static_cast<int>(value))
+#define TRACE_COUNTER2(category_group, name, value1_name, value1_val, \
+ value2_name, value2_val) \
+ INTERNAL_TRACE_EVENT_ADD(TRACE_EVENT_PHASE_COUNTER, category_group, name, \
+ TRACE_EVENT_FLAG_NONE, value1_name, \
+ static_cast<int>(value1_val), value2_name, \
+ static_cast<int>(value2_val))
+#define TRACE_COPY_COUNTER2(category_group, name, value1_name, value1_val, \
+ value2_name, value2_val) \
+ INTERNAL_TRACE_EVENT_ADD(TRACE_EVENT_PHASE_COUNTER, category_group, name, \
+ TRACE_EVENT_FLAG_COPY, value1_name, \
+ static_cast<int>(value1_val), value2_name, \
+ static_cast<int>(value2_val))
+
+// Counters with explicit timestamps.
+#define TRACE_COUNTER_WITH_TIMESTAMP1(category_group, name, timestamp, value) \
+ INTERNAL_TRACE_EVENT_ADD_WITH_TIMESTAMP( \
+ TRACE_EVENT_PHASE_COUNTER, category_group, name, timestamp, \
+ TRACE_EVENT_FLAG_NONE, "value", static_cast<int>(value))
+
+#define TRACE_COUNTER_WITH_TIMESTAMP2(category_group, name, timestamp, \
+ value1_name, value1_val, value2_name, \
+ value2_val) \
+ INTERNAL_TRACE_EVENT_ADD_WITH_TIMESTAMP( \
+ TRACE_EVENT_PHASE_COUNTER, category_group, name, timestamp, \
+ TRACE_EVENT_FLAG_NONE, value1_name, static_cast<int>(value1_val), \
+ value2_name, static_cast<int>(value2_val))
+
+// Counters with ids.
+#define TRACE_COUNTER_ID1(category_group, name, id, value) \
+ INTERNAL_TRACE_EVENT_ADD_WITH_ID(TRACE_EVENT_PHASE_COUNTER, category_group, \
+ name, id, TRACE_EVENT_FLAG_NONE, "value", \
+ static_cast<int>(value))
+#define TRACE_COPY_COUNTER_ID1(category_group, name, id, value) \
+ INTERNAL_TRACE_EVENT_ADD_WITH_ID(TRACE_EVENT_PHASE_COUNTER, category_group, \
+ name, id, TRACE_EVENT_FLAG_COPY, "value", \
+ static_cast<int>(value))
+#define TRACE_COUNTER_ID2(category_group, name, id, value1_name, value1_val, \
+ value2_name, value2_val) \
+ INTERNAL_TRACE_EVENT_ADD_WITH_ID(TRACE_EVENT_PHASE_COUNTER, category_group, \
+ name, id, TRACE_EVENT_FLAG_NONE, \
+ value1_name, static_cast<int>(value1_val), \
+ value2_name, static_cast<int>(value2_val))
+#define TRACE_COPY_COUNTER_ID2(category_group, name, id, value1_name, \
+ value1_val, value2_name, value2_val) \
+ INTERNAL_TRACE_EVENT_ADD_WITH_ID(TRACE_EVENT_PHASE_COUNTER, category_group, \
+ name, id, TRACE_EVENT_FLAG_COPY, \
+ value1_name, static_cast<int>(value1_val), \
+ value2_name, static_cast<int>(value2_val))
+
+// Sampling profiler events.
+#define TRACE_EVENT_SAMPLE_WITH_ID1(category_group, name, id, arg1_name, \
+ arg1_val) \
+ INTERNAL_TRACE_EVENT_ADD_WITH_ID(TRACE_EVENT_PHASE_SAMPLE, category_group, \
+ name, id, TRACE_EVENT_FLAG_NONE, arg1_name, \
+ arg1_val)
+
+// Legacy async events.
+#define TRACE_EVENT_ASYNC_BEGIN0(category_group, name, id) \
+ INTERNAL_TRACE_EVENT_ADD_WITH_ID(TRACE_EVENT_PHASE_ASYNC_BEGIN, \
+ category_group, name, id, \
+ TRACE_EVENT_FLAG_NONE)
+#define TRACE_EVENT_ASYNC_BEGIN1(category_group, name, id, arg1_name, \
+ arg1_val) \
+ INTERNAL_TRACE_EVENT_ADD_WITH_ID(TRACE_EVENT_PHASE_ASYNC_BEGIN, \
+ category_group, name, id, \
+ TRACE_EVENT_FLAG_NONE, arg1_name, arg1_val)
+#define TRACE_EVENT_ASYNC_BEGIN2(category_group, name, id, arg1_name, \
+ arg1_val, arg2_name, arg2_val) \
+ INTERNAL_TRACE_EVENT_ADD_WITH_ID( \
+ TRACE_EVENT_PHASE_ASYNC_BEGIN, category_group, name, id, \
+ TRACE_EVENT_FLAG_NONE, arg1_name, arg1_val, arg2_name, arg2_val)
+#define TRACE_EVENT_COPY_ASYNC_BEGIN0(category_group, name, id) \
+ INTERNAL_TRACE_EVENT_ADD_WITH_ID(TRACE_EVENT_PHASE_ASYNC_BEGIN, \
+ category_group, name, id, \
+ TRACE_EVENT_FLAG_COPY)
+#define TRACE_EVENT_COPY_ASYNC_BEGIN1(category_group, name, id, arg1_name, \
+ arg1_val) \
+ INTERNAL_TRACE_EVENT_ADD_WITH_ID(TRACE_EVENT_PHASE_ASYNC_BEGIN, \
+ category_group, name, id, \
+ TRACE_EVENT_FLAG_COPY, arg1_name, arg1_val)
+#define TRACE_EVENT_COPY_ASYNC_BEGIN2(category_group, name, id, arg1_name, \
+ arg1_val, arg2_name, arg2_val) \
+ INTERNAL_TRACE_EVENT_ADD_WITH_ID( \
+ TRACE_EVENT_PHASE_ASYNC_BEGIN, category_group, name, id, \
+ TRACE_EVENT_FLAG_COPY, arg1_name, arg1_val, arg2_name, arg2_val)
+#define TRACE_EVENT_ASYNC_BEGIN_WITH_FLAGS0(category_group, name, id, flags) \
+ INTERNAL_TRACE_EVENT_ADD_WITH_ID(TRACE_EVENT_PHASE_ASYNC_BEGIN, \
+ category_group, name, id, flags)
+
+// Legacy async events with explicit timestamps.
+#define TRACE_EVENT_ASYNC_BEGIN_WITH_TIMESTAMP0(category_group, name, id, \
+ timestamp) \
+ INTERNAL_TRACE_EVENT_ADD_WITH_ID_TID_AND_TIMESTAMP( \
+ TRACE_EVENT_PHASE_ASYNC_BEGIN, category_group, name, id, \
+ TRACE_EVENT_API_CURRENT_THREAD_ID, timestamp, TRACE_EVENT_FLAG_NONE)
+#define TRACE_EVENT_ASYNC_BEGIN_WITH_TIMESTAMP1( \
+ category_group, name, id, timestamp, arg1_name, arg1_val) \
+ INTERNAL_TRACE_EVENT_ADD_WITH_ID_TID_AND_TIMESTAMP( \
+ TRACE_EVENT_PHASE_ASYNC_BEGIN, category_group, name, id, \
+ TRACE_EVENT_API_CURRENT_THREAD_ID, timestamp, TRACE_EVENT_FLAG_NONE, \
+ arg1_name, arg1_val)
+#define TRACE_EVENT_ASYNC_BEGIN_WITH_TIMESTAMP2(category_group, name, id, \
+ timestamp, arg1_name, \
+ arg1_val, arg2_name, arg2_val) \
+ INTERNAL_TRACE_EVENT_ADD_WITH_ID_TID_AND_TIMESTAMP( \
+ TRACE_EVENT_PHASE_ASYNC_BEGIN, category_group, name, id, \
+ TRACE_EVENT_API_CURRENT_THREAD_ID, timestamp, TRACE_EVENT_FLAG_NONE, \
+ arg1_name, arg1_val, arg2_name, arg2_val)
+#define TRACE_EVENT_COPY_ASYNC_BEGIN_WITH_TIMESTAMP0(category_group, name, id, \
+ timestamp) \
+ INTERNAL_TRACE_EVENT_ADD_WITH_ID_TID_AND_TIMESTAMP( \
+ TRACE_EVENT_PHASE_ASYNC_BEGIN, category_group, name, id, \
+ TRACE_EVENT_API_CURRENT_THREAD_ID, timestamp, TRACE_EVENT_FLAG_COPY)
+#define TRACE_EVENT_ASYNC_BEGIN_WITH_TIMESTAMP_AND_FLAGS0( \
+ category_group, name, id, timestamp, flags) \
+ INTERNAL_TRACE_EVENT_ADD_WITH_ID_TID_AND_TIMESTAMP( \
+ TRACE_EVENT_PHASE_ASYNC_BEGIN, category_group, name, id, \
+ TRACE_EVENT_API_CURRENT_THREAD_ID, timestamp, flags)
+
+// Legacy async step into events.
+#define TRACE_EVENT_ASYNC_STEP_INTO0(category_group, name, id, step) \
+ INTERNAL_TRACE_EVENT_ADD_WITH_ID(TRACE_EVENT_PHASE_ASYNC_STEP_INTO, \
+ category_group, name, id, \
+ TRACE_EVENT_FLAG_NONE, "step", step)
+#define TRACE_EVENT_ASYNC_STEP_INTO1(category_group, name, id, step, \
+ arg1_name, arg1_val) \
+ INTERNAL_TRACE_EVENT_ADD_WITH_ID( \
+ TRACE_EVENT_PHASE_ASYNC_STEP_INTO, category_group, name, id, \
+ TRACE_EVENT_FLAG_NONE, "step", step, arg1_name, arg1_val)
+
+// Legacy async step into events with timestamps.
+#define TRACE_EVENT_ASYNC_STEP_INTO_WITH_TIMESTAMP0(category_group, name, id, \
+ step, timestamp) \
+ INTERNAL_TRACE_EVENT_ADD_WITH_ID_TID_AND_TIMESTAMP( \
+ TRACE_EVENT_PHASE_ASYNC_STEP_INTO, category_group, name, id, \
+ TRACE_EVENT_API_CURRENT_THREAD_ID, timestamp, TRACE_EVENT_FLAG_NONE, \
+ "step", step)
+
+// Legacy async step past events.
+#define TRACE_EVENT_ASYNC_STEP_PAST0(category_group, name, id, step) \
+ INTERNAL_TRACE_EVENT_ADD_WITH_ID(TRACE_EVENT_PHASE_ASYNC_STEP_PAST, \
+ category_group, name, id, \
+ TRACE_EVENT_FLAG_NONE, "step", step)
+#define TRACE_EVENT_ASYNC_STEP_PAST1(category_group, name, id, step, \
+ arg1_name, arg1_val) \
+ INTERNAL_TRACE_EVENT_ADD_WITH_ID( \
+ TRACE_EVENT_PHASE_ASYNC_STEP_PAST, category_group, name, id, \
+ TRACE_EVENT_FLAG_NONE, "step", step, arg1_name, arg1_val)
+
+// Legacy async end events.
+#define TRACE_EVENT_ASYNC_END0(category_group, name, id) \
+ INTERNAL_TRACE_EVENT_ADD_WITH_ID(TRACE_EVENT_PHASE_ASYNC_END, \
+ category_group, name, id, \
+ TRACE_EVENT_FLAG_NONE)
+#define TRACE_EVENT_ASYNC_END1(category_group, name, id, arg1_name, arg1_val) \
+ INTERNAL_TRACE_EVENT_ADD_WITH_ID(TRACE_EVENT_PHASE_ASYNC_END, \
+ category_group, name, id, \
+ TRACE_EVENT_FLAG_NONE, arg1_name, arg1_val)
+#define TRACE_EVENT_ASYNC_END2(category_group, name, id, arg1_name, arg1_val, \
+ arg2_name, arg2_val) \
+ INTERNAL_TRACE_EVENT_ADD_WITH_ID( \
+ TRACE_EVENT_PHASE_ASYNC_END, category_group, name, id, \
+ TRACE_EVENT_FLAG_NONE, arg1_name, arg1_val, arg2_name, arg2_val)
+#define TRACE_EVENT_COPY_ASYNC_END0(category_group, name, id) \
+ INTERNAL_TRACE_EVENT_ADD_WITH_ID(TRACE_EVENT_PHASE_ASYNC_END, \
+ category_group, name, id, \
+ TRACE_EVENT_FLAG_COPY)
+#define TRACE_EVENT_COPY_ASYNC_END1(category_group, name, id, arg1_name, \
+ arg1_val) \
+ INTERNAL_TRACE_EVENT_ADD_WITH_ID(TRACE_EVENT_PHASE_ASYNC_END, \
+ category_group, name, id, \
+ TRACE_EVENT_FLAG_COPY, arg1_name, arg1_val)
+#define TRACE_EVENT_COPY_ASYNC_END2(category_group, name, id, arg1_name, \
+ arg1_val, arg2_name, arg2_val) \
+ INTERNAL_TRACE_EVENT_ADD_WITH_ID( \
+ TRACE_EVENT_PHASE_ASYNC_END, category_group, name, id, \
+ TRACE_EVENT_FLAG_COPY, arg1_name, arg1_val, arg2_name, arg2_val)
+#define TRACE_EVENT_ASYNC_END_WITH_FLAGS0(category_group, name, id, flags) \
+ INTERNAL_TRACE_EVENT_ADD_WITH_ID(TRACE_EVENT_PHASE_ASYNC_END, \
+ category_group, name, id, flags)
+
+// Legacy async end events with explicit timestamps.
+#define TRACE_EVENT_ASYNC_END_WITH_TIMESTAMP0(category_group, name, id, \
+ timestamp) \
+ INTERNAL_TRACE_EVENT_ADD_WITH_ID_TID_AND_TIMESTAMP( \
+ TRACE_EVENT_PHASE_ASYNC_END, category_group, name, id, \
+ TRACE_EVENT_API_CURRENT_THREAD_ID, timestamp, TRACE_EVENT_FLAG_NONE)
+#define TRACE_EVENT_ASYNC_END_WITH_TIMESTAMP1(category_group, name, id, \
+ timestamp, arg1_name, arg1_val) \
+ INTERNAL_TRACE_EVENT_ADD_WITH_ID_TID_AND_TIMESTAMP( \
+ TRACE_EVENT_PHASE_ASYNC_END, category_group, name, id, \
+ TRACE_EVENT_API_CURRENT_THREAD_ID, timestamp, TRACE_EVENT_FLAG_NONE, \
+ arg1_name, arg1_val)
+#define TRACE_EVENT_ASYNC_END_WITH_TIMESTAMP2(category_group, name, id, \
+ timestamp, arg1_name, arg1_val, \
+ arg2_name, arg2_val) \
+ INTERNAL_TRACE_EVENT_ADD_WITH_ID_TID_AND_TIMESTAMP( \
+ TRACE_EVENT_PHASE_ASYNC_END, category_group, name, id, \
+ TRACE_EVENT_API_CURRENT_THREAD_ID, timestamp, TRACE_EVENT_FLAG_NONE, \
+ arg1_name, arg1_val, arg2_name, arg2_val)
+#define TRACE_EVENT_COPY_ASYNC_END_WITH_TIMESTAMP0(category_group, name, id, \
+ timestamp) \
+ INTERNAL_TRACE_EVENT_ADD_WITH_ID_TID_AND_TIMESTAMP( \
+ TRACE_EVENT_PHASE_ASYNC_END, category_group, name, id, \
+ TRACE_EVENT_API_CURRENT_THREAD_ID, timestamp, TRACE_EVENT_FLAG_COPY)
+#define TRACE_EVENT_ASYNC_END_WITH_TIMESTAMP_AND_FLAGS0(category_group, name, \
+ id, timestamp, flags) \
+ INTERNAL_TRACE_EVENT_ADD_WITH_ID_TID_AND_TIMESTAMP( \
+ TRACE_EVENT_PHASE_ASYNC_END, category_group, name, id, \
+ TRACE_EVENT_API_CURRENT_THREAD_ID, timestamp, flags)
+
+// Async events.
+#define TRACE_EVENT_NESTABLE_ASYNC_BEGIN0(category_group, name, id) \
+ INTERNAL_TRACE_EVENT_ADD_WITH_ID(TRACE_EVENT_PHASE_NESTABLE_ASYNC_BEGIN, \
+ category_group, name, id, \
+ TRACE_EVENT_FLAG_NONE)
+#define TRACE_EVENT_NESTABLE_ASYNC_BEGIN1(category_group, name, id, arg1_name, \
+ arg1_val) \
+ INTERNAL_TRACE_EVENT_ADD_WITH_ID(TRACE_EVENT_PHASE_NESTABLE_ASYNC_BEGIN, \
+ category_group, name, id, \
+ TRACE_EVENT_FLAG_NONE, arg1_name, arg1_val)
+#define TRACE_EVENT_NESTABLE_ASYNC_BEGIN2(category_group, name, id, arg1_name, \
+ arg1_val, arg2_name, arg2_val) \
+ INTERNAL_TRACE_EVENT_ADD_WITH_ID( \
+ TRACE_EVENT_PHASE_NESTABLE_ASYNC_BEGIN, category_group, name, id, \
+ TRACE_EVENT_FLAG_NONE, arg1_name, arg1_val, arg2_name, arg2_val)
+
+// Async end events.
+#define TRACE_EVENT_NESTABLE_ASYNC_END0(category_group, name, id) \
+ INTERNAL_TRACE_EVENT_ADD_WITH_ID(TRACE_EVENT_PHASE_NESTABLE_ASYNC_END, \
+ category_group, name, id, \
+ TRACE_EVENT_FLAG_NONE)
+#define TRACE_EVENT_NESTABLE_ASYNC_END1(category_group, name, id, arg1_name, \
+ arg1_val) \
+ INTERNAL_TRACE_EVENT_ADD_WITH_ID(TRACE_EVENT_PHASE_NESTABLE_ASYNC_END, \
+ category_group, name, id, \
+ TRACE_EVENT_FLAG_NONE, arg1_name, arg1_val)
+#define TRACE_EVENT_NESTABLE_ASYNC_END2(category_group, name, id, arg1_name, \
+ arg1_val, arg2_name, arg2_val) \
+ INTERNAL_TRACE_EVENT_ADD_WITH_ID( \
+ TRACE_EVENT_PHASE_NESTABLE_ASYNC_END, category_group, name, id, \
+ TRACE_EVENT_FLAG_NONE, arg1_name, arg1_val, arg2_name, arg2_val)
+
+// Async instant events.
+#define TRACE_EVENT_NESTABLE_ASYNC_INSTANT0(category_group, name, id) \
+ INTERNAL_TRACE_EVENT_ADD_WITH_ID(TRACE_EVENT_PHASE_NESTABLE_ASYNC_INSTANT, \
+ category_group, name, id, \
+ TRACE_EVENT_FLAG_NONE)
+#define TRACE_EVENT_NESTABLE_ASYNC_INSTANT1(category_group, name, id, \
+ arg1_name, arg1_val) \
+ INTERNAL_TRACE_EVENT_ADD_WITH_ID(TRACE_EVENT_PHASE_NESTABLE_ASYNC_INSTANT, \
+ category_group, name, id, \
+ TRACE_EVENT_FLAG_NONE, arg1_name, arg1_val)
+#define TRACE_EVENT_NESTABLE_ASYNC_INSTANT2( \
+ category_group, name, id, arg1_name, arg1_val, arg2_name, arg2_val) \
+ INTERNAL_TRACE_EVENT_ADD_WITH_ID( \
+ TRACE_EVENT_PHASE_NESTABLE_ASYNC_INSTANT, category_group, name, id, \
+ TRACE_EVENT_FLAG_NONE, arg1_name, arg1_val, arg2_name, arg2_val)
+#define TRACE_EVENT_COPY_NESTABLE_ASYNC_BEGIN_WITH_TTS2( \
+ category_group, name, id, arg1_name, arg1_val, arg2_name, arg2_val) \
+ INTERNAL_TRACE_EVENT_ADD_WITH_ID( \
+ TRACE_EVENT_PHASE_NESTABLE_ASYNC_BEGIN, category_group, name, id, \
+ TRACE_EVENT_FLAG_ASYNC_TTS | TRACE_EVENT_FLAG_COPY, arg1_name, arg1_val, \
+ arg2_name, arg2_val)
+#define TRACE_EVENT_COPY_NESTABLE_ASYNC_END_WITH_TTS2( \
+ category_group, name, id, arg1_name, arg1_val, arg2_name, arg2_val) \
+ INTERNAL_TRACE_EVENT_ADD_WITH_ID( \
+ TRACE_EVENT_PHASE_NESTABLE_ASYNC_END, category_group, name, id, \
+ TRACE_EVENT_FLAG_ASYNC_TTS | TRACE_EVENT_FLAG_COPY, arg1_name, arg1_val, \
+ arg2_name, arg2_val)
+
+// Async events with explicit timestamps.
+#define TRACE_EVENT_NESTABLE_ASYNC_BEGIN_WITH_TIMESTAMP0(category_group, name, \
+ id, timestamp) \
+ INTERNAL_TRACE_EVENT_ADD_WITH_ID_TID_AND_TIMESTAMP( \
+ TRACE_EVENT_PHASE_NESTABLE_ASYNC_BEGIN, category_group, name, id, \
+ TRACE_EVENT_API_CURRENT_THREAD_ID, timestamp, TRACE_EVENT_FLAG_NONE)
+#define TRACE_EVENT_NESTABLE_ASYNC_END_WITH_TIMESTAMP0(category_group, name, \
+ id, timestamp) \
+ INTERNAL_TRACE_EVENT_ADD_WITH_ID_TID_AND_TIMESTAMP( \
+ TRACE_EVENT_PHASE_NESTABLE_ASYNC_END, category_group, name, id, \
+ TRACE_EVENT_API_CURRENT_THREAD_ID, timestamp, TRACE_EVENT_FLAG_NONE)
+#define TRACE_EVENT_NESTABLE_ASYNC_END_WITH_TIMESTAMP1( \
+ category_group, name, id, timestamp, arg1_name, arg1_val) \
+ INTERNAL_TRACE_EVENT_ADD_WITH_ID_TID_AND_TIMESTAMP( \
+ TRACE_EVENT_PHASE_NESTABLE_ASYNC_END, category_group, name, id, \
+ TRACE_EVENT_API_CURRENT_THREAD_ID, timestamp, TRACE_EVENT_FLAG_NONE, \
+ arg1_name, arg1_val)
+#define TRACE_EVENT_NESTABLE_ASYNC_INSTANT_WITH_TIMESTAMP0( \
+ category_group, name, id, timestamp) \
+ INTERNAL_TRACE_EVENT_ADD_WITH_ID_TID_AND_TIMESTAMP( \
+ TRACE_EVENT_PHASE_NESTABLE_ASYNC_INSTANT, category_group, name, id, \
+ TRACE_EVENT_API_CURRENT_THREAD_ID, timestamp, TRACE_EVENT_FLAG_NONE)
+#define TRACE_EVENT_COPY_NESTABLE_ASYNC_BEGIN_WITH_TIMESTAMP0( \
+ category_group, name, id, timestamp) \
+ INTERNAL_TRACE_EVENT_ADD_WITH_ID_TID_AND_TIMESTAMP( \
+ TRACE_EVENT_PHASE_NESTABLE_ASYNC_BEGIN, category_group, name, id, \
+ TRACE_EVENT_API_CURRENT_THREAD_ID, timestamp, TRACE_EVENT_FLAG_COPY)
+#define TRACE_EVENT_COPY_NESTABLE_ASYNC_END_WITH_TIMESTAMP0( \
+ category_group, name, id, timestamp) \
+ INTERNAL_TRACE_EVENT_ADD_WITH_ID_TID_AND_TIMESTAMP( \
+ TRACE_EVENT_PHASE_NESTABLE_ASYNC_END, category_group, name, id, \
+ TRACE_EVENT_API_CURRENT_THREAD_ID, timestamp, TRACE_EVENT_FLAG_COPY)
+
+// Legacy flow events.
+#define TRACE_EVENT_FLOW_BEGIN0(category_group, name, id) \
+ INTERNAL_TRACE_EVENT_ADD_WITH_ID(TRACE_EVENT_PHASE_FLOW_BEGIN, \
+ category_group, name, id, \
+ TRACE_EVENT_FLAG_NONE)
+#define TRACE_EVENT_FLOW_BEGIN1(category_group, name, id, arg1_name, arg1_val) \
+ INTERNAL_TRACE_EVENT_ADD_WITH_ID(TRACE_EVENT_PHASE_FLOW_BEGIN, \
+ category_group, name, id, \
+ TRACE_EVENT_FLAG_NONE, arg1_name, arg1_val)
+#define TRACE_EVENT_FLOW_BEGIN2(category_group, name, id, arg1_name, arg1_val, \
+ arg2_name, arg2_val) \
+ INTERNAL_TRACE_EVENT_ADD_WITH_ID( \
+ TRACE_EVENT_PHASE_FLOW_BEGIN, category_group, name, id, \
+ TRACE_EVENT_FLAG_NONE, arg1_name, arg1_val, arg2_name, arg2_val)
+#define TRACE_EVENT_COPY_FLOW_BEGIN0(category_group, name, id) \
+ INTERNAL_TRACE_EVENT_ADD_WITH_ID(TRACE_EVENT_PHASE_FLOW_BEGIN, \
+ category_group, name, id, \
+ TRACE_EVENT_FLAG_COPY)
+#define TRACE_EVENT_COPY_FLOW_BEGIN1(category_group, name, id, arg1_name, \
+ arg1_val) \
+ INTERNAL_TRACE_EVENT_ADD_WITH_ID(TRACE_EVENT_PHASE_FLOW_BEGIN, \
+ category_group, name, id, \
+ TRACE_EVENT_FLAG_COPY, arg1_name, arg1_val)
+#define TRACE_EVENT_COPY_FLOW_BEGIN2(category_group, name, id, arg1_name, \
+ arg1_val, arg2_name, arg2_val) \
+ INTERNAL_TRACE_EVENT_ADD_WITH_ID( \
+ TRACE_EVENT_PHASE_FLOW_BEGIN, category_group, name, id, \
+ TRACE_EVENT_FLAG_COPY, arg1_name, arg1_val, arg2_name, arg2_val)
+
+// Legacy flow step events.
+#define TRACE_EVENT_FLOW_STEP0(category_group, name, id, step) \
+ INTERNAL_TRACE_EVENT_ADD_WITH_ID(TRACE_EVENT_PHASE_FLOW_STEP, \
+ category_group, name, id, \
+ TRACE_EVENT_FLAG_NONE, "step", step)
+#define TRACE_EVENT_FLOW_STEP1(category_group, name, id, step, arg1_name, \
+ arg1_val) \
+ INTERNAL_TRACE_EVENT_ADD_WITH_ID( \
+ TRACE_EVENT_PHASE_FLOW_STEP, category_group, name, id, \
+ TRACE_EVENT_FLAG_NONE, "step", step, arg1_name, arg1_val)
+#define TRACE_EVENT_COPY_FLOW_STEP0(category_group, name, id, step) \
+ INTERNAL_TRACE_EVENT_ADD_WITH_ID(TRACE_EVENT_PHASE_FLOW_STEP, \
+ category_group, name, id, \
+ TRACE_EVENT_FLAG_COPY, "step", step)
+#define TRACE_EVENT_COPY_FLOW_STEP1(category_group, name, id, step, arg1_name, \
+ arg1_val) \
+ INTERNAL_TRACE_EVENT_ADD_WITH_ID( \
+ TRACE_EVENT_PHASE_FLOW_STEP, category_group, name, id, \
+ TRACE_EVENT_FLAG_COPY, "step", step, arg1_name, arg1_val)
+
+// Legacy flow end events.
+#define TRACE_EVENT_FLOW_END0(category_group, name, id) \
+ INTERNAL_TRACE_EVENT_ADD_WITH_ID(TRACE_EVENT_PHASE_FLOW_END, category_group, \
+ name, id, TRACE_EVENT_FLAG_NONE)
+#define TRACE_EVENT_FLOW_END_BIND_TO_ENCLOSING0(category_group, name, id) \
+ INTERNAL_TRACE_EVENT_ADD_WITH_ID(TRACE_EVENT_PHASE_FLOW_END, category_group, \
+ name, id, \
+ TRACE_EVENT_FLAG_BIND_TO_ENCLOSING)
+#define TRACE_EVENT_FLOW_END1(category_group, name, id, arg1_name, arg1_val) \
+ INTERNAL_TRACE_EVENT_ADD_WITH_ID(TRACE_EVENT_PHASE_FLOW_END, category_group, \
+ name, id, TRACE_EVENT_FLAG_NONE, arg1_name, \
+ arg1_val)
+#define TRACE_EVENT_FLOW_END2(category_group, name, id, arg1_name, arg1_val, \
+ arg2_name, arg2_val) \
+ INTERNAL_TRACE_EVENT_ADD_WITH_ID(TRACE_EVENT_PHASE_FLOW_END, category_group, \
+ name, id, TRACE_EVENT_FLAG_NONE, arg1_name, \
+ arg1_val, arg2_name, arg2_val)
+#define TRACE_EVENT_COPY_FLOW_END0(category_group, name, id) \
+ INTERNAL_TRACE_EVENT_ADD_WITH_ID(TRACE_EVENT_PHASE_FLOW_END, category_group, \
+ name, id, TRACE_EVENT_FLAG_COPY)
+#define TRACE_EVENT_COPY_FLOW_END1(category_group, name, id, arg1_name, \
+ arg1_val) \
+ INTERNAL_TRACE_EVENT_ADD_WITH_ID(TRACE_EVENT_PHASE_FLOW_END, category_group, \
+ name, id, TRACE_EVENT_FLAG_COPY, arg1_name, \
+ arg1_val)
+#define TRACE_EVENT_COPY_FLOW_END2(category_group, name, id, arg1_name, \
+ arg1_val, arg2_name, arg2_val) \
+ INTERNAL_TRACE_EVENT_ADD_WITH_ID(TRACE_EVENT_PHASE_FLOW_END, category_group, \
+ name, id, TRACE_EVENT_FLAG_COPY, arg1_name, \
+ arg1_val, arg2_name, arg2_val)
+
+// Special strongly typed trace events.
+// TODO(skyostil): Migrate these to regular track event trace points.
+#define TRACE_TASK_EXECUTION(run_function, task) \
+ if (false) { \
+ base::ignore_result(run_function); \
+ base::ignore_result(task); \
+ }
+
+#define TRACE_LOG_MESSAGE(file, message, line) \
+ if (false) { \
+ base::ignore_result(file); \
+ base::ignore_result(message); \
+ base::ignore_result(line); \
+ }
+
+// Metadata events.
+#define TRACE_EVENT_METADATA1(category_group, name, arg1_name, arg1_val) \
+ INTERNAL_TRACE_EVENT_METADATA_ADD(category_group, name, arg1_name, arg1_val)
+
+// Clock sync events.
+#define TRACE_EVENT_CLOCK_SYNC_RECEIVER(sync_id) \
+ INTERNAL_TRACE_EVENT_ADD(TRACE_EVENT_PHASE_CLOCK_SYNC, "__metadata", \
+ "clock_sync", TRACE_EVENT_FLAG_NONE, "sync_id", \
+ sync_id)
+#define TRACE_EVENT_CLOCK_SYNC_ISSUER(sync_id, issue_ts, issue_end_ts) \
+ INTERNAL_TRACE_EVENT_ADD_WITH_TIMESTAMP( \
+ TRACE_EVENT_PHASE_CLOCK_SYNC, "__metadata", "clock_sync", issue_end_ts, \
+ TRACE_EVENT_FLAG_NONE, "sync_id", sync_id, "issue_ts", issue_ts)
+
+// Object events.
+#define TRACE_EVENT_OBJECT_CREATED_WITH_ID(category_group, name, id) \
+ INTERNAL_TRACE_EVENT_ADD_WITH_ID(TRACE_EVENT_PHASE_CREATE_OBJECT, \
+ category_group, name, id, \
+ TRACE_EVENT_FLAG_NONE)
+
+#define TRACE_EVENT_OBJECT_SNAPSHOT_WITH_ID(category_group, name, id, \
+ snapshot) \
+ INTERNAL_TRACE_EVENT_ADD_WITH_ID( \
+ TRACE_EVENT_PHASE_SNAPSHOT_OBJECT, category_group, name, id, \
+ TRACE_EVENT_FLAG_NONE, "snapshot", snapshot)
+
+#define TRACE_EVENT_OBJECT_SNAPSHOT_WITH_ID_AND_TIMESTAMP( \
+ category_group, name, id, timestamp, snapshot) \
+ INTERNAL_TRACE_EVENT_ADD_WITH_ID_TID_AND_TIMESTAMP( \
+ TRACE_EVENT_PHASE_SNAPSHOT_OBJECT, category_group, name, id, \
+ TRACE_EVENT_API_CURRENT_THREAD_ID, timestamp, TRACE_EVENT_FLAG_NONE, \
+ "snapshot", snapshot)
+
+#define TRACE_EVENT_OBJECT_DELETED_WITH_ID(category_group, name, id) \
+ INTERNAL_TRACE_EVENT_ADD_WITH_ID(TRACE_EVENT_PHASE_DELETE_OBJECT, \
+ category_group, name, id, \
+ TRACE_EVENT_FLAG_NONE)
+
+// Context events.
+#define TRACE_EVENT_ENTER_CONTEXT(category_group, name, context) \
+ INTERNAL_TRACE_EVENT_ADD_WITH_ID(TRACE_EVENT_PHASE_ENTER_CONTEXT, \
+ category_group, name, context, \
+ TRACE_EVENT_FLAG_NONE)
+#define TRACE_EVENT_LEAVE_CONTEXT(category_group, name, context) \
+ INTERNAL_TRACE_EVENT_ADD_WITH_ID(TRACE_EVENT_PHASE_LEAVE_CONTEXT, \
+ category_group, name, context, \
+ TRACE_EVENT_FLAG_NONE)
+
+// Macro to efficiently determine if a given category group is enabled.
+// TODO(skyostil): Implement.
+#define TRACE_EVENT_CATEGORY_GROUP_ENABLED(category_group, ret) \
+ do { \
+ *ret = false; \
+ } while (0)
+
+// Macro to efficiently determine, through polling, if a new trace has begun.
+// TODO(skyostil): Implement.
+#define TRACE_EVENT_IS_NEW_TRACE(ret) \
+ do { \
+ *ret = false; \
+ } while (0)
+
+// Time queries.
+#define TRACE_TIME_TICKS_NOW() INTERNAL_TRACE_TIME_TICKS_NOW()
+#define TRACE_TIME_NOW() INTERNAL_TRACE_TIME_NOW()
+
+// ----------------------------------------------------------------------------
+// Legacy tracing API (adapted from trace_event.h).
+// ----------------------------------------------------------------------------
+
+// We can implement the following subset of the legacy tracing API without
+// involvement from the embedder. APIs such as TraceId and
+// TRACE_EVENT_API_ADD_TRACE_EVENT are still up to the embedder to define.
+
+#define TRACE_STR_COPY(str) (str)
+
+// TODO(skyostil): Implement properly using CategoryRegistry.
+#define TRACE_EVENT_API_GET_CATEGORY_GROUP_ENABLED(category) \
+ [&] { \
+ static uint8_t enabled; \
+ TRACE_EVENT_CATEGORY_GROUP_ENABLED(category, &enabled); \
+ return &enabled; \
+ }()
+
+#endif // PERFETTO_ENABLE_LEGACY_TRACE_EVENTS
+
+#endif // INCLUDE_PERFETTO_TRACING_TRACK_EVENT_LEGACY_H_
diff --git a/protos/perfetto/common/android_log_constants.proto b/protos/perfetto/common/android_log_constants.proto
index 04bd728..47e42d1 100644
--- a/protos/perfetto/common/android_log_constants.proto
+++ b/protos/perfetto/common/android_log_constants.proto
@@ -15,7 +15,6 @@
*/
syntax = "proto2";
-option optimize_for = LITE_RUNTIME;
package perfetto.protos;
diff --git a/protos/perfetto/common/commit_data_request.proto b/protos/perfetto/common/commit_data_request.proto
index 59e29fb..7e6a1a9 100644
--- a/protos/perfetto/common/commit_data_request.proto
+++ b/protos/perfetto/common/commit_data_request.proto
@@ -15,7 +15,6 @@
*/
syntax = "proto2";
-option optimize_for = LITE_RUNTIME;
package perfetto.protos;
diff --git a/protos/perfetto/common/data_source_descriptor.proto b/protos/perfetto/common/data_source_descriptor.proto
index 63a5114..725c2f2 100644
--- a/protos/perfetto/common/data_source_descriptor.proto
+++ b/protos/perfetto/common/data_source_descriptor.proto
@@ -15,7 +15,6 @@
*/
syntax = "proto2";
-option optimize_for = LITE_RUNTIME;
package perfetto.protos;
diff --git a/protos/perfetto/common/descriptor.proto b/protos/perfetto/common/descriptor.proto
index d0d86ab..95f6fc0 100644
--- a/protos/perfetto/common/descriptor.proto
+++ b/protos/perfetto/common/descriptor.proto
@@ -19,7 +19,6 @@
package perfetto.protos;
-option optimize_for = LITE_RUNTIME;
// The protocol compiler can output a FileDescriptorSet containing the .proto
// files it parses.
diff --git a/protos/perfetto/common/gpu_counter_descriptor.proto b/protos/perfetto/common/gpu_counter_descriptor.proto
index f32b012..7a81e1a 100644
--- a/protos/perfetto/common/gpu_counter_descriptor.proto
+++ b/protos/perfetto/common/gpu_counter_descriptor.proto
@@ -15,7 +15,6 @@
*/
syntax = "proto2";
-option optimize_for = LITE_RUNTIME;
package perfetto.protos;
diff --git a/protos/perfetto/common/observable_events.proto b/protos/perfetto/common/observable_events.proto
index e1256f8..e3911e4 100644
--- a/protos/perfetto/common/observable_events.proto
+++ b/protos/perfetto/common/observable_events.proto
@@ -15,7 +15,6 @@
*/
syntax = "proto2";
-option optimize_for = LITE_RUNTIME;
package perfetto.protos;
diff --git a/protos/perfetto/common/sys_stats_counters.proto b/protos/perfetto/common/sys_stats_counters.proto
index 91c4e80..837656b 100644
--- a/protos/perfetto/common/sys_stats_counters.proto
+++ b/protos/perfetto/common/sys_stats_counters.proto
@@ -15,7 +15,6 @@
*/
syntax = "proto2";
-option optimize_for = LITE_RUNTIME;
package perfetto.protos;
diff --git a/protos/perfetto/common/trace_stats.proto b/protos/perfetto/common/trace_stats.proto
index 9a661e1..e925ad4 100644
--- a/protos/perfetto/common/trace_stats.proto
+++ b/protos/perfetto/common/trace_stats.proto
@@ -15,7 +15,6 @@
*/
syntax = "proto2";
-option optimize_for = LITE_RUNTIME;
package perfetto.protos;
diff --git a/protos/perfetto/common/tracing_service_state.proto b/protos/perfetto/common/tracing_service_state.proto
index 86723b3..dd475ab 100644
--- a/protos/perfetto/common/tracing_service_state.proto
+++ b/protos/perfetto/common/tracing_service_state.proto
@@ -15,7 +15,6 @@
*/
syntax = "proto2";
-option optimize_for = LITE_RUNTIME;
package perfetto.protos;
diff --git a/protos/perfetto/common/track_event_descriptor.proto b/protos/perfetto/common/track_event_descriptor.proto
index 5536cc8..47d605a 100644
--- a/protos/perfetto/common/track_event_descriptor.proto
+++ b/protos/perfetto/common/track_event_descriptor.proto
@@ -15,7 +15,6 @@
*/
syntax = "proto2";
-option optimize_for = LITE_RUNTIME;
package perfetto.protos;
diff --git a/protos/perfetto/config/BUILD.gn b/protos/perfetto/config/BUILD.gn
index 1ccbba4..7d40c27 100644
--- a/protos/perfetto/config/BUILD.gn
+++ b/protos/perfetto/config/BUILD.gn
@@ -45,7 +45,5 @@
# autogenerated merged proto has a valid syntax.
perfetto_proto_library("merged_config") {
proto_generators = [ "lite" ]
- sources = [
- "perfetto_config.proto",
- ]
+ sources = [ "perfetto_config.proto" ]
}
diff --git a/protos/perfetto/config/android/BUILD.gn b/protos/perfetto/config/android/BUILD.gn
index 6e98fbb..78c2d01 100644
--- a/protos/perfetto/config/android/BUILD.gn
+++ b/protos/perfetto/config/android/BUILD.gn
@@ -16,9 +16,7 @@
import("../../../../gn/proto_library.gni")
perfetto_proto_library("@TYPE@") {
- deps = [
- "../../common:@TYPE@",
- ]
+ deps = [ "../../common:@TYPE@" ]
sources = [
"android_log_config.proto",
"packages_list_config.proto",
diff --git a/protos/perfetto/config/android/android_log_config.proto b/protos/perfetto/config/android/android_log_config.proto
index 5a43f2d..ff4c400 100644
--- a/protos/perfetto/config/android/android_log_config.proto
+++ b/protos/perfetto/config/android/android_log_config.proto
@@ -15,7 +15,6 @@
*/
syntax = "proto2";
-option optimize_for = LITE_RUNTIME;
package perfetto.protos;
import "protos/perfetto/common/android_log_constants.proto";
diff --git a/protos/perfetto/config/android/packages_list_config.proto b/protos/perfetto/config/android/packages_list_config.proto
index 7796eba..171fc10 100644
--- a/protos/perfetto/config/android/packages_list_config.proto
+++ b/protos/perfetto/config/android/packages_list_config.proto
@@ -15,7 +15,6 @@
*/
syntax = "proto2";
-option optimize_for = LITE_RUNTIME;
package perfetto.protos;
diff --git a/protos/perfetto/config/chrome/BUILD.gn b/protos/perfetto/config/chrome/BUILD.gn
index b893d06..4f44718 100644
--- a/protos/perfetto/config/chrome/BUILD.gn
+++ b/protos/perfetto/config/chrome/BUILD.gn
@@ -16,7 +16,5 @@
import("../../../../gn/proto_library.gni")
perfetto_proto_library("@TYPE@") {
- sources = [
- "chrome_config.proto",
- ]
+ sources = [ "chrome_config.proto" ]
}
diff --git a/protos/perfetto/config/chrome/chrome_config.proto b/protos/perfetto/config/chrome/chrome_config.proto
index 3906f03..aa24c38 100644
--- a/protos/perfetto/config/chrome/chrome_config.proto
+++ b/protos/perfetto/config/chrome/chrome_config.proto
@@ -15,7 +15,6 @@
*/
syntax = "proto2";
-option optimize_for = LITE_RUNTIME;
package perfetto.protos;
diff --git a/protos/perfetto/config/data_source_config.proto b/protos/perfetto/config/data_source_config.proto
index e969699..aa071d6 100644
--- a/protos/perfetto/config/data_source_config.proto
+++ b/protos/perfetto/config/data_source_config.proto
@@ -15,7 +15,6 @@
*/
syntax = "proto2";
-option optimize_for = LITE_RUNTIME;
package perfetto.protos;
diff --git a/protos/perfetto/config/ftrace/BUILD.gn b/protos/perfetto/config/ftrace/BUILD.gn
index 37ff9ca..057a0b4 100644
--- a/protos/perfetto/config/ftrace/BUILD.gn
+++ b/protos/perfetto/config/ftrace/BUILD.gn
@@ -16,7 +16,5 @@
import("../../../../gn/proto_library.gni")
perfetto_proto_library("@TYPE@") {
- sources = [
- "ftrace_config.proto",
- ]
+ sources = [ "ftrace_config.proto" ]
}
diff --git a/protos/perfetto/config/ftrace/ftrace_config.proto b/protos/perfetto/config/ftrace/ftrace_config.proto
index a612d89..3b78baa 100644
--- a/protos/perfetto/config/ftrace/ftrace_config.proto
+++ b/protos/perfetto/config/ftrace/ftrace_config.proto
@@ -15,7 +15,6 @@
*/
syntax = "proto2";
-option optimize_for = LITE_RUNTIME;
package perfetto.protos;
diff --git a/protos/perfetto/config/gpu/gpu_counter_config.proto b/protos/perfetto/config/gpu/gpu_counter_config.proto
index 017195b..d51a997 100644
--- a/protos/perfetto/config/gpu/gpu_counter_config.proto
+++ b/protos/perfetto/config/gpu/gpu_counter_config.proto
@@ -15,7 +15,6 @@
*/
syntax = "proto2";
-option optimize_for = LITE_RUNTIME;
package perfetto.protos;
diff --git a/protos/perfetto/config/gpu/vulkan_memory_config.proto b/protos/perfetto/config/gpu/vulkan_memory_config.proto
index be86bb2..c1959ae 100644
--- a/protos/perfetto/config/gpu/vulkan_memory_config.proto
+++ b/protos/perfetto/config/gpu/vulkan_memory_config.proto
@@ -15,7 +15,6 @@
*/
syntax = "proto2";
-option optimize_for = LITE_RUNTIME;
package perfetto.protos;
diff --git a/protos/perfetto/config/inode_file/BUILD.gn b/protos/perfetto/config/inode_file/BUILD.gn
index d2cbdfd..4ce2f34 100644
--- a/protos/perfetto/config/inode_file/BUILD.gn
+++ b/protos/perfetto/config/inode_file/BUILD.gn
@@ -15,7 +15,5 @@
import("../../../../gn/proto_library.gni")
perfetto_proto_library("@TYPE@") {
- sources = [
- "inode_file_config.proto",
- ]
+ sources = [ "inode_file_config.proto" ]
}
diff --git a/protos/perfetto/config/inode_file/inode_file_config.proto b/protos/perfetto/config/inode_file/inode_file_config.proto
index d291cd1..d94e319 100644
--- a/protos/perfetto/config/inode_file/inode_file_config.proto
+++ b/protos/perfetto/config/inode_file/inode_file_config.proto
@@ -15,7 +15,6 @@
*/
syntax = "proto2";
-option optimize_for = LITE_RUNTIME;
package perfetto.protos;
diff --git a/protos/perfetto/config/power/BUILD.gn b/protos/perfetto/config/power/BUILD.gn
index 0f74515..aa005b5 100644
--- a/protos/perfetto/config/power/BUILD.gn
+++ b/protos/perfetto/config/power/BUILD.gn
@@ -15,7 +15,5 @@
import("../../../../gn/proto_library.gni")
perfetto_proto_library("@TYPE@") {
- sources = [
- "android_power_config.proto",
- ]
+ sources = [ "android_power_config.proto" ]
}
diff --git a/protos/perfetto/config/power/android_power_config.proto b/protos/perfetto/config/power/android_power_config.proto
index c17371d..9cc795a 100644
--- a/protos/perfetto/config/power/android_power_config.proto
+++ b/protos/perfetto/config/power/android_power_config.proto
@@ -15,7 +15,6 @@
*/
syntax = "proto2";
-option optimize_for = LITE_RUNTIME;
package perfetto.protos;
diff --git a/protos/perfetto/config/process_stats/BUILD.gn b/protos/perfetto/config/process_stats/BUILD.gn
index 7acfffe..e3aa244 100644
--- a/protos/perfetto/config/process_stats/BUILD.gn
+++ b/protos/perfetto/config/process_stats/BUILD.gn
@@ -15,7 +15,5 @@
import("../../../../gn/proto_library.gni")
perfetto_proto_library("@TYPE@") {
- sources = [
- "process_stats_config.proto",
- ]
+ sources = [ "process_stats_config.proto" ]
}
diff --git a/protos/perfetto/config/process_stats/process_stats_config.proto b/protos/perfetto/config/process_stats/process_stats_config.proto
index 14cb4e9..fc406c9 100644
--- a/protos/perfetto/config/process_stats/process_stats_config.proto
+++ b/protos/perfetto/config/process_stats/process_stats_config.proto
@@ -15,7 +15,6 @@
*/
syntax = "proto2";
-option optimize_for = LITE_RUNTIME;
package perfetto.protos;
diff --git a/protos/perfetto/config/profiling/heapprofd_config.proto b/protos/perfetto/config/profiling/heapprofd_config.proto
index 0f3a30f..15a7c68 100644
--- a/protos/perfetto/config/profiling/heapprofd_config.proto
+++ b/protos/perfetto/config/profiling/heapprofd_config.proto
@@ -15,7 +15,6 @@
*/
syntax = "proto2";
-option optimize_for = LITE_RUNTIME;
package perfetto.protos;
diff --git a/protos/perfetto/config/profiling/java_hprof_config.proto b/protos/perfetto/config/profiling/java_hprof_config.proto
index 07d0993..572df33 100644
--- a/protos/perfetto/config/profiling/java_hprof_config.proto
+++ b/protos/perfetto/config/profiling/java_hprof_config.proto
@@ -15,7 +15,6 @@
*/
syntax = "proto2";
-option optimize_for = LITE_RUNTIME;
package perfetto.protos;
diff --git a/protos/perfetto/config/profiling/perf_event_config.proto b/protos/perfetto/config/profiling/perf_event_config.proto
index 7bb967e..0333d71 100644
--- a/protos/perfetto/config/profiling/perf_event_config.proto
+++ b/protos/perfetto/config/profiling/perf_event_config.proto
@@ -15,7 +15,6 @@
*/
syntax = "proto2";
-option optimize_for = LITE_RUNTIME;
package perfetto.protos;
diff --git a/protos/perfetto/config/sys_stats/BUILD.gn b/protos/perfetto/config/sys_stats/BUILD.gn
index 634dd7e..cfe6874 100644
--- a/protos/perfetto/config/sys_stats/BUILD.gn
+++ b/protos/perfetto/config/sys_stats/BUILD.gn
@@ -15,10 +15,6 @@
import("../../../../gn/proto_library.gni")
perfetto_proto_library("@TYPE@") {
- deps = [
- "../../common:@TYPE@",
- ]
- sources = [
- "sys_stats_config.proto",
- ]
+ deps = [ "../../common:@TYPE@" ]
+ sources = [ "sys_stats_config.proto" ]
}
diff --git a/protos/perfetto/config/sys_stats/sys_stats_config.proto b/protos/perfetto/config/sys_stats/sys_stats_config.proto
index 7eafa3e..4e037fc 100644
--- a/protos/perfetto/config/sys_stats/sys_stats_config.proto
+++ b/protos/perfetto/config/sys_stats/sys_stats_config.proto
@@ -15,7 +15,6 @@
*/
syntax = "proto2";
-option optimize_for = LITE_RUNTIME;
package perfetto.protos;
diff --git a/protos/perfetto/config/test_config.proto b/protos/perfetto/config/test_config.proto
index c22a7e9..40bfa8a 100644
--- a/protos/perfetto/config/test_config.proto
+++ b/protos/perfetto/config/test_config.proto
@@ -15,7 +15,6 @@
*/
syntax = "proto2";
-option optimize_for = LITE_RUNTIME;
package perfetto.protos;
diff --git a/protos/perfetto/config/trace_config.proto b/protos/perfetto/config/trace_config.proto
index 46971c1..085f10c 100644
--- a/protos/perfetto/config/trace_config.proto
+++ b/protos/perfetto/config/trace_config.proto
@@ -15,7 +15,6 @@
*/
syntax = "proto2";
-option optimize_for = LITE_RUNTIME;
import "protos/perfetto/config/data_source_config.proto";
diff --git a/protos/perfetto/ipc/BUILD.gn b/protos/perfetto/ipc/BUILD.gn
index 383ae5f..3388b7d 100644
--- a/protos/perfetto/ipc/BUILD.gn
+++ b/protos/perfetto/ipc/BUILD.gn
@@ -40,7 +40,5 @@
"zero",
"cpp",
]
- sources = [
- "wire_protocol.proto",
- ]
+ sources = [ "wire_protocol.proto" ]
}
diff --git a/protos/perfetto/ipc/consumer_port.proto b/protos/perfetto/ipc/consumer_port.proto
index 26854e8..6a6e3ca 100644
--- a/protos/perfetto/ipc/consumer_port.proto
+++ b/protos/perfetto/ipc/consumer_port.proto
@@ -15,7 +15,6 @@
*/
syntax = "proto2";
-option optimize_for = LITE_RUNTIME;
import "protos/perfetto/common/observable_events.proto";
import "protos/perfetto/common/tracing_service_state.proto";
diff --git a/protos/perfetto/ipc/producer_port.proto b/protos/perfetto/ipc/producer_port.proto
index ebd8b98..fc09783 100644
--- a/protos/perfetto/ipc/producer_port.proto
+++ b/protos/perfetto/ipc/producer_port.proto
@@ -15,7 +15,6 @@
*/
syntax = "proto2";
-option optimize_for = LITE_RUNTIME;
import "protos/perfetto/common/commit_data_request.proto";
import "protos/perfetto/config/data_source_config.proto";
diff --git a/protos/perfetto/ipc/wire_protocol.proto b/protos/perfetto/ipc/wire_protocol.proto
index 5f80f66..c57b71b 100644
--- a/protos/perfetto/ipc/wire_protocol.proto
+++ b/protos/perfetto/ipc/wire_protocol.proto
@@ -15,7 +15,6 @@
*/
syntax = "proto2";
-option optimize_for = LITE_RUNTIME;
package perfetto.protos;
diff --git a/protos/perfetto/metrics/BUILD.gn b/protos/perfetto/metrics/BUILD.gn
index 1bb4387..8a35ef1 100644
--- a/protos/perfetto/metrics/BUILD.gn
+++ b/protos/perfetto/metrics/BUILD.gn
@@ -16,20 +16,14 @@
import("../../../gn/proto_library.gni")
perfetto_proto_library("@TYPE@") {
- deps = [
- "android:@TYPE@",
- ]
- sources = [
- "metrics.proto",
- ]
+ deps = [ "android:@TYPE@" ]
+ sources = [ "metrics.proto" ]
}
if (perfetto_build_standalone) {
perfetto_proto_library("descriptor") {
proto_generators = [ "descriptor" ]
generate_descriptor = "metrics.descriptor"
- sources = [
- "metrics.proto",
- ]
+ sources = [ "metrics.proto" ]
}
}
diff --git a/protos/perfetto/metrics/android/BUILD.gn b/protos/perfetto/metrics/android/BUILD.gn
index 5f7e2b4..9b51e5b 100644
--- a/protos/perfetto/metrics/android/BUILD.gn
+++ b/protos/perfetto/metrics/android/BUILD.gn
@@ -19,6 +19,7 @@
"batt_metric.proto",
"cpu_metric.proto",
"heap_profile_callsites.proto",
+ "hwui_metric.proto",
"ion_metric.proto",
"java_heap_stats.proto",
"lmk_metric.proto",
diff --git a/protos/perfetto/metrics/android/batt_metric.proto b/protos/perfetto/metrics/android/batt_metric.proto
index b7c2d15..d9d7876 100644
--- a/protos/perfetto/metrics/android/batt_metric.proto
+++ b/protos/perfetto/metrics/android/batt_metric.proto
@@ -15,7 +15,6 @@
*/
syntax = "proto2";
-option optimize_for = LITE_RUNTIME;
package perfetto.protos;
diff --git a/protos/perfetto/metrics/android/cpu_metric.proto b/protos/perfetto/metrics/android/cpu_metric.proto
index be17af5..12f7588 100644
--- a/protos/perfetto/metrics/android/cpu_metric.proto
+++ b/protos/perfetto/metrics/android/cpu_metric.proto
@@ -15,7 +15,6 @@
*/
syntax = "proto2";
-option optimize_for = LITE_RUNTIME;
package perfetto.protos;
diff --git a/protos/perfetto/metrics/android/heap_profile_callsites.proto b/protos/perfetto/metrics/android/heap_profile_callsites.proto
index df1a516..af88c6e 100644
--- a/protos/perfetto/metrics/android/heap_profile_callsites.proto
+++ b/protos/perfetto/metrics/android/heap_profile_callsites.proto
@@ -14,7 +14,6 @@
* limitations under the License.
*/
syntax = "proto2";
-option optimize_for = LITE_RUNTIME;
package perfetto.protos;
diff --git a/protos/perfetto/metrics/android/hwui_metric.proto b/protos/perfetto/metrics/android/hwui_metric.proto
new file mode 100644
index 0000000..b2c11c8
--- /dev/null
+++ b/protos/perfetto/metrics/android/hwui_metric.proto
@@ -0,0 +1,103 @@
+/*
+ * Copyright (C) 2020 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;
+
+// Android HWUI graphics performance and graphics memory usage metrics.
+message ProcessRenderInfo {
+ // Name of the package launched
+ optional string process_name = 1;
+
+ // CPU time spent on RenderThread in milliseconds.
+ optional int64 rt_cpu_time_ms = 2;
+
+ // Number of frames drawn on RenderThread, followed by max/min/avg CPU time to draw a frame
+ // in nanoseconds.
+ optional uint32 draw_frame_count = 3;
+ optional int64 draw_frame_max = 4;
+ optional int64 draw_frame_min = 5;
+ optional double draw_frame_avg = 6;
+
+ // Number of GPU commands flushes and max/min/avg time per flush in nanoseconds.
+ optional uint32 flush_count = 7;
+ optional int64 flush_max = 8;
+ optional int64 flush_min = 9;
+ optional double flush_avg = 10;
+
+ // Number of View tree preparation counts and max/min/avg time to traverse the tree in
+ // nanoseconds.
+ optional uint32 prepare_tree_count = 11;
+ optional int64 prepare_tree_max = 12;
+ optional int64 prepare_tree_min = 13;
+ optional double prepare_tree_avg = 14;
+
+ // Number of times the GPU rendered a frame and max/min/avg time for GPU to finish rendering in
+ // in nanoseconds.
+ optional uint32 gpu_completion_count = 15;
+ optional int64 gpu_completion_max = 16;
+ optional int64 gpu_completion_min = 17;
+ optional double gpu_completion_avg = 18;
+
+ // Number of times a frame was recorded/serialized in a display list on the UI thread with
+ // max/min/avg time in nanoseconds.
+ optional uint32 ui_record_count = 19;
+ optional int64 ui_record_max = 20;
+ optional int64 ui_record_min = 21;
+ optional double ui_record_avg = 22;
+
+ // number of unique shader programs that were used to render frames, followed by total and average
+ // times to prepare a shader in nanoseconds.
+ optional uint32 shader_compile_count = 23;
+ optional int64 shader_compile_time = 24;
+ optional double shader_compile_avg = 25;
+ // number of shader programs loaded from the disk cache, followed by total time and average time
+ // to prepare a shader in nanoseconds.
+ optional uint32 cache_hit_count = 26;
+ optional int64 cache_hit_time = 27;
+ optional double cache_hit_avg = 28;
+ // number of shader programs compiled/linked, followed by total time and average time to prepare
+ // a shader in nanoseconds.
+ optional uint32 cache_miss_count = 29;
+ optional int64 cache_miss_time = 30;
+ optional double cache_miss_avg = 31;
+
+ // max/min/avg CPU memory used for graphics by HWUI at the end of a frame.
+ optional int64 graphics_cpu_mem_max = 32;
+ optional int64 graphics_cpu_mem_min = 33;
+ optional double graphics_cpu_mem_avg = 34;
+
+ // max/min/avg GPU memory used by HWUI at the end of a frame excluding textures.
+ optional int64 graphics_gpu_mem_max = 35;
+ optional int64 graphics_gpu_mem_min = 36;
+ optional double graphics_gpu_mem_avg = 37;
+
+ // max/min/avg memory used for GPU textures by HWUI at the end of a frame.
+ optional int64 texture_mem_max = 38;
+ optional int64 texture_mem_min = 39;
+ optional double texture_mem_avg = 40;
+
+ // max/min/avg memory used by HWUI at the end of a frame. This is a sum of previous 3 categories.
+ optional int64 all_mem_max = 41;
+ optional int64 all_mem_min = 42;
+ optional double all_mem_avg = 43;
+}
+
+message AndroidHwuiMetric {
+ // HWUI metrics for processes that have a RenderThread.
+ repeated ProcessRenderInfo process_info = 1;
+}
diff --git a/protos/perfetto/metrics/android/ion_metric.proto b/protos/perfetto/metrics/android/ion_metric.proto
index b50041e..c5a5b19 100644
--- a/protos/perfetto/metrics/android/ion_metric.proto
+++ b/protos/perfetto/metrics/android/ion_metric.proto
@@ -15,7 +15,6 @@
*/
syntax = "proto2";
-option optimize_for = LITE_RUNTIME;
package perfetto.protos;
diff --git a/protos/perfetto/metrics/android/java_heap_stats.proto b/protos/perfetto/metrics/android/java_heap_stats.proto
index e07190b..85d0595 100644
--- a/protos/perfetto/metrics/android/java_heap_stats.proto
+++ b/protos/perfetto/metrics/android/java_heap_stats.proto
@@ -14,7 +14,6 @@
* limitations under the License.
*/
syntax = "proto2";
-option optimize_for = LITE_RUNTIME;
package perfetto.protos;
diff --git a/protos/perfetto/metrics/android/lmk_metric.proto b/protos/perfetto/metrics/android/lmk_metric.proto
index 5bb1881..be4218f 100644
--- a/protos/perfetto/metrics/android/lmk_metric.proto
+++ b/protos/perfetto/metrics/android/lmk_metric.proto
@@ -15,7 +15,6 @@
*/
syntax = "proto2";
-option optimize_for = LITE_RUNTIME;
package perfetto.protos;
diff --git a/protos/perfetto/metrics/android/lmk_reason_metric.proto b/protos/perfetto/metrics/android/lmk_reason_metric.proto
index c21233a..fbfb746 100644
--- a/protos/perfetto/metrics/android/lmk_reason_metric.proto
+++ b/protos/perfetto/metrics/android/lmk_reason_metric.proto
@@ -15,7 +15,6 @@
*/
syntax = "proto2";
-option optimize_for = LITE_RUNTIME;
package perfetto.protos;
diff --git a/protos/perfetto/metrics/android/mem_metric.proto b/protos/perfetto/metrics/android/mem_metric.proto
index 0443c0d..5fb5c9f 100644
--- a/protos/perfetto/metrics/android/mem_metric.proto
+++ b/protos/perfetto/metrics/android/mem_metric.proto
@@ -15,7 +15,6 @@
*/
syntax = "proto2";
-option optimize_for = LITE_RUNTIME;
package perfetto.protos;
diff --git a/protos/perfetto/metrics/android/mem_unagg_metric.proto b/protos/perfetto/metrics/android/mem_unagg_metric.proto
index e86893c..fc9276d 100644
--- a/protos/perfetto/metrics/android/mem_unagg_metric.proto
+++ b/protos/perfetto/metrics/android/mem_unagg_metric.proto
@@ -15,7 +15,6 @@
*/
syntax = "proto2";
-option optimize_for = LITE_RUNTIME;
package perfetto.protos;
diff --git a/protos/perfetto/metrics/android/package_list.proto b/protos/perfetto/metrics/android/package_list.proto
index 3525294..6701979 100644
--- a/protos/perfetto/metrics/android/package_list.proto
+++ b/protos/perfetto/metrics/android/package_list.proto
@@ -14,7 +14,6 @@
* limitations under the License.
*/
syntax = "proto2";
-option optimize_for = LITE_RUNTIME;
package perfetto.protos;
diff --git a/protos/perfetto/metrics/android/powrails_metric.proto b/protos/perfetto/metrics/android/powrails_metric.proto
index df0823f..fcf0aa7 100644
--- a/protos/perfetto/metrics/android/powrails_metric.proto
+++ b/protos/perfetto/metrics/android/powrails_metric.proto
@@ -15,7 +15,6 @@
*/
syntax = "proto2";
-option optimize_for = LITE_RUNTIME;
package perfetto.protos;
diff --git a/protos/perfetto/metrics/android/process_metadata.proto b/protos/perfetto/metrics/android/process_metadata.proto
index 792fda0..fd7fe7b 100644
--- a/protos/perfetto/metrics/android/process_metadata.proto
+++ b/protos/perfetto/metrics/android/process_metadata.proto
@@ -14,7 +14,6 @@
* limitations under the License.
*/
syntax = "proto2";
-option optimize_for = LITE_RUNTIME;
package perfetto.protos;
diff --git a/protos/perfetto/metrics/android/startup_metric.proto b/protos/perfetto/metrics/android/startup_metric.proto
index 1310a38..d38a598 100644
--- a/protos/perfetto/metrics/android/startup_metric.proto
+++ b/protos/perfetto/metrics/android/startup_metric.proto
@@ -15,7 +15,6 @@
*/
syntax = "proto2";
-option optimize_for = LITE_RUNTIME;
package perfetto.protos;
diff --git a/protos/perfetto/metrics/android/unmapped_java_symbols.proto b/protos/perfetto/metrics/android/unmapped_java_symbols.proto
index 53266ca..b8c8834 100644
--- a/protos/perfetto/metrics/android/unmapped_java_symbols.proto
+++ b/protos/perfetto/metrics/android/unmapped_java_symbols.proto
@@ -15,7 +15,6 @@
*/
syntax = "proto2";
-option optimize_for = LITE_RUNTIME;
package perfetto.protos;
diff --git a/protos/perfetto/metrics/android/unsymbolized_frames.proto b/protos/perfetto/metrics/android/unsymbolized_frames.proto
index 98d9d44..da75511 100644
--- a/protos/perfetto/metrics/android/unsymbolized_frames.proto
+++ b/protos/perfetto/metrics/android/unsymbolized_frames.proto
@@ -15,7 +15,6 @@
*/
syntax = "proto2";
-option optimize_for = LITE_RUNTIME;
package perfetto.protos;
diff --git a/test/task_runner_thread_delegates.cc b/protos/perfetto/metrics/custom_options.proto
similarity index 67%
copy from test/task_runner_thread_delegates.cc
copy to protos/perfetto/metrics/custom_options.proto
index 291482f..8f4bfbb 100644
--- a/test/task_runner_thread_delegates.cc
+++ b/protos/perfetto/metrics/custom_options.proto
@@ -14,12 +14,13 @@
* limitations under the License.
*/
-#include "test/task_runner_thread_delegates.h"
+syntax = "proto2";
-namespace perfetto {
+import "google/protobuf/descriptor.proto";
-ServiceDelegate::~ServiceDelegate() = default;
-ProbesProducerDelegate::~ProbesProducerDelegate() = default;
-FakeProducerDelegate::~FakeProducerDelegate() = default;
-
-} // namespace perfetto
+// Field options you can define on a metric. These options are only exposed as
+// part of JSON export.
+extend google.protobuf.FieldOptions {
+ optional string unit = 50001;
+ optional string improvementDirection = 50002;
+}
diff --git a/protos/perfetto/metrics/metrics.proto b/protos/perfetto/metrics/metrics.proto
index c17be13..16be108 100644
--- a/protos/perfetto/metrics/metrics.proto
+++ b/protos/perfetto/metrics/metrics.proto
@@ -15,7 +15,6 @@
*/
syntax = "proto2";
-option optimize_for = LITE_RUNTIME;
package perfetto.protos;
@@ -29,6 +28,7 @@
import "protos/perfetto/metrics/android/powrails_metric.proto";
import "protos/perfetto/metrics/android/startup_metric.proto";
import "protos/perfetto/metrics/android/heap_profile_callsites.proto";
+import "protos/perfetto/metrics/android/hwui_metric.proto";
import "protos/perfetto/metrics/android/package_list.proto";
import "protos/perfetto/metrics/android/unmapped_java_symbols.proto";
import "protos/perfetto/metrics/android/unsymbolized_frames.proto";
@@ -47,11 +47,12 @@
optional string trace_uuid = 3;
optional string android_build_fingerprint = 4;
optional int64 statsd_triggering_subscription_id = 5;
+ optional int64 trace_size_bytes = 6;
}
// Root message for all Perfetto-based metrics.
//
-// Next id: 20
+// Next id: 21
message TraceMetrics {
reserved 4, 10, 13, 14;
@@ -103,6 +104,8 @@
// Java type names that have no deobfuscation mappings.
optional UnmappedJavaSymbols unmapped_java_symbols = 19;
+ optional AndroidHwuiMetric android_hwui_metric = 20;
+
// Demo extensions.
extensions 450 to 499;
diff --git a/protos/perfetto/metrics/perfetto_merged_metrics.proto b/protos/perfetto/metrics/perfetto_merged_metrics.proto
index 3221b5c..4cf3399 100644
--- a/protos/perfetto/metrics/perfetto_merged_metrics.proto
+++ b/protos/perfetto/metrics/perfetto_merged_metrics.proto
@@ -406,6 +406,94 @@
// End of protos/perfetto/metrics/android/heap_profile_callsites.proto
+// Begin of protos/perfetto/metrics/android/hwui_metric.proto
+
+// Android HWUI graphics performance and graphics memory usage metrics.
+message ProcessRenderInfo {
+ // Name of the package launched
+ optional string process_name = 1;
+
+ // CPU time spent on RenderThread in milliseconds.
+ optional int64 rt_cpu_time_ms = 2;
+
+ // Number of frames drawn on RenderThread, followed by max/min/avg CPU time to draw a frame
+ // in nanoseconds.
+ optional uint32 draw_frame_count = 3;
+ optional int64 draw_frame_max = 4;
+ optional int64 draw_frame_min = 5;
+ optional double draw_frame_avg = 6;
+
+ // Number of GPU commands flushes and max/min/avg time per flush in nanoseconds.
+ optional uint32 flush_count = 7;
+ optional int64 flush_max = 8;
+ optional int64 flush_min = 9;
+ optional double flush_avg = 10;
+
+ // Number of View tree preparation counts and max/min/avg time to traverse the tree in
+ // nanoseconds.
+ optional uint32 prepare_tree_count = 11;
+ optional int64 prepare_tree_max = 12;
+ optional int64 prepare_tree_min = 13;
+ optional double prepare_tree_avg = 14;
+
+ // Number of times the GPU rendered a frame and max/min/avg time for GPU to finish rendering in
+ // in nanoseconds.
+ optional uint32 gpu_completion_count = 15;
+ optional int64 gpu_completion_max = 16;
+ optional int64 gpu_completion_min = 17;
+ optional double gpu_completion_avg = 18;
+
+ // Number of times a frame was recorded/serialized in a display list on the UI thread with
+ // max/min/avg time in nanoseconds.
+ optional uint32 ui_record_count = 19;
+ optional int64 ui_record_max = 20;
+ optional int64 ui_record_min = 21;
+ optional double ui_record_avg = 22;
+
+ // number of unique shader programs that were used to render frames, followed by total and average
+ // times to prepare a shader in nanoseconds.
+ optional uint32 shader_compile_count = 23;
+ optional int64 shader_compile_time = 24;
+ optional double shader_compile_avg = 25;
+ // number of shader programs loaded from the disk cache, followed by total time and average time
+ // to prepare a shader in nanoseconds.
+ optional uint32 cache_hit_count = 26;
+ optional int64 cache_hit_time = 27;
+ optional double cache_hit_avg = 28;
+ // number of shader programs compiled/linked, followed by total time and average time to prepare
+ // a shader in nanoseconds.
+ optional uint32 cache_miss_count = 29;
+ optional int64 cache_miss_time = 30;
+ optional double cache_miss_avg = 31;
+
+ // max/min/avg CPU memory used for graphics by HWUI at the end of a frame.
+ optional int64 graphics_cpu_mem_max = 32;
+ optional int64 graphics_cpu_mem_min = 33;
+ optional double graphics_cpu_mem_avg = 34;
+
+ // max/min/avg GPU memory used by HWUI at the end of a frame excluding textures.
+ optional int64 graphics_gpu_mem_max = 35;
+ optional int64 graphics_gpu_mem_min = 36;
+ optional double graphics_gpu_mem_avg = 37;
+
+ // max/min/avg memory used for GPU textures by HWUI at the end of a frame.
+ optional int64 texture_mem_max = 38;
+ optional int64 texture_mem_min = 39;
+ optional double texture_mem_avg = 40;
+
+ // max/min/avg memory used by HWUI at the end of a frame. This is a sum of previous 3 categories.
+ optional int64 all_mem_max = 41;
+ optional int64 all_mem_min = 42;
+ optional double all_mem_avg = 43;
+}
+
+message AndroidHwuiMetric {
+ // HWUI metrics for processes that have a RenderThread.
+ repeated ProcessRenderInfo process_info = 1;
+}
+
+// End of protos/perfetto/metrics/android/hwui_metric.proto
+
// Begin of protos/perfetto/metrics/android/package_list.proto
message AndroidPackageList {
@@ -485,11 +573,12 @@
optional string trace_uuid = 3;
optional string android_build_fingerprint = 4;
optional int64 statsd_triggering_subscription_id = 5;
+ optional int64 trace_size_bytes = 6;
}
// Root message for all Perfetto-based metrics.
//
-// Next id: 20
+// Next id: 21
message TraceMetrics {
reserved 4, 10, 13, 14;
@@ -541,6 +630,8 @@
// Java type names that have no deobfuscation mappings.
optional UnmappedJavaSymbols unmapped_java_symbols = 19;
+ optional AndroidHwuiMetric android_hwui_metric = 20;
+
// Demo extensions.
extensions 450 to 499;
diff --git a/protos/perfetto/trace/BUILD.gn b/protos/perfetto/trace/BUILD.gn
index ebcdfde..9f27411 100644
--- a/protos/perfetto/trace/BUILD.gn
+++ b/protos/perfetto/trace/BUILD.gn
@@ -93,9 +93,7 @@
}
perfetto_proto_library("minimal_@TYPE@") {
- deps = [
- "../config:@TYPE@",
- ]
+ deps = [ "../config:@TYPE@" ]
sources = proto_sources_minimal
}
@@ -103,18 +101,14 @@
# autogenerated merged proto has a valid syntax.
perfetto_proto_library("merged_trace") {
proto_generators = [ "lite" ]
- sources = [
- "perfetto_trace.proto",
- ]
+ sources = [ "perfetto_trace.proto" ]
}
if (perfetto_build_standalone) {
perfetto_proto_library("descriptor") {
proto_generators = [ "descriptor" ]
generate_descriptor = "trace.descriptor"
- sources = [
- "trace.proto",
- ]
+ sources = [ "trace.proto" ]
}
}
@@ -122,7 +116,5 @@
# targets to implement custom parsers based on our protos.
static_library("perfetto_trace_protos") {
complete_static_lib = true
- deps = [
- ":lite",
- ]
+ deps = [ ":lite" ]
}
diff --git a/protos/perfetto/trace/android/BUILD.gn b/protos/perfetto/trace/android/BUILD.gn
index 3a8334b..98163d6 100644
--- a/protos/perfetto/trace/android/BUILD.gn
+++ b/protos/perfetto/trace/android/BUILD.gn
@@ -15,9 +15,7 @@
import("../../../../gn/proto_library.gni")
perfetto_proto_library("@TYPE@") {
- deps = [
- "../../common:@TYPE@",
- ]
+ deps = [ "../../common:@TYPE@" ]
sources = [
"android_log.proto",
diff --git a/protos/perfetto/trace/android/android_log.proto b/protos/perfetto/trace/android/android_log.proto
index 41edacc..4ee0a5d 100644
--- a/protos/perfetto/trace/android/android_log.proto
+++ b/protos/perfetto/trace/android/android_log.proto
@@ -15,7 +15,6 @@
*/
syntax = "proto2";
-option optimize_for = LITE_RUNTIME;
package perfetto.protos;
import "protos/perfetto/common/android_log_constants.proto";
diff --git a/protos/perfetto/trace/android/graphics_frame_event.proto b/protos/perfetto/trace/android/graphics_frame_event.proto
index 36cfa39..616aca8 100644
--- a/protos/perfetto/trace/android/graphics_frame_event.proto
+++ b/protos/perfetto/trace/android/graphics_frame_event.proto
@@ -15,7 +15,6 @@
*/
syntax = "proto2";
-option optimize_for = LITE_RUNTIME;
package perfetto.protos;
// Generated by Android's SurfaceFlinger.
diff --git a/protos/perfetto/trace/android/packages_list.proto b/protos/perfetto/trace/android/packages_list.proto
index 8ae6200..1c4100f 100644
--- a/protos/perfetto/trace/android/packages_list.proto
+++ b/protos/perfetto/trace/android/packages_list.proto
@@ -15,7 +15,6 @@
*/
syntax = "proto2";
-option optimize_for = LITE_RUNTIME;
package perfetto.protos;
message PackagesList {
diff --git a/protos/perfetto/trace/chrome/BUILD.gn b/protos/perfetto/trace/chrome/BUILD.gn
index e49afe9..dc4ecb2 100644
--- a/protos/perfetto/trace/chrome/BUILD.gn
+++ b/protos/perfetto/trace/chrome/BUILD.gn
@@ -33,7 +33,5 @@
"../profiling:@TYPE@",
"../track_event:@TYPE@",
]
- sources = [
- "chrome_trace_packet.proto",
- ]
+ sources = [ "chrome_trace_packet.proto" ]
}
diff --git a/protos/perfetto/trace/chrome/chrome_benchmark_metadata.proto b/protos/perfetto/trace/chrome/chrome_benchmark_metadata.proto
index 1500660..af26892 100644
--- a/protos/perfetto/trace/chrome/chrome_benchmark_metadata.proto
+++ b/protos/perfetto/trace/chrome/chrome_benchmark_metadata.proto
@@ -15,7 +15,6 @@
*/
syntax = "proto2";
-option optimize_for = LITE_RUNTIME;
package perfetto.protos;
// This message is not intended to be written by the chrome on the device.
diff --git a/protos/perfetto/trace/chrome/chrome_metadata.proto b/protos/perfetto/trace/chrome/chrome_metadata.proto
index 9e91c8f..e08aebb 100644
--- a/protos/perfetto/trace/chrome/chrome_metadata.proto
+++ b/protos/perfetto/trace/chrome/chrome_metadata.proto
@@ -15,7 +15,6 @@
*/
syntax = "proto2";
-option optimize_for = LITE_RUNTIME;
package perfetto.protos;
diff --git a/protos/perfetto/trace/chrome/chrome_trace_event.proto b/protos/perfetto/trace/chrome/chrome_trace_event.proto
index 62c0ad3..1c3725c 100644
--- a/protos/perfetto/trace/chrome/chrome_trace_event.proto
+++ b/protos/perfetto/trace/chrome/chrome_trace_event.proto
@@ -15,7 +15,6 @@
*/
syntax = "proto2";
-option optimize_for = LITE_RUNTIME;
package perfetto.protos;
message ChromeTracedValue {
diff --git a/protos/perfetto/trace/chrome/chrome_trace_packet.proto b/protos/perfetto/trace/chrome/chrome_trace_packet.proto
index 956f07d..ae0201d 100644
--- a/protos/perfetto/trace/chrome/chrome_trace_packet.proto
+++ b/protos/perfetto/trace/chrome/chrome_trace_packet.proto
@@ -24,7 +24,6 @@
// https://android-review.googlesource.com/c/platform/external/perfetto/+/
// 591673#17 for details.
syntax = "proto3";
-option optimize_for = LITE_RUNTIME;
import "protos/perfetto/common/trace_stats.proto";
import "protos/perfetto/config/trace_config.proto";
diff --git a/protos/perfetto/trace/clock_snapshot.proto b/protos/perfetto/trace/clock_snapshot.proto
index e3dff0f..16c6ce5 100644
--- a/protos/perfetto/trace/clock_snapshot.proto
+++ b/protos/perfetto/trace/clock_snapshot.proto
@@ -15,7 +15,6 @@
*/
syntax = "proto2";
-option optimize_for = LITE_RUNTIME;
package perfetto.protos;
diff --git a/protos/perfetto/trace/filesystem/BUILD.gn b/protos/perfetto/trace/filesystem/BUILD.gn
index 7d415e1..96d7d65 100644
--- a/protos/perfetto/trace/filesystem/BUILD.gn
+++ b/protos/perfetto/trace/filesystem/BUILD.gn
@@ -15,7 +15,5 @@
import("../../../../gn/proto_library.gni")
perfetto_proto_library("@TYPE@") {
- sources = [
- "inode_file_map.proto",
- ]
+ sources = [ "inode_file_map.proto" ]
}
diff --git a/protos/perfetto/trace/filesystem/inode_file_map.proto b/protos/perfetto/trace/filesystem/inode_file_map.proto
index 92f8581..e1d4c98 100644
--- a/protos/perfetto/trace/filesystem/inode_file_map.proto
+++ b/protos/perfetto/trace/filesystem/inode_file_map.proto
@@ -15,7 +15,6 @@
*/
syntax = "proto2";
-option optimize_for = LITE_RUNTIME;
package perfetto.protos;
// Represents the mapping between inode numbers in a block device and their path
diff --git a/protos/perfetto/trace/ftrace/BUILD.gn b/protos/perfetto/trace/ftrace/BUILD.gn
index 3fa8cc0..5684450 100644
--- a/protos/perfetto/trace/ftrace/BUILD.gn
+++ b/protos/perfetto/trace/ftrace/BUILD.gn
@@ -29,8 +29,6 @@
perfetto_proto_library("descriptor") {
proto_generators = [ "descriptor" ]
generate_descriptor = "ftrace.descriptor"
- sources = [
- "ftrace_event_bundle.proto",
- ]
+ sources = [ "ftrace_event_bundle.proto" ]
}
}
diff --git a/protos/perfetto/trace/ftrace/binder.proto b/protos/perfetto/trace/ftrace/binder.proto
index 89187e6..ecec4a1 100644
--- a/protos/perfetto/trace/ftrace/binder.proto
+++ b/protos/perfetto/trace/ftrace/binder.proto
@@ -3,7 +3,6 @@
// Do not edit.
syntax = "proto2";
-option optimize_for = LITE_RUNTIME;
package perfetto.protos;
message BinderTransactionFtraceEvent {
diff --git a/protos/perfetto/trace/ftrace/block.proto b/protos/perfetto/trace/ftrace/block.proto
index 27d6a69..c39a7a2 100644
--- a/protos/perfetto/trace/ftrace/block.proto
+++ b/protos/perfetto/trace/ftrace/block.proto
@@ -3,7 +3,6 @@
// Do not edit.
syntax = "proto2";
-option optimize_for = LITE_RUNTIME;
package perfetto.protos;
message BlockRqIssueFtraceEvent {
diff --git a/protos/perfetto/trace/ftrace/cgroup.proto b/protos/perfetto/trace/ftrace/cgroup.proto
index 0e52c1e..b8a7d1e 100644
--- a/protos/perfetto/trace/ftrace/cgroup.proto
+++ b/protos/perfetto/trace/ftrace/cgroup.proto
@@ -3,7 +3,6 @@
// Do not edit.
syntax = "proto2";
-option optimize_for = LITE_RUNTIME;
package perfetto.protos;
message CgroupAttachTaskFtraceEvent {
diff --git a/protos/perfetto/trace/ftrace/clk.proto b/protos/perfetto/trace/ftrace/clk.proto
index ae6470d..6d5b753 100644
--- a/protos/perfetto/trace/ftrace/clk.proto
+++ b/protos/perfetto/trace/ftrace/clk.proto
@@ -3,7 +3,6 @@
// Do not edit.
syntax = "proto2";
-option optimize_for = LITE_RUNTIME;
package perfetto.protos;
message ClkEnableFtraceEvent {
diff --git a/protos/perfetto/trace/ftrace/compaction.proto b/protos/perfetto/trace/ftrace/compaction.proto
index 2d24a48..cb57262 100644
--- a/protos/perfetto/trace/ftrace/compaction.proto
+++ b/protos/perfetto/trace/ftrace/compaction.proto
@@ -3,7 +3,6 @@
// Do not edit.
syntax = "proto2";
-option optimize_for = LITE_RUNTIME;
package perfetto.protos;
message MmCompactionBeginFtraceEvent {
diff --git a/protos/perfetto/trace/ftrace/ext4.proto b/protos/perfetto/trace/ftrace/ext4.proto
index 4c7d7a0..90d0322 100644
--- a/protos/perfetto/trace/ftrace/ext4.proto
+++ b/protos/perfetto/trace/ftrace/ext4.proto
@@ -3,7 +3,6 @@
// Do not edit.
syntax = "proto2";
-option optimize_for = LITE_RUNTIME;
package perfetto.protos;
message Ext4DaWriteBeginFtraceEvent {
diff --git a/protos/perfetto/trace/ftrace/f2fs.proto b/protos/perfetto/trace/ftrace/f2fs.proto
index 2526b92..556c964 100644
--- a/protos/perfetto/trace/ftrace/f2fs.proto
+++ b/protos/perfetto/trace/ftrace/f2fs.proto
@@ -3,7 +3,6 @@
// Do not edit.
syntax = "proto2";
-option optimize_for = LITE_RUNTIME;
package perfetto.protos;
message F2fsDoSubmitBioFtraceEvent {
diff --git a/protos/perfetto/trace/ftrace/fence.proto b/protos/perfetto/trace/ftrace/fence.proto
index a03fb1a..141a509 100644
--- a/protos/perfetto/trace/ftrace/fence.proto
+++ b/protos/perfetto/trace/ftrace/fence.proto
@@ -3,7 +3,6 @@
// Do not edit.
syntax = "proto2";
-option optimize_for = LITE_RUNTIME;
package perfetto.protos;
message FenceInitFtraceEvent {
diff --git a/protos/perfetto/trace/ftrace/filemap.proto b/protos/perfetto/trace/ftrace/filemap.proto
index 82d892f..3d70c1f 100644
--- a/protos/perfetto/trace/ftrace/filemap.proto
+++ b/protos/perfetto/trace/ftrace/filemap.proto
@@ -3,7 +3,6 @@
// Do not edit.
syntax = "proto2";
-option optimize_for = LITE_RUNTIME;
package perfetto.protos;
message MmFilemapAddToPageCacheFtraceEvent {
diff --git a/protos/perfetto/trace/ftrace/ftrace.proto b/protos/perfetto/trace/ftrace/ftrace.proto
index 86b7a6d..9fc6f56 100644
--- a/protos/perfetto/trace/ftrace/ftrace.proto
+++ b/protos/perfetto/trace/ftrace/ftrace.proto
@@ -3,7 +3,6 @@
// Do not edit.
syntax = "proto2";
-option optimize_for = LITE_RUNTIME;
package perfetto.protos;
message PrintFtraceEvent {
diff --git a/protos/perfetto/trace/ftrace/ftrace_event.proto b/protos/perfetto/trace/ftrace/ftrace_event.proto
index d6dfc74..38e4adc 100644
--- a/protos/perfetto/trace/ftrace/ftrace_event.proto
+++ b/protos/perfetto/trace/ftrace/ftrace_event.proto
@@ -19,7 +19,6 @@
// Do not edit.
syntax = "proto2";
-option optimize_for = LITE_RUNTIME;
import "protos/perfetto/trace/ftrace/binder.proto";
import "protos/perfetto/trace/ftrace/block.proto";
diff --git a/protos/perfetto/trace/ftrace/ftrace_event_bundle.proto b/protos/perfetto/trace/ftrace/ftrace_event_bundle.proto
index 1d69b1f..69aedaa 100644
--- a/protos/perfetto/trace/ftrace/ftrace_event_bundle.proto
+++ b/protos/perfetto/trace/ftrace/ftrace_event_bundle.proto
@@ -15,7 +15,6 @@
*/
syntax = "proto2";
-option optimize_for = LITE_RUNTIME;
import "protos/perfetto/trace/ftrace/ftrace_event.proto";
diff --git a/protos/perfetto/trace/ftrace/ftrace_stats.proto b/protos/perfetto/trace/ftrace/ftrace_stats.proto
index 53fc392..5e6ea92 100644
--- a/protos/perfetto/trace/ftrace/ftrace_stats.proto
+++ b/protos/perfetto/trace/ftrace/ftrace_stats.proto
@@ -15,7 +15,6 @@
*/
syntax = "proto2";
-option optimize_for = LITE_RUNTIME;
package perfetto.protos;
diff --git a/protos/perfetto/trace/ftrace/generic.proto b/protos/perfetto/trace/ftrace/generic.proto
index 54aec3d..65d5c95 100644
--- a/protos/perfetto/trace/ftrace/generic.proto
+++ b/protos/perfetto/trace/ftrace/generic.proto
@@ -15,7 +15,6 @@
*/
syntax = "proto2";
-option optimize_for = LITE_RUNTIME;
package perfetto.protos;
diff --git a/protos/perfetto/trace/ftrace/i2c.proto b/protos/perfetto/trace/ftrace/i2c.proto
index e35f17c..8fffd40 100644
--- a/protos/perfetto/trace/ftrace/i2c.proto
+++ b/protos/perfetto/trace/ftrace/i2c.proto
@@ -3,7 +3,6 @@
// Do not edit.
syntax = "proto2";
-option optimize_for = LITE_RUNTIME;
package perfetto.protos;
message I2cReadFtraceEvent {
diff --git a/protos/perfetto/trace/ftrace/ipi.proto b/protos/perfetto/trace/ftrace/ipi.proto
index e267bff..73aeebe 100644
--- a/protos/perfetto/trace/ftrace/ipi.proto
+++ b/protos/perfetto/trace/ftrace/ipi.proto
@@ -3,7 +3,6 @@
// Do not edit.
syntax = "proto2";
-option optimize_for = LITE_RUNTIME;
package perfetto.protos;
message IpiEntryFtraceEvent {
diff --git a/protos/perfetto/trace/ftrace/irq.proto b/protos/perfetto/trace/ftrace/irq.proto
index f5d532b..8e9c786 100644
--- a/protos/perfetto/trace/ftrace/irq.proto
+++ b/protos/perfetto/trace/ftrace/irq.proto
@@ -3,7 +3,6 @@
// Do not edit.
syntax = "proto2";
-option optimize_for = LITE_RUNTIME;
package perfetto.protos;
message SoftirqEntryFtraceEvent {
diff --git a/protos/perfetto/trace/ftrace/kfree.proto b/protos/perfetto/trace/ftrace/kfree.proto
index 2597408..3a5ce00 100644
--- a/protos/perfetto/trace/ftrace/kfree.proto
+++ b/protos/perfetto/trace/ftrace/kfree.proto
@@ -3,7 +3,6 @@
// Do not edit.
syntax = "proto2";
-option optimize_for = LITE_RUNTIME;
package perfetto.protos;
message KfreeFtraceEvent {
diff --git a/protos/perfetto/trace/ftrace/kmalloc.proto b/protos/perfetto/trace/ftrace/kmalloc.proto
index d4b4f91..81d7d99 100644
--- a/protos/perfetto/trace/ftrace/kmalloc.proto
+++ b/protos/perfetto/trace/ftrace/kmalloc.proto
@@ -3,7 +3,6 @@
// Do not edit.
syntax = "proto2";
-option optimize_for = LITE_RUNTIME;
package perfetto.protos;
message KmallocFtraceEvent {
diff --git a/protos/perfetto/trace/ftrace/kmem.proto b/protos/perfetto/trace/ftrace/kmem.proto
index b207d2b..e9c52de 100644
--- a/protos/perfetto/trace/ftrace/kmem.proto
+++ b/protos/perfetto/trace/ftrace/kmem.proto
@@ -3,7 +3,6 @@
// Do not edit.
syntax = "proto2";
-option optimize_for = LITE_RUNTIME;
package perfetto.protos;
message AllocPagesIommuEndFtraceEvent {
diff --git a/protos/perfetto/trace/ftrace/lowmemorykiller.proto b/protos/perfetto/trace/ftrace/lowmemorykiller.proto
index ea1ce0d..67c7f5e 100644
--- a/protos/perfetto/trace/ftrace/lowmemorykiller.proto
+++ b/protos/perfetto/trace/ftrace/lowmemorykiller.proto
@@ -3,7 +3,6 @@
// Do not edit.
syntax = "proto2";
-option optimize_for = LITE_RUNTIME;
package perfetto.protos;
message LowmemoryKillFtraceEvent {
diff --git a/protos/perfetto/trace/ftrace/mdss.proto b/protos/perfetto/trace/ftrace/mdss.proto
index 9345111..d7b3c42 100644
--- a/protos/perfetto/trace/ftrace/mdss.proto
+++ b/protos/perfetto/trace/ftrace/mdss.proto
@@ -3,7 +3,6 @@
// Do not edit.
syntax = "proto2";
-option optimize_for = LITE_RUNTIME;
package perfetto.protos;
message MdpCmdKickoffFtraceEvent {
diff --git a/protos/perfetto/trace/ftrace/mm_event.proto b/protos/perfetto/trace/ftrace/mm_event.proto
index 063e214..59b91db 100644
--- a/protos/perfetto/trace/ftrace/mm_event.proto
+++ b/protos/perfetto/trace/ftrace/mm_event.proto
@@ -3,7 +3,6 @@
// Do not edit.
syntax = "proto2";
-option optimize_for = LITE_RUNTIME;
package perfetto.protos;
message MmEventRecordFtraceEvent {
diff --git a/protos/perfetto/trace/ftrace/oom.proto b/protos/perfetto/trace/ftrace/oom.proto
index da46153..015f2da 100644
--- a/protos/perfetto/trace/ftrace/oom.proto
+++ b/protos/perfetto/trace/ftrace/oom.proto
@@ -3,7 +3,6 @@
// Do not edit.
syntax = "proto2";
-option optimize_for = LITE_RUNTIME;
package perfetto.protos;
message OomScoreAdjUpdateFtraceEvent {
diff --git a/protos/perfetto/trace/ftrace/power.proto b/protos/perfetto/trace/ftrace/power.proto
index a79cc03..f38015a 100644
--- a/protos/perfetto/trace/ftrace/power.proto
+++ b/protos/perfetto/trace/ftrace/power.proto
@@ -3,7 +3,6 @@
// Do not edit.
syntax = "proto2";
-option optimize_for = LITE_RUNTIME;
package perfetto.protos;
message CpuFrequencyFtraceEvent {
diff --git a/protos/perfetto/trace/ftrace/print.proto b/protos/perfetto/trace/ftrace/print.proto
index 86b7a6d..9fc6f56 100644
--- a/protos/perfetto/trace/ftrace/print.proto
+++ b/protos/perfetto/trace/ftrace/print.proto
@@ -3,7 +3,6 @@
// Do not edit.
syntax = "proto2";
-option optimize_for = LITE_RUNTIME;
package perfetto.protos;
message PrintFtraceEvent {
diff --git a/protos/perfetto/trace/ftrace/raw_syscalls.proto b/protos/perfetto/trace/ftrace/raw_syscalls.proto
index 0dda679..405202b 100644
--- a/protos/perfetto/trace/ftrace/raw_syscalls.proto
+++ b/protos/perfetto/trace/ftrace/raw_syscalls.proto
@@ -3,7 +3,6 @@
// Do not edit.
syntax = "proto2";
-option optimize_for = LITE_RUNTIME;
package perfetto.protos;
message SysEnterFtraceEvent {
diff --git a/protos/perfetto/trace/ftrace/regulator.proto b/protos/perfetto/trace/ftrace/regulator.proto
index 97a42ef..1776b05 100644
--- a/protos/perfetto/trace/ftrace/regulator.proto
+++ b/protos/perfetto/trace/ftrace/regulator.proto
@@ -3,7 +3,6 @@
// Do not edit.
syntax = "proto2";
-option optimize_for = LITE_RUNTIME;
package perfetto.protos;
message RegulatorDisableFtraceEvent {
diff --git a/protos/perfetto/trace/ftrace/sched.proto b/protos/perfetto/trace/ftrace/sched.proto
index 4d546b4..9c31fac 100644
--- a/protos/perfetto/trace/ftrace/sched.proto
+++ b/protos/perfetto/trace/ftrace/sched.proto
@@ -3,7 +3,6 @@
// Do not edit.
syntax = "proto2";
-option optimize_for = LITE_RUNTIME;
package perfetto.protos;
message SchedSwitchFtraceEvent {
diff --git a/protos/perfetto/trace/ftrace/sde.proto b/protos/perfetto/trace/ftrace/sde.proto
index fbafd2e..724a9a3 100644
--- a/protos/perfetto/trace/ftrace/sde.proto
+++ b/protos/perfetto/trace/ftrace/sde.proto
@@ -3,7 +3,6 @@
// Do not edit.
syntax = "proto2";
-option optimize_for = LITE_RUNTIME;
package perfetto.protos;
message SdeTracingMarkWriteFtraceEvent {
diff --git a/protos/perfetto/trace/ftrace/signal.proto b/protos/perfetto/trace/ftrace/signal.proto
index 41b26bd..6e76d0e 100644
--- a/protos/perfetto/trace/ftrace/signal.proto
+++ b/protos/perfetto/trace/ftrace/signal.proto
@@ -3,7 +3,6 @@
// Do not edit.
syntax = "proto2";
-option optimize_for = LITE_RUNTIME;
package perfetto.protos;
message SignalDeliverFtraceEvent {
diff --git a/protos/perfetto/trace/ftrace/sync.proto b/protos/perfetto/trace/ftrace/sync.proto
index cf5a6d8..0105a9d 100644
--- a/protos/perfetto/trace/ftrace/sync.proto
+++ b/protos/perfetto/trace/ftrace/sync.proto
@@ -3,7 +3,6 @@
// Do not edit.
syntax = "proto2";
-option optimize_for = LITE_RUNTIME;
package perfetto.protos;
message SyncPtFtraceEvent {
diff --git a/protos/perfetto/trace/ftrace/systrace.proto b/protos/perfetto/trace/ftrace/systrace.proto
index b52b305..5296125 100644
--- a/protos/perfetto/trace/ftrace/systrace.proto
+++ b/protos/perfetto/trace/ftrace/systrace.proto
@@ -3,7 +3,6 @@
// Do not edit.
syntax = "proto2";
-option optimize_for = LITE_RUNTIME;
package perfetto.protos;
message ZeroFtraceEvent {
diff --git a/protos/perfetto/trace/ftrace/task.proto b/protos/perfetto/trace/ftrace/task.proto
index 4e966aa..878e04f 100644
--- a/protos/perfetto/trace/ftrace/task.proto
+++ b/protos/perfetto/trace/ftrace/task.proto
@@ -3,7 +3,6 @@
// Do not edit.
syntax = "proto2";
-option optimize_for = LITE_RUNTIME;
package perfetto.protos;
message TaskNewtaskFtraceEvent {
diff --git a/protos/perfetto/trace/ftrace/test_bundle_wrapper.proto b/protos/perfetto/trace/ftrace/test_bundle_wrapper.proto
index c15c3f6..72c1344 100644
--- a/protos/perfetto/trace/ftrace/test_bundle_wrapper.proto
+++ b/protos/perfetto/trace/ftrace/test_bundle_wrapper.proto
@@ -15,7 +15,6 @@
*/
syntax = "proto2";
-option optimize_for = LITE_RUNTIME;
package perfetto.protos;
import "protos/perfetto/trace/ftrace/ftrace_event_bundle.proto";
diff --git a/protos/perfetto/trace/ftrace/vmscan.proto b/protos/perfetto/trace/ftrace/vmscan.proto
index 242acff..f5c5f66 100644
--- a/protos/perfetto/trace/ftrace/vmscan.proto
+++ b/protos/perfetto/trace/ftrace/vmscan.proto
@@ -3,7 +3,6 @@
// Do not edit.
syntax = "proto2";
-option optimize_for = LITE_RUNTIME;
package perfetto.protos;
message MmVmscanDirectReclaimBeginFtraceEvent {
diff --git a/protos/perfetto/trace/ftrace/workqueue.proto b/protos/perfetto/trace/ftrace/workqueue.proto
index 23cc342..dd68361 100644
--- a/protos/perfetto/trace/ftrace/workqueue.proto
+++ b/protos/perfetto/trace/ftrace/workqueue.proto
@@ -3,7 +3,6 @@
// Do not edit.
syntax = "proto2";
-option optimize_for = LITE_RUNTIME;
package perfetto.protos;
message WorkqueueActivateWorkFtraceEvent {
diff --git a/protos/perfetto/trace/gpu/BUILD.gn b/protos/perfetto/trace/gpu/BUILD.gn
index fd1ba9f..6caf06c 100644
--- a/protos/perfetto/trace/gpu/BUILD.gn
+++ b/protos/perfetto/trace/gpu/BUILD.gn
@@ -15,9 +15,7 @@
import("../../../../gn/proto_library.gni")
perfetto_proto_library("@TYPE@") {
- deps = [
- "../../common:@TYPE@",
- ]
+ deps = [ "../../common:@TYPE@" ]
sources = [
"gpu_counter_event.proto",
"gpu_log.proto",
diff --git a/protos/perfetto/trace/gpu/gpu_counter_event.proto b/protos/perfetto/trace/gpu/gpu_counter_event.proto
index fe3a8f0..ee109b2 100644
--- a/protos/perfetto/trace/gpu/gpu_counter_event.proto
+++ b/protos/perfetto/trace/gpu/gpu_counter_event.proto
@@ -15,7 +15,6 @@
*/
syntax = "proto2";
-option optimize_for = LITE_RUNTIME;
package perfetto.protos;
diff --git a/protos/perfetto/trace/gpu/gpu_log.proto b/protos/perfetto/trace/gpu/gpu_log.proto
index 1c39bc0..3c10e36 100644
--- a/protos/perfetto/trace/gpu/gpu_log.proto
+++ b/protos/perfetto/trace/gpu/gpu_log.proto
@@ -15,7 +15,6 @@
*/
syntax = "proto2";
-option optimize_for = LITE_RUNTIME;
package perfetto.protos;
diff --git a/protos/perfetto/trace/gpu/gpu_render_stage_event.proto b/protos/perfetto/trace/gpu/gpu_render_stage_event.proto
index 6e62a4b..16f8b00 100644
--- a/protos/perfetto/trace/gpu/gpu_render_stage_event.proto
+++ b/protos/perfetto/trace/gpu/gpu_render_stage_event.proto
@@ -15,7 +15,6 @@
*/
syntax = "proto2";
-option optimize_for = LITE_RUNTIME;
package perfetto.protos;
diff --git a/protos/perfetto/trace/gpu/vulkan_api_event.proto b/protos/perfetto/trace/gpu/vulkan_api_event.proto
index 5b7ef04..08d9947 100644
--- a/protos/perfetto/trace/gpu/vulkan_api_event.proto
+++ b/protos/perfetto/trace/gpu/vulkan_api_event.proto
@@ -15,18 +15,20 @@
*/
syntax = "proto2";
-option optimize_for = LITE_RUNTIME;
package perfetto.protos;
// Message for recording the Vulkan call.
message VulkanApiEvent {
- oneof event { VkDebugUtilsObjectName vk_debug_utils_object_name = 1; }
+ oneof event {
+ VkDebugUtilsObjectName vk_debug_utils_object_name = 1;
+ VkQueueSubmit vk_queue_submit = 2;
+ }
// For recording vkSetDebugUtilsObjectNameEXT and
// vkDebugMarkerSetObjectNameEXT
message VkDebugUtilsObjectName {
- optional int32 pid = 1;
+ optional uint32 pid = 1;
optional uint64 vk_device = 2;
// VkObjectType. Value must match
// https://www.khronos.org/registry/vulkan/specs/1.1-extensions/man/html/VkObjectType.html.
@@ -34,4 +36,17 @@
optional uint64 object = 4;
optional string object_name = 5;
}
+
+ // For recording vkQueueSubmit call.
+ message VkQueueSubmit {
+ optional uint64 duration_ns = 1;
+ optional uint32 pid = 2;
+ optional uint32 tid = 3;
+ optional uint64 vk_queue = 4;
+ repeated uint64 vk_command_buffers = 5;
+ // Submission ID. An identifier unique to each vkQueueSubmit call. This
+ // submission_id must match GpuRenderStageEvent.submission_id if the
+ // GpuRenderStageEvent is created due to this vkQueueSubmit.
+ optional uint32 submission_id = 6;
+ }
}
diff --git a/protos/perfetto/trace/gpu/vulkan_memory_event.proto b/protos/perfetto/trace/gpu/vulkan_memory_event.proto
index d37bacb..a8963cf 100644
--- a/protos/perfetto/trace/gpu/vulkan_memory_event.proto
+++ b/protos/perfetto/trace/gpu/vulkan_memory_event.proto
@@ -15,7 +15,6 @@
*/
syntax = "proto2";
-option optimize_for = LITE_RUNTIME;
package perfetto.protos;
diff --git a/protos/perfetto/trace/interned_data/BUILD.gn b/protos/perfetto/trace/interned_data/BUILD.gn
index dbda3ab..9ca2273 100644
--- a/protos/perfetto/trace/interned_data/BUILD.gn
+++ b/protos/perfetto/trace/interned_data/BUILD.gn
@@ -15,9 +15,7 @@
import("../../../../gn/proto_library.gni")
perfetto_proto_library("@TYPE@") {
- sources = [
- "interned_data.proto",
- ]
+ sources = [ "interned_data.proto" ]
deps = [
"../profiling:@TYPE@",
"../track_event:@TYPE@",
diff --git a/protos/perfetto/trace/interned_data/interned_data.proto b/protos/perfetto/trace/interned_data/interned_data.proto
index 3cacef9..8b80554 100644
--- a/protos/perfetto/trace/interned_data/interned_data.proto
+++ b/protos/perfetto/trace/interned_data/interned_data.proto
@@ -15,7 +15,6 @@
*/
syntax = "proto2";
-option optimize_for = LITE_RUNTIME;
import "protos/perfetto/trace/track_event/debug_annotation.proto";
import "protos/perfetto/trace/track_event/log_message.proto";
diff --git a/protos/perfetto/trace/perfetto/BUILD.gn b/protos/perfetto/trace/perfetto/BUILD.gn
index 5fc30a4..6e69286 100644
--- a/protos/perfetto/trace/perfetto/BUILD.gn
+++ b/protos/perfetto/trace/perfetto/BUILD.gn
@@ -15,7 +15,5 @@
import("../../../../gn/proto_library.gni")
perfetto_proto_library("@TYPE@") {
- sources = [
- "perfetto_metatrace.proto",
- ]
+ sources = [ "perfetto_metatrace.proto" ]
}
diff --git a/protos/perfetto/trace/perfetto/perfetto_metatrace.proto b/protos/perfetto/trace/perfetto/perfetto_metatrace.proto
index 63ceacb..f096101 100644
--- a/protos/perfetto/trace/perfetto/perfetto_metatrace.proto
+++ b/protos/perfetto/trace/perfetto/perfetto_metatrace.proto
@@ -15,7 +15,6 @@
*/
syntax = "proto2";
-option optimize_for = LITE_RUNTIME;
package perfetto.protos;
diff --git a/protos/perfetto/trace/perfetto_trace.proto b/protos/perfetto/trace/perfetto_trace.proto
index d7ee5c6..d70c75e 100644
--- a/protos/perfetto/trace/perfetto_trace.proto
+++ b/protos/perfetto/trace/perfetto_trace.proto
@@ -4080,7 +4080,7 @@
// Next id: 4.
message ChromeProcessDescriptor {
// See chromium's content::ProcessType.
- enum ChromeProcessType {
+ enum ProcessType {
PROCESS_UNSPECIFIED = 0;
PROCESS_BROWSER = 1;
PROCESS_RENDERER = 2;
@@ -4091,7 +4091,7 @@
PROCESS_PPAPI_PLUGIN = 7;
PROCESS_PPAPI_BROKER = 8;
}
- optional ChromeProcessType process_type = 1;
+ optional ProcessType process_type = 1;
optional int32 process_priority = 2;
// To support old UI. New UI should determine default sorting by process_type.
@@ -4117,8 +4117,8 @@
// Scheduler:
THREAD_POOL_BG_WORKER = 3;
THREAD_POOL_FG_WORKER = 4;
- THREAD_POOL_FB_BLOCKING = 5;
THREAD_POOL_BG_BLOCKING = 6;
+ THREAD_POOL_FG_BLOCKING = 5;
THREAD_POOL_SERVICE = 7;
// Compositor:
@@ -4237,10 +4237,11 @@
// Describes a process's attributes. Emitted as part of a TrackDescriptor,
// usually by the process's main thread.
//
-// Next id: 6.
+// Next id: 7.
message ProcessDescriptor {
optional int32 pid = 1;
repeated string cmdline = 2;
+ optional string process_name = 6;
optional int32 process_priority = 5;
@@ -4357,9 +4358,7 @@
// Begin of protos/perfetto/trace/track_event/track_descriptor.proto
// Defines a track for TrackEvents. Slices and instant events on the same track
-// will be nested based on their timestamps, see TrackEvent::Type. Additionally
-// events on tracks which represent the same thread (i.e., matching pid and tid
-// in ThreadDescriptor) will be merged onto one sequential timeline.
+// will be nested based on their timestamps, see TrackEvent::Type.
//
// A TrackDescriptor only needs to be emitted by one trace writer / producer and
// is valid for the entirety of the trace. To ensure the descriptor isn't lost
@@ -4389,10 +4388,24 @@
// Name of the track.
optional string name = 2;
- // Associate the track with a process or thread - the UI will merge all tracks
- // for the same process / thread into a single timeline view.
+ // Associate the track with a process, making it the process-global track.
+ // There should only be one such track per process (usually for instant
+ // events; trace processor uses this fact to detect pid reuse). If you need
+ // more (e.g. for asynchronous events), create child tracks using parent_uuid.
+ //
+ // Trace processor will merge events on a process track with slice-type events
+ // from other sources (e.g. ftrace) for the same process into a single
+ // timeline view.
optional ProcessDescriptor process = 3;
optional ChromeProcessDescriptor chrome_process = 6;
+
+ // Associate the track with a thread, indicating that the track's events
+ // describe synchronous code execution on the thread. There should only be one
+ // such track per thread (trace processor uses this fact to detect tid reuse).
+ //
+ // Trace processor will merge events on a thread track with slice-type events
+ // from other sources (e.g. ftrace) for the same thread into a single timeline
+ // view.
optional ThreadDescriptor thread = 4;
optional ChromeThreadDescriptor chrome_thread = 7;
}
@@ -4812,12 +4825,15 @@
// Message for recording the Vulkan call.
message VulkanApiEvent {
- oneof event { VkDebugUtilsObjectName vk_debug_utils_object_name = 1; }
+ oneof event {
+ VkDebugUtilsObjectName vk_debug_utils_object_name = 1;
+ VkQueueSubmit vk_queue_submit = 2;
+ }
// For recording vkSetDebugUtilsObjectNameEXT and
// vkDebugMarkerSetObjectNameEXT
message VkDebugUtilsObjectName {
- optional int32 pid = 1;
+ optional uint32 pid = 1;
optional uint64 vk_device = 2;
// VkObjectType. Value must match
// https://www.khronos.org/registry/vulkan/specs/1.1-extensions/man/html/VkObjectType.html.
@@ -4825,6 +4841,19 @@
optional uint64 object = 4;
optional string object_name = 5;
}
+
+ // For recording vkQueueSubmit call.
+ message VkQueueSubmit {
+ optional uint64 duration_ns = 1;
+ optional uint32 pid = 2;
+ optional uint32 tid = 3;
+ optional uint64 vk_queue = 4;
+ repeated uint64 vk_command_buffers = 5;
+ // Submission ID. An identifier unique to each vkQueueSubmit call. This
+ // submission_id must match GpuRenderStageEvent.submission_id if the
+ // GpuRenderStageEvent is created due to this vkQueueSubmit.
+ optional uint32 submission_id = 6;
+ }
}
// End of protos/perfetto/trace/gpu/vulkan_api_event.proto
diff --git a/protos/perfetto/trace/power/battery_counters.proto b/protos/perfetto/trace/power/battery_counters.proto
index 383ecf8..2337c41 100644
--- a/protos/perfetto/trace/power/battery_counters.proto
+++ b/protos/perfetto/trace/power/battery_counters.proto
@@ -15,7 +15,6 @@
*/
syntax = "proto2";
-option optimize_for = LITE_RUNTIME;
package perfetto.protos;
message BatteryCounters {
diff --git a/protos/perfetto/trace/power/power_rails.proto b/protos/perfetto/trace/power/power_rails.proto
index d4a718c..efe8a52 100644
--- a/protos/perfetto/trace/power/power_rails.proto
+++ b/protos/perfetto/trace/power/power_rails.proto
@@ -15,7 +15,6 @@
*/
syntax = "proto2";
-option optimize_for = LITE_RUNTIME;
package perfetto.protos;
message PowerRails {
diff --git a/protos/perfetto/trace/profiling/heap_graph.proto b/protos/perfetto/trace/profiling/heap_graph.proto
index 933d2d0..134168c 100644
--- a/protos/perfetto/trace/profiling/heap_graph.proto
+++ b/protos/perfetto/trace/profiling/heap_graph.proto
@@ -15,7 +15,6 @@
*/
syntax = "proto2";
-option optimize_for = LITE_RUNTIME;
import "protos/perfetto/trace/profiling/profile_common.proto";
diff --git a/protos/perfetto/trace/profiling/profile_common.proto b/protos/perfetto/trace/profiling/profile_common.proto
index 9b88de2..1c0bd6f 100644
--- a/protos/perfetto/trace/profiling/profile_common.proto
+++ b/protos/perfetto/trace/profiling/profile_common.proto
@@ -15,7 +15,6 @@
*/
syntax = "proto2";
-option optimize_for = LITE_RUNTIME;
package perfetto.protos;
diff --git a/protos/perfetto/trace/profiling/profile_packet.proto b/protos/perfetto/trace/profiling/profile_packet.proto
index 300e2b7..845f137 100644
--- a/protos/perfetto/trace/profiling/profile_packet.proto
+++ b/protos/perfetto/trace/profiling/profile_packet.proto
@@ -15,7 +15,6 @@
*/
syntax = "proto2";
-option optimize_for = LITE_RUNTIME;
import "protos/perfetto/trace/profiling/profile_common.proto";
diff --git a/protos/perfetto/trace/ps/process_stats.proto b/protos/perfetto/trace/ps/process_stats.proto
index 5db028f..66b133d 100644
--- a/protos/perfetto/trace/ps/process_stats.proto
+++ b/protos/perfetto/trace/ps/process_stats.proto
@@ -15,7 +15,6 @@
*/
syntax = "proto2";
-option optimize_for = LITE_RUNTIME;
package perfetto.protos;
// Per-process periodically sampled stats. These samples are wrapped in a
diff --git a/protos/perfetto/trace/ps/process_tree.proto b/protos/perfetto/trace/ps/process_tree.proto
index 14d3b6d..446c689 100644
--- a/protos/perfetto/trace/ps/process_tree.proto
+++ b/protos/perfetto/trace/ps/process_tree.proto
@@ -15,7 +15,6 @@
*/
syntax = "proto2";
-option optimize_for = LITE_RUNTIME;
package perfetto.protos;
message ProcessTree {
diff --git a/protos/perfetto/trace/sys_stats/BUILD.gn b/protos/perfetto/trace/sys_stats/BUILD.gn
index aa79c47..594b7e7 100644
--- a/protos/perfetto/trace/sys_stats/BUILD.gn
+++ b/protos/perfetto/trace/sys_stats/BUILD.gn
@@ -15,10 +15,6 @@
import("../../../../gn/proto_library.gni")
perfetto_proto_library("@TYPE@") {
- deps = [
- "../../common:@TYPE@",
- ]
- sources = [
- "sys_stats.proto",
- ]
+ deps = [ "../../common:@TYPE@" ]
+ sources = [ "sys_stats.proto" ]
}
diff --git a/protos/perfetto/trace/sys_stats/sys_stats.proto b/protos/perfetto/trace/sys_stats/sys_stats.proto
index ad7db64..ce485f3 100644
--- a/protos/perfetto/trace/sys_stats/sys_stats.proto
+++ b/protos/perfetto/trace/sys_stats/sys_stats.proto
@@ -15,7 +15,6 @@
*/
syntax = "proto2";
-option optimize_for = LITE_RUNTIME;
package perfetto.protos;
import "protos/perfetto/common/sys_stats_counters.proto";
diff --git a/protos/perfetto/trace/system_info.proto b/protos/perfetto/trace/system_info.proto
index 434061e..4d2fbaa 100644
--- a/protos/perfetto/trace/system_info.proto
+++ b/protos/perfetto/trace/system_info.proto
@@ -15,7 +15,6 @@
*/
syntax = "proto2";
-option optimize_for = LITE_RUNTIME;
package perfetto.protos;
diff --git a/protos/perfetto/trace/test_event.proto b/protos/perfetto/trace/test_event.proto
index 769b6b0..58a4537 100644
--- a/protos/perfetto/trace/test_event.proto
+++ b/protos/perfetto/trace/test_event.proto
@@ -15,7 +15,6 @@
*/
syntax = "proto2";
-option optimize_for = LITE_RUNTIME;
package perfetto.protos;
diff --git a/protos/perfetto/trace/trace.proto b/protos/perfetto/trace/trace.proto
index fa8677e..2a1cd79 100644
--- a/protos/perfetto/trace/trace.proto
+++ b/protos/perfetto/trace/trace.proto
@@ -15,7 +15,6 @@
*/
syntax = "proto2";
-option optimize_for = LITE_RUNTIME;
import "protos/perfetto/trace/trace_packet.proto";
diff --git a/protos/perfetto/trace/trace_packet.proto b/protos/perfetto/trace/trace_packet.proto
index da3b6af..bc3c9bf 100644
--- a/protos/perfetto/trace/trace_packet.proto
+++ b/protos/perfetto/trace/trace_packet.proto
@@ -15,7 +15,6 @@
*/
syntax = "proto2";
-option optimize_for = LITE_RUNTIME;
import "protos/perfetto/common/trace_stats.proto";
import "protos/perfetto/config/trace_config.proto";
diff --git a/protos/perfetto/trace/trace_packet_defaults.proto b/protos/perfetto/trace/trace_packet_defaults.proto
index b6f3e83..032b852 100644
--- a/protos/perfetto/trace/trace_packet_defaults.proto
+++ b/protos/perfetto/trace/trace_packet_defaults.proto
@@ -15,7 +15,6 @@
*/
syntax = "proto2";
-option optimize_for = LITE_RUNTIME;
import "protos/perfetto/trace/track_event/track_event.proto";
diff --git a/protos/perfetto/trace/track_event/chrome_compositor_scheduler_state.proto b/protos/perfetto/trace/track_event/chrome_compositor_scheduler_state.proto
index 40853d7..109180a 100644
--- a/protos/perfetto/trace/track_event/chrome_compositor_scheduler_state.proto
+++ b/protos/perfetto/trace/track_event/chrome_compositor_scheduler_state.proto
@@ -15,7 +15,6 @@
*/
syntax = "proto2";
-option optimize_for = LITE_RUNTIME;
import "protos/perfetto/trace/track_event/source_location.proto";
diff --git a/protos/perfetto/trace/track_event/chrome_histogram_sample.proto b/protos/perfetto/trace/track_event/chrome_histogram_sample.proto
index 902a9dcc..67dd28c 100644
--- a/protos/perfetto/trace/track_event/chrome_histogram_sample.proto
+++ b/protos/perfetto/trace/track_event/chrome_histogram_sample.proto
@@ -15,7 +15,6 @@
*/
syntax = "proto2";
-option optimize_for = LITE_RUNTIME;
package perfetto.protos;
diff --git a/protos/perfetto/trace/track_event/chrome_keyed_service.proto b/protos/perfetto/trace/track_event/chrome_keyed_service.proto
index 95ce21d..1cb3e09 100644
--- a/protos/perfetto/trace/track_event/chrome_keyed_service.proto
+++ b/protos/perfetto/trace/track_event/chrome_keyed_service.proto
@@ -15,7 +15,6 @@
*/
syntax = "proto2";
-option optimize_for = LITE_RUNTIME;
package perfetto.protos;
diff --git a/protos/perfetto/trace/track_event/chrome_legacy_ipc.proto b/protos/perfetto/trace/track_event/chrome_legacy_ipc.proto
index df6dcce..1b03889 100644
--- a/protos/perfetto/trace/track_event/chrome_legacy_ipc.proto
+++ b/protos/perfetto/trace/track_event/chrome_legacy_ipc.proto
@@ -15,7 +15,6 @@
*/
syntax = "proto2";
-option optimize_for = LITE_RUNTIME;
package perfetto.protos;
diff --git a/protos/perfetto/trace/track_event/chrome_process_descriptor.proto b/protos/perfetto/trace/track_event/chrome_process_descriptor.proto
index 25e5d6f..f7d0177 100644
--- a/protos/perfetto/trace/track_event/chrome_process_descriptor.proto
+++ b/protos/perfetto/trace/track_event/chrome_process_descriptor.proto
@@ -15,7 +15,6 @@
*/
syntax = "proto2";
-option optimize_for = LITE_RUNTIME;
package perfetto.protos;
@@ -25,7 +24,7 @@
// Next id: 4.
message ChromeProcessDescriptor {
// See chromium's content::ProcessType.
- enum ChromeProcessType {
+ enum ProcessType {
PROCESS_UNSPECIFIED = 0;
PROCESS_BROWSER = 1;
PROCESS_RENDERER = 2;
@@ -36,7 +35,7 @@
PROCESS_PPAPI_PLUGIN = 7;
PROCESS_PPAPI_BROKER = 8;
}
- optional ChromeProcessType process_type = 1;
+ optional ProcessType process_type = 1;
optional int32 process_priority = 2;
// To support old UI. New UI should determine default sorting by process_type.
diff --git a/protos/perfetto/trace/track_event/chrome_thread_descriptor.proto b/protos/perfetto/trace/track_event/chrome_thread_descriptor.proto
index 0f23e7b..d19e3bd 100644
--- a/protos/perfetto/trace/track_event/chrome_thread_descriptor.proto
+++ b/protos/perfetto/trace/track_event/chrome_thread_descriptor.proto
@@ -15,7 +15,6 @@
*/
syntax = "proto2";
-option optimize_for = LITE_RUNTIME;
package perfetto.protos;
@@ -34,8 +33,8 @@
// Scheduler:
THREAD_POOL_BG_WORKER = 3;
THREAD_POOL_FG_WORKER = 4;
- THREAD_POOL_FB_BLOCKING = 5;
THREAD_POOL_BG_BLOCKING = 6;
+ THREAD_POOL_FG_BLOCKING = 5;
THREAD_POOL_SERVICE = 7;
// Compositor:
diff --git a/protos/perfetto/trace/track_event/chrome_user_event.proto b/protos/perfetto/trace/track_event/chrome_user_event.proto
index 4f6d869..d071830 100644
--- a/protos/perfetto/trace/track_event/chrome_user_event.proto
+++ b/protos/perfetto/trace/track_event/chrome_user_event.proto
@@ -15,7 +15,6 @@
*/
syntax = "proto2";
-option optimize_for = LITE_RUNTIME;
package perfetto.protos;
diff --git a/protos/perfetto/trace/track_event/debug_annotation.proto b/protos/perfetto/trace/track_event/debug_annotation.proto
index 1bbfaa9..8b755d8 100644
--- a/protos/perfetto/trace/track_event/debug_annotation.proto
+++ b/protos/perfetto/trace/track_event/debug_annotation.proto
@@ -15,7 +15,6 @@
*/
syntax = "proto2";
-option optimize_for = LITE_RUNTIME;
package perfetto.protos;
diff --git a/protos/perfetto/trace/track_event/log_message.proto b/protos/perfetto/trace/track_event/log_message.proto
index a2fde6d..55263f9 100644
--- a/protos/perfetto/trace/track_event/log_message.proto
+++ b/protos/perfetto/trace/track_event/log_message.proto
@@ -15,7 +15,6 @@
*/
syntax = "proto2";
-option optimize_for = LITE_RUNTIME;
package perfetto.protos;
diff --git a/protos/perfetto/trace/track_event/process_descriptor.proto b/protos/perfetto/trace/track_event/process_descriptor.proto
index fceb5ba..3ba9049 100644
--- a/protos/perfetto/trace/track_event/process_descriptor.proto
+++ b/protos/perfetto/trace/track_event/process_descriptor.proto
@@ -15,17 +15,17 @@
*/
syntax = "proto2";
-option optimize_for = LITE_RUNTIME;
package perfetto.protos;
// Describes a process's attributes. Emitted as part of a TrackDescriptor,
// usually by the process's main thread.
//
-// Next id: 6.
+// Next id: 7.
message ProcessDescriptor {
optional int32 pid = 1;
repeated string cmdline = 2;
+ optional string process_name = 6;
optional int32 process_priority = 5;
diff --git a/protos/perfetto/trace/track_event/source_location.proto b/protos/perfetto/trace/track_event/source_location.proto
index 39d6bb1..81ed7cf 100644
--- a/protos/perfetto/trace/track_event/source_location.proto
+++ b/protos/perfetto/trace/track_event/source_location.proto
@@ -15,7 +15,6 @@
*/
syntax = "proto2";
-option optimize_for = LITE_RUNTIME;
package perfetto.protos;
diff --git a/protos/perfetto/trace/track_event/task_execution.proto b/protos/perfetto/trace/track_event/task_execution.proto
index 6eebad9..77f4599 100644
--- a/protos/perfetto/trace/track_event/task_execution.proto
+++ b/protos/perfetto/trace/track_event/task_execution.proto
@@ -15,7 +15,6 @@
*/
syntax = "proto2";
-option optimize_for = LITE_RUNTIME;
package perfetto.protos;
diff --git a/protos/perfetto/trace/track_event/thread_descriptor.proto b/protos/perfetto/trace/track_event/thread_descriptor.proto
index 1c14e21..594c1b2 100644
--- a/protos/perfetto/trace/track_event/thread_descriptor.proto
+++ b/protos/perfetto/trace/track_event/thread_descriptor.proto
@@ -15,7 +15,6 @@
*/
syntax = "proto2";
-option optimize_for = LITE_RUNTIME;
package perfetto.protos;
diff --git a/protos/perfetto/trace/track_event/track_descriptor.proto b/protos/perfetto/trace/track_event/track_descriptor.proto
index 35b1ce2..5254b28 100644
--- a/protos/perfetto/trace/track_event/track_descriptor.proto
+++ b/protos/perfetto/trace/track_event/track_descriptor.proto
@@ -15,7 +15,6 @@
*/
syntax = "proto2";
-option optimize_for = LITE_RUNTIME;
import "protos/perfetto/trace/track_event/chrome_process_descriptor.proto";
import "protos/perfetto/trace/track_event/chrome_thread_descriptor.proto";
@@ -25,9 +24,7 @@
package perfetto.protos;
// Defines a track for TrackEvents. Slices and instant events on the same track
-// will be nested based on their timestamps, see TrackEvent::Type. Additionally
-// events on tracks which represent the same thread (i.e., matching pid and tid
-// in ThreadDescriptor) will be merged onto one sequential timeline.
+// will be nested based on their timestamps, see TrackEvent::Type.
//
// A TrackDescriptor only needs to be emitted by one trace writer / producer and
// is valid for the entirety of the trace. To ensure the descriptor isn't lost
@@ -57,10 +54,24 @@
// Name of the track.
optional string name = 2;
- // Associate the track with a process or thread - the UI will merge all tracks
- // for the same process / thread into a single timeline view.
+ // Associate the track with a process, making it the process-global track.
+ // There should only be one such track per process (usually for instant
+ // events; trace processor uses this fact to detect pid reuse). If you need
+ // more (e.g. for asynchronous events), create child tracks using parent_uuid.
+ //
+ // Trace processor will merge events on a process track with slice-type events
+ // from other sources (e.g. ftrace) for the same process into a single
+ // timeline view.
optional ProcessDescriptor process = 3;
optional ChromeProcessDescriptor chrome_process = 6;
+
+ // Associate the track with a thread, indicating that the track's events
+ // describe synchronous code execution on the thread. There should only be one
+ // such track per thread (trace processor uses this fact to detect tid reuse).
+ //
+ // Trace processor will merge events on a thread track with slice-type events
+ // from other sources (e.g. ftrace) for the same thread into a single timeline
+ // view.
optional ThreadDescriptor thread = 4;
optional ChromeThreadDescriptor chrome_thread = 7;
}
diff --git a/protos/perfetto/trace/track_event/track_event.proto b/protos/perfetto/trace/track_event/track_event.proto
index 3d4b635..c566648 100644
--- a/protos/perfetto/trace/track_event/track_event.proto
+++ b/protos/perfetto/trace/track_event/track_event.proto
@@ -15,7 +15,6 @@
*/
syntax = "proto2";
-option optimize_for = LITE_RUNTIME;
import "protos/perfetto/trace/track_event/debug_annotation.proto";
import "protos/perfetto/trace/track_event/log_message.proto";
diff --git a/protos/perfetto/trace/trigger.proto b/protos/perfetto/trace/trigger.proto
index d895d80..759eb4f 100644
--- a/protos/perfetto/trace/trigger.proto
+++ b/protos/perfetto/trace/trigger.proto
@@ -14,7 +14,6 @@
* limitations under the License.
*/
syntax = "proto2";
-option optimize_for = LITE_RUNTIME;
package perfetto.protos;
diff --git a/protos/perfetto/trace_processor/BUILD.gn b/protos/perfetto/trace_processor/BUILD.gn
index e645a3a..461fd9c 100644
--- a/protos/perfetto/trace_processor/BUILD.gn
+++ b/protos/perfetto/trace_processor/BUILD.gn
@@ -25,7 +25,5 @@
perfetto_proto_library("metrics_impl_zero") {
proto_generators = [ "zero" ]
- sources = [
- "metrics_impl.proto",
- ]
+ sources = [ "metrics_impl.proto" ]
}
diff --git a/protos/perfetto/trace_processor/metrics_impl.proto b/protos/perfetto/trace_processor/metrics_impl.proto
index 6ff42f5..281ced8 100644
--- a/protos/perfetto/trace_processor/metrics_impl.proto
+++ b/protos/perfetto/trace_processor/metrics_impl.proto
@@ -15,7 +15,6 @@
*/
syntax = "proto2";
-option optimize_for = LITE_RUNTIME;
package perfetto.protos;
diff --git a/protos/perfetto/trace_processor/trace_processor.proto b/protos/perfetto/trace_processor/trace_processor.proto
index 45804b7..d24d202 100644
--- a/protos/perfetto/trace_processor/trace_processor.proto
+++ b/protos/perfetto/trace_processor/trace_processor.proto
@@ -15,7 +15,6 @@
*/
syntax = "proto2";
-option optimize_for = LITE_RUNTIME;
package perfetto.trace_processor.protos;
diff --git a/protos/third_party/pprof/BUILD.gn b/protos/third_party/pprof/BUILD.gn
index 18c24df..553d0ac 100644
--- a/protos/third_party/pprof/BUILD.gn
+++ b/protos/third_party/pprof/BUILD.gn
@@ -16,7 +16,5 @@
perfetto_proto_library("@TYPE@") {
proto_generators = [ "zero" ]
- sources = [
- "profile.proto",
- ]
+ sources = [ "profile.proto" ]
}
diff --git a/protos/third_party/pprof/profile.proto b/protos/third_party/pprof/profile.proto
index 30a4f6a..23aadc4 100644
--- a/protos/third_party/pprof/profile.proto
+++ b/protos/third_party/pprof/profile.proto
@@ -45,11 +45,6 @@
option java_package = "com.google.perftools.profiles";
option java_outer_classname = "ProfileProto";
-// Perfetto Changes ===========================================================
-// 1. Add optimize_for = LITE_RUNTIME
-option optimize_for = LITE_RUNTIME;
-// ============================================================================
-
message Profile {
// A description of the samples associated with each Sample.value.
// For a cpu profile this might be:
diff --git a/src/android_internal/BUILD.gn b/src/android_internal/BUILD.gn
index 4306b16..956e07c 100644
--- a/src/android_internal/BUILD.gn
+++ b/src/android_internal/BUILD.gn
@@ -39,9 +39,7 @@
}
source_set("lazy_library_loader") {
- public_deps = [
- ":headers",
- ]
+ public_deps = [ ":headers" ]
deps = [
"../../gn:default_deps",
"../../src/base",
@@ -90,8 +88,8 @@
# This target should never depend on any other perfetto target to avoid ODR
# violation by doubly linking code in two .so(s) loaded in the same exe.
assert_no_deps = [
+ "//include/*",
"//src/base/*",
"//src/tracing/*",
- "//include/*",
]
}
diff --git a/src/base/BUILD.gn b/src/base/BUILD.gn
index c786391..b1e4062 100644
--- a/src/base/BUILD.gn
+++ b/src/base/BUILD.gn
@@ -20,9 +20,7 @@
enable_stack_trace = is_debug && perfetto_build_standalone && !is_wasm
source_set("base") {
- deps = [
- "../../gn:default_deps",
- ]
+ deps = [ "../../gn:default_deps" ]
public_deps = [
"../../include/perfetto/base",
"../../include/perfetto/ext/base",
@@ -61,9 +59,7 @@
if (enable_stack_trace) {
source_set("debug_crash_stack_trace") {
- sources = [
- "debug_crash_stack_trace.cc",
- ]
+ sources = [ "debug_crash_stack_trace.cc" ]
deps = [
"../../gn:default_deps",
"../../include/perfetto/ext/base",
@@ -84,9 +80,7 @@
"../../include/perfetto/ext/base",
"../../include/perfetto/ext/base",
]
- sources = [
- "unix_socket.cc",
- ]
+ sources = [ "unix_socket.cc" ]
}
}
@@ -165,8 +159,6 @@
"../../gn:benchmark",
"../../gn:default_deps",
]
- sources = [
- "flat_set_benchmark.cc",
- ]
+ sources = [ "flat_set_benchmark.cc" ]
}
}
diff --git a/src/base/flat_set_benchmark.cc b/src/base/flat_set_benchmark.cc
index 12e5565..0773fbe 100644
--- a/src/base/flat_set_benchmark.cc
+++ b/src/base/flat_set_benchmark.cc
@@ -18,7 +18,7 @@
#include <benchmark/benchmark.h>
-#include "perfetto/ext/base/flat_set.h"
+#include "perfetto/base/flat_set.h"
namespace {
diff --git a/src/base/flat_set_unittest.cc b/src/base/flat_set_unittest.cc
index c853e13..406e05c 100644
--- a/src/base/flat_set_unittest.cc
+++ b/src/base/flat_set_unittest.cc
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-#include "perfetto/ext/base/flat_set.h"
+#include "perfetto/base/flat_set.h"
#include <random>
#include <set>
@@ -38,7 +38,9 @@
EXPECT_EQ(flat_set.find(42), flat_set.end());
EXPECT_EQ(flat_set.find(42), flat_set.begin());
- flat_set.insert(1);
+ auto it_and_inserted = flat_set.insert(1);
+ EXPECT_EQ(it_and_inserted.first, flat_set.find(1));
+ EXPECT_TRUE(it_and_inserted.second);
EXPECT_FALSE(flat_set.empty());
EXPECT_EQ(flat_set.size(), 1u);
{
@@ -52,7 +54,9 @@
EXPECT_NE(flat_set.begin(), flat_set.end());
EXPECT_EQ(std::distance(flat_set.begin(), flat_set.end()), 1);
- flat_set.insert(1);
+ it_and_inserted = flat_set.insert(1);
+ EXPECT_EQ(it_and_inserted.first, flat_set.find(1));
+ EXPECT_FALSE(it_and_inserted.second);
EXPECT_EQ(flat_set.size(), 1u);
EXPECT_TRUE(flat_set.count(1));
EXPECT_FALSE(flat_set.count(0));
@@ -62,10 +66,10 @@
EXPECT_FALSE(flat_set.count(1));
EXPECT_EQ(flat_set.size(), 0u);
- flat_set.insert(7);
- flat_set.insert(-4);
- flat_set.insert(11);
- flat_set.insert(-13);
+ EXPECT_TRUE(flat_set.insert(7).second);
+ EXPECT_TRUE(flat_set.insert(-4).second);
+ EXPECT_TRUE(flat_set.insert(11).second);
+ EXPECT_TRUE(flat_set.insert(-13).second);
EXPECT_TRUE(flat_set.count(7));
EXPECT_TRUE(flat_set.count(-4));
EXPECT_TRUE(flat_set.count(11));
@@ -94,8 +98,11 @@
for (int i = 0; i < 10000; i++) {
const int val = int_dist(rng);
if (i % 3) {
- flat_set.insert(val);
- gold_set.insert(val);
+ auto flat_result = flat_set.insert(val);
+ auto gold_result = gold_set.insert(val);
+ EXPECT_EQ(flat_result.first, flat_set.find(val));
+ EXPECT_EQ(gold_result.first, gold_set.find(val));
+ EXPECT_EQ(flat_result.second, gold_result.second);
} else {
flat_set.erase(val);
gold_set.erase(val);
diff --git a/src/base/logging.cc b/src/base/logging.cc
index d38e263..b733988 100644
--- a/src/base/logging.cc
+++ b/src/base/logging.cc
@@ -125,11 +125,11 @@
// to correlated events across differrent processses (e.g. traced and
// traced_probes). The wall time % 1000 is good enough.
char timestamp[32];
- int t_ms = static_cast<int>(GetWallTimeMs().count());
- int t_sec = t_ms / 1000;
+ uint32_t t_ms = static_cast<uint32_t>(GetWallTimeMs().count());
+ uint32_t t_sec = t_ms / 1000;
t_ms -= t_sec * 1000;
t_sec = t_sec % 1000;
- snprintf(timestamp, sizeof(timestamp), "[%03d.%03d] ", t_sec, t_ms);
+ snprintf(timestamp, sizeof(timestamp), "[%03u.%03u] ", t_sec, t_ms);
if (use_colors) {
fprintf(stderr, "%s%s%s%s %s%s%s\n", kLightGray, timestamp, file_and_line,
diff --git a/src/base/paged_memory.cc b/src/base/paged_memory.cc
index a214de3..c7feb53 100644
--- a/src/base/paged_memory.cc
+++ b/src/base/paged_memory.cc
@@ -113,16 +113,18 @@
PERFETTO_DCHECK(p_);
PERFETTO_DCHECK(p >= p_);
PERFETTO_DCHECK(static_cast<char*>(p) + size <= p_ + size_);
-#if PERFETTO_BUILDFLAG(PERFETTO_OS_WIN)
+#if PERFETTO_BUILDFLAG(PERFETTO_OS_WIN) || PERFETTO_BUILDFLAG(PERFETTO_OS_NACL)
// Discarding pages on Windows has more CPU cost than is justified for the
// possible memory savings.
return false;
-#else // PERFETTO_BUILDFLAG(PERFETTO_OS_WIN)
+#else // PERFETTO_BUILDFLAG(PERFETTO_OS_WIN) ||
+ // PERFETTO_BUILDFLAG(PERFETTO_OS_NACL)
// http://man7.org/linux/man-pages/man2/madvise.2.html
int res = madvise(p, size, MADV_DONTNEED);
PERFETTO_DCHECK(res == 0);
return true;
-#endif // PERFETTO_BUILDFLAG(PERFETTO_OS_WIN)
+#endif // PERFETTO_BUILDFLAG(PERFETTO_OS_WIN) ||
+ // PERFETTO_BUILDFLAG(PERFETTO_OS_NACL)
}
#if TRACK_COMMITTED_SIZE()
diff --git a/src/base/paged_memory_unittest.cc b/src/base/paged_memory_unittest.cc
index 97f1a74..06695d6 100644
--- a/src/base/paged_memory_unittest.cc
+++ b/src/base/paged_memory_unittest.cc
@@ -83,7 +83,7 @@
// Next page shouldn't be mapped.
ASSERT_FALSE(vm_test_utils::IsMapped(ptr_raw + kMappedSize, 4096));
- EXPECT_DEATH({ ptr_raw[kMappedSize] = 'x'; }, ".*");
+ EXPECT_DEATH_IF_SUPPORTED({ ptr_raw[kMappedSize] = 'x'; }, ".*");
// Commit the remaining pages.
mem.EnsureCommitted(kSize);
@@ -119,7 +119,7 @@
#if defined(ADDRESS_SANITIZER)
TEST(PagedMemoryTest, AccessUncommittedMemoryTriggersASAN) {
- EXPECT_DEATH(
+ EXPECT_DEATH_IF_SUPPORTED(
{
constexpr size_t kNumPages = 4096;
constexpr size_t kSize = 4096 * kNumPages;
@@ -141,8 +141,8 @@
PagedMemory mem = PagedMemory::Allocate(kSize);
ASSERT_TRUE(mem.IsValid());
volatile char* raw = reinterpret_cast<char*>(mem.Get());
- EXPECT_DEATH({ raw[-1] = 'x'; }, ".*");
- EXPECT_DEATH({ raw[kSize] = 'x'; }, ".*");
+ EXPECT_DEATH_IF_SUPPORTED({ raw[-1] = 'x'; }, ".*");
+ EXPECT_DEATH_IF_SUPPORTED({ raw[kSize] = 'x'; }, ".*");
}
// Disable this on:
diff --git a/src/base/scoped_file_unittest.cc b/src/base/scoped_file_unittest.cc
index 13f1acb..dff4413 100644
--- a/src/base/scoped_file_unittest.cc
+++ b/src/base/scoped_file_unittest.cc
@@ -170,7 +170,7 @@
#ifdef TEST_INVALID_CLOSE
TEST(ScopedFileTest, CloseFailureIsFatal) {
int raw_fd = open(kNullFilename, O_RDONLY);
- ASSERT_DEATH(
+ ASSERT_DEATH_IF_SUPPORTED(
{
ScopedFile scoped_file(raw_fd);
ASSERT_EQ(0, close(raw_fd));
diff --git a/src/base/task_runner_unittest.cc b/src/base/task_runner_unittest.cc
index a8368b5..10f047b 100644
--- a/src/base/task_runner_unittest.cc
+++ b/src/base/task_runner_unittest.cc
@@ -30,16 +30,11 @@
namespace base {
namespace {
-template <typename T>
class TaskRunnerTest : public ::testing::Test {
public:
- T task_runner;
+ UnixTaskRunner task_runner;
};
-using TaskRunnerTypes = ::testing::Types<UnixTaskRunner>;
-
-TYPED_TEST_SUITE(TaskRunnerTest, TaskRunnerTypes);
-
struct TestPipe : Pipe {
TestPipe() : Pipe(Pipe::Create()) {
// Make the pipe initially readable.
@@ -59,7 +54,7 @@
}
};
-TYPED_TEST(TaskRunnerTest, PostImmediateTask) {
+TEST_F(TaskRunnerTest, PostImmediateTask) {
auto& task_runner = this->task_runner;
int counter = 0;
task_runner.PostTask([&counter] { counter = (counter << 4) | 1; });
@@ -71,7 +66,7 @@
EXPECT_EQ(0x1234, counter);
}
-TYPED_TEST(TaskRunnerTest, PostDelayedTask) {
+TEST_F(TaskRunnerTest, PostDelayedTask) {
auto& task_runner = this->task_runner;
int counter = 0;
task_runner.PostDelayedTask([&counter] { counter = (counter << 4) | 1; }, 5);
@@ -83,7 +78,7 @@
EXPECT_EQ(0x1234, counter);
}
-TYPED_TEST(TaskRunnerTest, PostImmediateTaskFromTask) {
+TEST_F(TaskRunnerTest, PostImmediateTaskFromTask) {
auto& task_runner = this->task_runner;
task_runner.PostTask([&task_runner] {
task_runner.PostTask([&task_runner] { task_runner.Quit(); });
@@ -91,7 +86,7 @@
task_runner.Run();
}
-TYPED_TEST(TaskRunnerTest, PostDelayedTaskFromTask) {
+TEST_F(TaskRunnerTest, PostDelayedTaskFromTask) {
auto& task_runner = this->task_runner;
task_runner.PostTask([&task_runner] {
task_runner.PostDelayedTask([&task_runner] { task_runner.Quit(); }, 10);
@@ -99,7 +94,7 @@
task_runner.Run();
}
-TYPED_TEST(TaskRunnerTest, PostImmediateTaskFromOtherThread) {
+TEST_F(TaskRunnerTest, PostImmediateTaskFromOtherThread) {
auto& task_runner = this->task_runner;
ThreadChecker thread_checker;
int counter = 0;
@@ -118,7 +113,7 @@
EXPECT_EQ(0x1234, counter);
}
-TYPED_TEST(TaskRunnerTest, PostDelayedTaskFromOtherThread) {
+TEST_F(TaskRunnerTest, PostDelayedTaskFromOtherThread) {
auto& task_runner = this->task_runner;
std::thread thread([&task_runner] {
task_runner.PostDelayedTask([&task_runner] { task_runner.Quit(); }, 10);
@@ -127,7 +122,7 @@
thread.join();
}
-TYPED_TEST(TaskRunnerTest, AddFileDescriptorWatch) {
+TEST_F(TaskRunnerTest, AddFileDescriptorWatch) {
auto& task_runner = this->task_runner;
TestPipe pipe;
task_runner.AddFileDescriptorWatch(pipe.rd.get(),
@@ -135,7 +130,7 @@
task_runner.Run();
}
-TYPED_TEST(TaskRunnerTest, RemoveFileDescriptorWatch) {
+TEST_F(TaskRunnerTest, RemoveFileDescriptorWatch) {
auto& task_runner = this->task_runner;
TestPipe pipe;
@@ -149,7 +144,7 @@
EXPECT_FALSE(watch_ran);
}
-TYPED_TEST(TaskRunnerTest, RemoveFileDescriptorWatchFromTask) {
+TEST_F(TaskRunnerTest, RemoveFileDescriptorWatchFromTask) {
auto& task_runner = this->task_runner;
TestPipe pipe;
@@ -165,7 +160,7 @@
EXPECT_FALSE(watch_ran);
}
-TYPED_TEST(TaskRunnerTest, AddFileDescriptorWatchFromAnotherWatch) {
+TEST_F(TaskRunnerTest, AddFileDescriptorWatchFromAnotherWatch) {
auto& task_runner = this->task_runner;
TestPipe pipe;
TestPipe pipe2;
@@ -179,7 +174,7 @@
task_runner.Run();
}
-TYPED_TEST(TaskRunnerTest, RemoveFileDescriptorWatchFromAnotherWatch) {
+TEST_F(TaskRunnerTest, RemoveFileDescriptorWatchFromAnotherWatch) {
auto& task_runner = this->task_runner;
TestPipe pipe;
TestPipe pipe2;
@@ -198,7 +193,7 @@
EXPECT_FALSE(watch_ran);
}
-TYPED_TEST(TaskRunnerTest, ReplaceFileDescriptorWatchFromAnotherWatch) {
+TEST_F(TaskRunnerTest, ReplaceFileDescriptorWatchFromAnotherWatch) {
auto& task_runner = this->task_runner;
TestPipe pipe;
TestPipe pipe2;
@@ -216,7 +211,7 @@
EXPECT_FALSE(watch_ran);
}
-TYPED_TEST(TaskRunnerTest, AddFileDescriptorWatchFromAnotherThread) {
+TEST_F(TaskRunnerTest, AddFileDescriptorWatchFromAnotherThread) {
auto& task_runner = this->task_runner;
TestPipe pipe;
@@ -228,7 +223,7 @@
thread.join();
}
-TYPED_TEST(TaskRunnerTest, FileDescriptorWatchWithMultipleEvents) {
+TEST_F(TaskRunnerTest, FileDescriptorWatchWithMultipleEvents) {
auto& task_runner = this->task_runner;
TestPipe pipe;
@@ -246,7 +241,7 @@
task_runner.Run();
}
-TYPED_TEST(TaskRunnerTest, FileDescriptorClosedEvent) {
+TEST_F(TaskRunnerTest, FileDescriptorClosedEvent) {
auto& task_runner = this->task_runner;
TestPipe pipe;
pipe.wr.reset();
@@ -255,7 +250,7 @@
task_runner.Run();
}
-TYPED_TEST(TaskRunnerTest, PostManyDelayedTasks) {
+TEST_F(TaskRunnerTest, PostManyDelayedTasks) {
// Check that PostTask doesn't start failing if there are too many scheduled
// wake-ups.
auto& task_runner = this->task_runner;
@@ -265,7 +260,7 @@
task_runner.Run();
}
-TYPED_TEST(TaskRunnerTest, RunAgain) {
+TEST_F(TaskRunnerTest, RunAgain) {
auto& task_runner = this->task_runner;
int counter = 0;
task_runner.PostTask([&task_runner, &counter] {
@@ -281,31 +276,28 @@
EXPECT_EQ(2, counter);
}
-template <typename TaskRunner>
-void RepeatingTask(TaskRunner* task_runner) {
- task_runner->PostTask(std::bind(&RepeatingTask<TaskRunner>, task_runner));
+void RepeatingTask(UnixTaskRunner* task_runner) {
+ task_runner->PostTask(std::bind(&RepeatingTask, task_runner));
}
-TYPED_TEST(TaskRunnerTest, FileDescriptorWatchesNotStarved) {
+TEST_F(TaskRunnerTest, FileDescriptorWatchesNotStarved) {
auto& task_runner = this->task_runner;
TestPipe pipe;
- task_runner.PostTask(std::bind(&RepeatingTask<TypeParam>, &task_runner));
+ task_runner.PostTask(std::bind(&RepeatingTask, &task_runner));
task_runner.AddFileDescriptorWatch(pipe.rd.get(),
[&task_runner] { task_runner.Quit(); });
task_runner.Run();
}
-template <typename TaskRunner>
-void CountdownTask(TaskRunner* task_runner, int* counter) {
+void CountdownTask(UnixTaskRunner* task_runner, int* counter) {
if (!--(*counter)) {
task_runner->Quit();
return;
}
- task_runner->PostTask(
- std::bind(&CountdownTask<TaskRunner>, task_runner, counter));
+ task_runner->PostTask(std::bind(&CountdownTask, task_runner, counter));
}
-TYPED_TEST(TaskRunnerTest, NoDuplicateFileDescriptorWatchCallbacks) {
+TEST_F(TaskRunnerTest, NoDuplicateFileDescriptorWatchCallbacks) {
auto& task_runner = this->task_runner;
TestPipe pipe;
bool watch_called = 0;
@@ -315,12 +307,11 @@
pipe.Read();
watch_called = true;
});
- task_runner.PostTask(
- std::bind(&CountdownTask<TypeParam>, &task_runner, &counter));
+ task_runner.PostTask(std::bind(&CountdownTask, &task_runner, &counter));
task_runner.Run();
}
-TYPED_TEST(TaskRunnerTest, ReplaceFileDescriptorWatchFromOtherThread) {
+TEST_F(TaskRunnerTest, ReplaceFileDescriptorWatchFromOtherThread) {
auto& task_runner = this->task_runner;
TestPipe pipe;
@@ -339,7 +330,7 @@
thread.join();
}
-TYPED_TEST(TaskRunnerTest, IsIdleForTesting) {
+TEST_F(TaskRunnerTest, IsIdleForTesting) {
auto& task_runner = this->task_runner;
task_runner.PostTask(
[&task_runner] { EXPECT_FALSE(task_runner.IsIdleForTesting()); });
@@ -350,7 +341,7 @@
task_runner.Run();
}
-TYPED_TEST(TaskRunnerTest, RunsTasksOnCurrentThread) {
+TEST_F(TaskRunnerTest, RunsTasksOnCurrentThread) {
auto& main_tr = this->task_runner;
EXPECT_TRUE(main_tr.RunsTasksOnCurrentThread());
diff --git a/src/base/test/benchmark_main.cc b/src/base/test/benchmark_main.cc
index e410e52..3a3feaa 100644
--- a/src/base/test/benchmark_main.cc
+++ b/src/base/test/benchmark_main.cc
@@ -14,4 +14,4 @@
#include <benchmark/benchmark.h>
-BENCHMARK_MAIN();
+BENCHMARK_MAIN()
diff --git a/src/base/test/utils.h b/src/base/test/utils.h
index c2125e7..9f61eac 100644
--- a/src/base/test/utils.h
+++ b/src/base/test/utils.h
@@ -23,15 +23,27 @@
#if PERFETTO_DCHECK_IS_ON()
-#define EXPECT_DCHECK_DEATH(statement) EXPECT_DEATH(statement, "PERFETTO_CHECK")
-#define ASSERT_DCHECK_DEATH(statement) ASSERT_DEATH(statement, "PERFETTO_CHECK")
+#define EXPECT_DCHECK_DEATH(statement) \
+ EXPECT_DEATH_IF_SUPPORTED(statement, "PERFETTO_CHECK")
+#define ASSERT_DCHECK_DEATH(statement) \
+ ASSERT_DEATH_IF_SUPPORTED(statement, "PERFETTO_CHECK")
#else // PERFETTO_DCHECK_IS_ON()
+// Since PERFETTO_DCHECK_IS_ON() is false these statements should not die (if
+// they should/do we should use EXPECT/ASSERT DEATH_TEST_IF_SUPPORTED directly).
+// Therefore if the platform supports DEATH_TESTS we can use the handy
+// GTEST_EXECUTE_STATEMENT_ which prevents optimizing the code away, and if not
+// we just fall back on executing the code directly.
+#if defined(GTEST_EXECUTE_STATEMENT_)
#define EXPECT_DCHECK_DEATH(statement) \
GTEST_EXECUTE_STATEMENT_(statement, "PERFETTO_CHECK")
#define ASSERT_DCHECK_DEATH(statement) \
GTEST_EXECUTE_STATEMENT_(statement, "PERFETTO_CHECK")
+#else
+#define EXPECT_DCHECK_DEATH(statement) [&]() { statement }()
+#define ASSERT_DCHECK_DEATH(statement) [&]() { statement }()
+#endif // defined(GTEST_EXECUTE_STATEMENT_)
#endif // PERFETTO_DCHECK_IS_ON()
diff --git a/src/base/thread_task_runner.cc b/src/base/thread_task_runner.cc
index 0576ee9..d1a3b93 100644
--- a/src/base/thread_task_runner.cc
+++ b/src/base/thread_task_runner.cc
@@ -27,6 +27,11 @@
#include "perfetto/base/logging.h"
#include "perfetto/ext/base/unix_task_runner.h"
+#if PERFETTO_BUILDFLAG(PERFETTO_OS_LINUX) || \
+ PERFETTO_BUILDFLAG(PERFETTO_OS_ANDROID)
+#include <sys/prctl.h>
+#endif
+
namespace perfetto {
namespace base {
@@ -52,7 +57,7 @@
thread_.join();
}
-ThreadTaskRunner::ThreadTaskRunner() {
+ThreadTaskRunner::ThreadTaskRunner(const std::string& name) : name_(name) {
std::mutex init_lock;
std::condition_variable init_cv;
@@ -66,6 +71,7 @@
// notifying).
init_cv.notify_one();
};
+
thread_ = std::thread(&ThreadTaskRunner::RunTaskThread, this,
std::move(initializer));
@@ -75,11 +81,44 @@
void ThreadTaskRunner::RunTaskThread(
std::function<void(UnixTaskRunner*)> initializer) {
+ if (!name_.empty()) {
+#if PERFETTO_BUILDFLAG(PERFETTO_OS_MACOSX)
+ pthread_setname_np(name_.c_str());
+#elif PERFETTO_BUILDFLAG(PERFETTO_OS_LINUX) || \
+ PERFETTO_BUILDFLAG(PERFETTO_OS_ANDROID)
+ prctl(PR_SET_NAME, name_.c_str());
+#endif
+ }
+
UnixTaskRunner task_runner;
task_runner.PostTask(std::bind(std::move(initializer), &task_runner));
task_runner.Run();
}
+void ThreadTaskRunner::PostTaskAndWaitForTesting(std::function<void()> fn) {
+ std::mutex mutex;
+ std::condition_variable cv;
+
+ std::unique_lock<std::mutex> lock(mutex);
+ bool done = false;
+ task_runner_->PostTask([&mutex, &cv, &done, &fn] {
+ fn();
+
+ std::lock_guard<std::mutex> inner_lock(mutex);
+ done = true;
+ cv.notify_one();
+ });
+ cv.wait(lock, [&done] { return done; });
+}
+
+uint64_t ThreadTaskRunner::GetThreadCPUTimeNsForTesting() {
+ uint64_t thread_time_ns = 0;
+ PostTaskAndWaitForTesting([&thread_time_ns] {
+ thread_time_ns = static_cast<uint64_t>(base::GetThreadCPUTimeNs().count());
+ });
+ return thread_time_ns;
+}
+
} // namespace base
} // namespace perfetto
diff --git a/src/base/unix_socket.cc b/src/base/unix_socket.cc
index e63f978..f6db62a 100644
--- a/src/base/unix_socket.cc
+++ b/src/base/unix_socket.cc
@@ -172,6 +172,15 @@
}
// static
+UnixSocketRaw UnixSocketRaw::CreateMayFail(SockFamily family, SockType type) {
+ auto fd = ScopedFile(socket(GetSockFamily(family), GetSockType(type), 0));
+ if (!fd) {
+ return UnixSocketRaw();
+ }
+ return UnixSocketRaw(std::move(fd), family, type);
+}
+
+// static
std::pair<UnixSocketRaw, UnixSocketRaw> UnixSocketRaw::CreatePair(
SockFamily family,
SockType type) {
diff --git a/src/base/watchdog_posix.cc b/src/base/watchdog_posix.cc
index 401ecdb..25782d9 100644
--- a/src/base/watchdog_posix.cc
+++ b/src/base/watchdog_posix.cc
@@ -28,8 +28,8 @@
#include "perfetto/base/build_config.h"
#include "perfetto/base/logging.h"
+#include "perfetto/base/thread_utils.h"
#include "perfetto/ext/base/scoped_file.h"
-#include "perfetto/ext/base/thread_utils.h"
namespace perfetto {
namespace base {
@@ -47,7 +47,8 @@
for (size_t i = 0; i < size; i++) {
total += array[i];
}
- return total / size;
+ return static_cast<double>(total / size);
+
}
} // namespace
@@ -164,7 +165,7 @@
// Add the current stat value to the ring buffer and check that the mean
// remains under our threshold.
if (memory_window_bytes_.Push(rss_bytes)) {
- if (memory_window_bytes_.Mean() > memory_limit_bytes_) {
+ if (memory_window_bytes_.Mean() > static_cast<double>(memory_limit_bytes_)) {
PERFETTO_ELOG(
"Memory watchdog trigger. Memory window of %f bytes is above the "
"%" PRIu64 " bytes limit.",
@@ -187,7 +188,7 @@
double window_interval_ticks =
(static_cast<double>(WindowTimeForRingBuffer(cpu_window_time_ticks_)) /
1000.0) *
- sysconf(_SC_CLK_TCK);
+ static_cast<double>(sysconf(_SC_CLK_TCK));
double percentage = static_cast<double>(difference_ticks) /
static_cast<double>(window_interval_ticks) * 100;
if (percentage > cpu_limit_percentage_) {
diff --git a/src/base/watchdog_unittest.cc b/src/base/watchdog_unittest.cc
index f3bc850..81d0ac6 100644
--- a/src/base/watchdog_unittest.cc
+++ b/src/base/watchdog_unittest.cc
@@ -17,9 +17,9 @@
#include "perfetto/ext/base/watchdog.h"
#include "perfetto/base/logging.h"
+#include "perfetto/base/thread_utils.h"
#include "perfetto/ext/base/paged_memory.h"
#include "perfetto/ext/base/scoped_file.h"
-#include "perfetto/ext/base/thread_utils.h"
#include "test/gtest_and_gmock.h"
#include <signal.h>
@@ -116,7 +116,7 @@
return sigaction(SIGABRT, act, nullptr);
}
-PlatformThreadID g_aborted_thread = 0;
+PlatformThreadId g_aborted_thread = 0;
void SIGABRTHandler(int) {
g_aborted_thread = GetThreadId();
}
@@ -138,7 +138,7 @@
std::condition_variable cv;
bool quit = false;
g_aborted_thread = 0;
- PlatformThreadID expected_tid = 0;
+ PlatformThreadId expected_tid = 0;
auto thread_fn = [&mutex, &cv, &quit, &expected_tid](size_t thread_num) {
if (thread_num == kKillThreadNum) {
diff --git a/src/ipc/BUILD.gn b/src/ipc/BUILD.gn
index 3e48bb0..d8ee2b4 100644
--- a/src/ipc/BUILD.gn
+++ b/src/ipc/BUILD.gn
@@ -21,45 +21,74 @@
# projects should be depending on our IPC layer.
assert(enable_perfetto_ipc)
-source_set("ipc") {
- public_configs = [ "../../gn:default_config" ]
+source_set("client") {
public_deps = [
"../../include/perfetto/ext/ipc",
"../base:unix_socket",
]
deps = [
+ ":common",
"../../gn:default_deps",
"../../protos/perfetto/ipc:wire_protocol_cpp",
"../base",
]
sources = [
- "buffered_frame_deserializer.cc",
- "buffered_frame_deserializer.h",
"client_impl.cc",
"client_impl.h",
- "deferred.cc",
+ "service_proxy.cc",
+ ]
+}
+
+source_set("host") {
+ public_deps = [
+ "../../include/perfetto/ext/ipc",
+ "../base:unix_socket",
+ ]
+ deps = [
+ ":common",
+ "../../gn:default_deps",
+ "../../protos/perfetto/ipc:wire_protocol_cpp",
+ "../base",
+ ]
+ sources = [
"host_impl.cc",
"host_impl.h",
- "service_proxy.cc",
+ ]
+}
+
+source_set("common") {
+ public_deps = [
+ "../../include/perfetto/ext/ipc",
+ "../../protos/perfetto/ipc:wire_protocol_cpp",
+ ]
+ deps = [
+ "../../gn:default_deps",
+ "../base",
+ ]
+ sources = [
+ "buffered_frame_deserializer.cc",
+ "buffered_frame_deserializer.h",
+ "deferred.cc",
"virtual_destructors.cc",
]
}
perfetto_fuzzer_test("buffered_frame_deserializer_fuzzer") {
- sources = [
- "buffered_frame_deserializer_fuzzer.cc",
- ]
+ sources = [ "buffered_frame_deserializer_fuzzer.cc" ]
deps = [
- ":ipc",
+ ":common",
"../../gn:default_deps",
"../../protos/perfetto/ipc:wire_protocol_cpp",
+ "../base",
]
}
perfetto_unittest_source_set("unittests") {
testonly = true
deps = [
- ":ipc",
+ ":client",
+ ":common",
+ ":host",
":test_messages_cpp",
":test_messages_ipc",
"../../gn:default_deps",
@@ -94,7 +123,8 @@
static_library("perfetto_ipc") {
complete_static_lib = true
deps = [
- ":ipc",
+ ":client",
+ ":host",
"../../gn:default_deps",
]
}
diff --git a/src/ipc/client_impl.cc b/src/ipc/client_impl.cc
index e2dbc35..f38ef6d 100644
--- a/src/ipc/client_impl.cc
+++ b/src/ipc/client_impl.cc
@@ -27,6 +27,8 @@
#include "perfetto/ext/ipc/service_descriptor.h"
#include "perfetto/ext/ipc/service_proxy.h"
+#include "protos/perfetto/ipc/wire_protocol.gen.h"
+
// TODO(primiano): Add ThreadChecker everywhere.
// TODO(primiano): Add timeouts.
diff --git a/src/ipc/client_impl.h b/src/ipc/client_impl.h
index 35dea50..ff9c7bc 100644
--- a/src/ipc/client_impl.h
+++ b/src/ipc/client_impl.h
@@ -17,20 +17,25 @@
#ifndef SRC_IPC_CLIENT_IMPL_H_
#define SRC_IPC_CLIENT_IMPL_H_
+#include <list>
+#include <map>
+#include <memory>
+
#include "perfetto/base/task_runner.h"
#include "perfetto/ext/base/scoped_file.h"
#include "perfetto/ext/base/unix_socket.h"
#include "perfetto/ext/ipc/client.h"
#include "src/ipc/buffered_frame_deserializer.h"
-#include "protos/perfetto/ipc/wire_protocol.gen.h"
-
-#include <list>
-#include <map>
-#include <memory>
-
namespace perfetto {
+namespace protos {
+namespace gen {
+class IPCFrame_BindServiceReply;
+class IPCFrame_InvokeMethodReply;
+} // namespace gen
+} // namespace protos
+
namespace base {
class TaskRunner;
} // namespace base
@@ -78,8 +83,10 @@
bool SendFrame(const Frame&, int fd = -1);
void OnFrameReceived(const Frame&);
- void OnBindServiceReply(QueuedRequest, const Frame::BindServiceReply&);
- void OnInvokeMethodReply(QueuedRequest, const Frame::InvokeMethodReply&);
+ void OnBindServiceReply(QueuedRequest,
+ const protos::gen::IPCFrame_BindServiceReply&);
+ void OnInvokeMethodReply(QueuedRequest,
+ const protos::gen::IPCFrame_InvokeMethodReply&);
bool invoking_method_reply_ = false;
std::unique_ptr<base::UnixSocket> sock_;
diff --git a/src/ipc/client_impl_unittest.cc b/src/ipc/client_impl_unittest.cc
index 42a5dd2..08ea09c 100644
--- a/src/ipc/client_impl_unittest.cc
+++ b/src/ipc/client_impl_unittest.cc
@@ -32,6 +32,7 @@
#include "src/ipc/test/test_socket.h"
#include "test/gtest_and_gmock.h"
+#include "protos/perfetto/ipc/wire_protocol.gen.h"
#include "src/ipc/test/client_unittest_messages.gen.h"
namespace perfetto {
diff --git a/src/ipc/protoc_plugin/BUILD.gn b/src/ipc/protoc_plugin/BUILD.gn
index 535f53a..57dcb51 100644
--- a/src/ipc/protoc_plugin/BUILD.gn
+++ b/src/ipc/protoc_plugin/BUILD.gn
@@ -15,9 +15,7 @@
import("../../../gn/perfetto_host_executable.gni")
perfetto_host_executable("ipc_plugin") {
- sources = [
- "ipc_plugin.cc",
- ]
+ sources = [ "ipc_plugin.cc" ]
deps = [
"../../../gn:default_deps",
"../../../gn:protoc_lib",
diff --git a/src/ipc/service_proxy.cc b/src/ipc/service_proxy.cc
index e416f5f..7246a04 100644
--- a/src/ipc/service_proxy.cc
+++ b/src/ipc/service_proxy.cc
@@ -23,6 +23,8 @@
#include "perfetto/ext/ipc/service_descriptor.h"
#include "src/ipc/client_impl.h"
+#include "protos/perfetto/ipc/wire_protocol.gen.h"
+
namespace perfetto {
namespace ipc {
diff --git a/src/ipc/test/client_unittest_messages.proto b/src/ipc/test/client_unittest_messages.proto
index e19fa08..20c4623 100644
--- a/src/ipc/test/client_unittest_messages.proto
+++ b/src/ipc/test/client_unittest_messages.proto
@@ -15,7 +15,6 @@
*/
syntax = "proto2";
-option optimize_for = LITE_RUNTIME;
package perfetto.ipc;
diff --git a/src/ipc/test/deferred_unittest_messages.proto b/src/ipc/test/deferred_unittest_messages.proto
index 8fee32e..c09cc43 100644
--- a/src/ipc/test/deferred_unittest_messages.proto
+++ b/src/ipc/test/deferred_unittest_messages.proto
@@ -15,7 +15,6 @@
*/
syntax = "proto2";
-option optimize_for = LITE_RUNTIME;
package perfetto.ipc;
diff --git a/src/ipc/test/greeter_service.proto b/src/ipc/test/greeter_service.proto
index 8524ba7..724db63 100644
--- a/src/ipc/test/greeter_service.proto
+++ b/src/ipc/test/greeter_service.proto
@@ -15,7 +15,6 @@
*/
syntax = "proto2";
-option optimize_for = LITE_RUNTIME;
// Deliberately a namespace != of perfetto.* to spot namespace dependencies
// bugs in the autogenerated headers.
diff --git a/src/perfetto_cmd/BUILD.gn b/src/perfetto_cmd/BUILD.gn
index 969b732..4b06501 100644
--- a/src/perfetto_cmd/BUILD.gn
+++ b/src/perfetto_cmd/BUILD.gn
@@ -23,9 +23,7 @@
":perfetto_cmd",
"../../gn:default_deps",
]
- sources = [
- "main.cc",
- ]
+ sources = [ "main.cc" ]
}
# Tool to finalize long running traces.
@@ -39,15 +37,11 @@
":trigger_perfetto_cmd",
"../../gn:default_deps",
]
- sources = [
- "trigger_perfetto_main.cc",
- ]
+ sources = [ "trigger_perfetto_main.cc" ]
}
source_set("perfetto_atoms") {
- sources = [
- "perfetto_atoms.h",
- ]
+ sources = [ "perfetto_atoms.h" ]
}
# Contains all the implementation but not the main() entry point. This target
@@ -61,15 +55,17 @@
":perfetto_atoms",
":trigger_producer",
"../../gn:default_deps",
- "../../gn:zlib",
"../../protos/perfetto/common:cpp",
"../../protos/perfetto/config:cpp",
"../../protos/perfetto/config/ftrace:cpp",
"../android_internal:lazy_library_loader",
"../base",
"../protozero",
- "../tracing:ipc",
+ "../tracing/ipc/consumer",
]
+ if (enable_perfetto_zlib) {
+ deps += [ "../../gn:zlib" ]
+ }
sources = [
"config.cc",
"config.h",
@@ -97,11 +93,9 @@
":trigger_producer",
"../../gn:default_deps",
"../base",
- "../tracing:ipc",
+ "../tracing/ipc/producer",
]
- sources = [
- "trigger_perfetto.cc",
- ]
+ sources = [ "trigger_perfetto.cc" ]
}
source_set("trigger_producer") {
@@ -112,15 +106,13 @@
deps = [
"../../gn:default_deps",
"../base",
- "../tracing:ipc",
+ "../tracing/ipc/producer",
]
}
perfetto_proto_library("protos") {
proto_generators = [ "cpp" ]
- sources = [
- "perfetto_cmd_state.proto",
- ]
+ sources = [ "perfetto_cmd_state.proto" ]
proto_path = perfetto_root_path
}
@@ -131,14 +123,16 @@
":perfetto_cmd",
"../../gn:default_deps",
"../../gn:gtest_and_gmock",
- "../../gn:zlib",
"../../include/perfetto/base",
"../../include/perfetto/ext/base",
"../../protos/perfetto/config:cpp",
"../../protos/perfetto/config/ftrace:cpp",
"../../protos/perfetto/trace:cpp",
- "../tracing",
+ "../tracing/core",
]
+ if (enable_perfetto_zlib) {
+ deps += [ "../../gn:zlib" ]
+ }
sources = [
"config_unittest.cc",
"packet_writer_unittest.cc",
diff --git a/src/perfetto_cmd/packet_writer.cc b/src/perfetto_cmd/packet_writer.cc
index 9d5a8d6..45aad47 100644
--- a/src/perfetto_cmd/packet_writer.cc
+++ b/src/perfetto_cmd/packet_writer.cc
@@ -24,13 +24,17 @@
#include <stdio.h>
#include <sys/stat.h>
#include <unistd.h>
-#include <zlib.h>
+#include "perfetto/base/build_config.h"
#include "perfetto/ext/base/paged_memory.h"
#include "perfetto/ext/base/utils.h"
#include "perfetto/ext/tracing/core/trace_packet.h"
#include "perfetto/protozero/proto_utils.h"
+#if PERFETTO_BUILDFLAG(PERFETTO_ZLIB)
+#include <zlib.h>
+#endif
+
namespace perfetto {
namespace {
@@ -43,14 +47,20 @@
// ID of the |packet| field in trace.proto. Hardcoded as this we don't
// want to depend on protos/trace:lite for binary size saving reasons.
constexpr uint32_t kPacketId = 1;
+
+#if PERFETTO_BUILDFLAG(PERFETTO_ZLIB)
+
// ID of |compressed_packets| in trace_packet.proto.
constexpr uint32_t kCompressedPacketsId = 50;
// Maximum allowable size for a single packet.
const size_t kMaxPacketSize = 500 * 1024;
+
// After every kPendingBytesLimit we do a Z_SYNC_FLUSH in the zlib stream.
const size_t kPendingBytesLimit = 32 * 1024;
+#endif // PERFETTO_BUILDFLAG(PERFETTO_ZLIB)
+
template <uint32_t id>
size_t GetPreamble(size_t sz, Preamble* preamble) {
uint8_t* ptr = reinterpret_cast<uint8_t*>(preamble->data());
@@ -73,6 +83,31 @@
FILE* fd_;
};
+FilePacketWriter::FilePacketWriter(FILE* fd) : fd_(fd) {}
+
+FilePacketWriter::~FilePacketWriter() {
+ fflush(fd_);
+}
+
+bool FilePacketWriter::WritePackets(const std::vector<TracePacket>& packets) {
+ for (const TracePacket& packet : packets) {
+ Preamble preamble;
+ size_t size = GetPreamble<kPacketId>(packet.size(), &preamble);
+ if (fwrite(preamble.data(), 1, size, fd_) != size)
+ return false;
+ for (const Slice& slice : packet.slices()) {
+ if (fwrite(reinterpret_cast<const char*>(slice.start), 1, slice.size,
+ fd_) != slice.size) {
+ return false;
+ }
+ }
+ }
+
+ return true;
+}
+
+#if PERFETTO_BUILDFLAG(PERFETTO_ZLIB)
+
class ZipPacketWriter : public PacketWriter {
public:
ZipPacketWriter(std::unique_ptr<PacketWriter>);
@@ -102,29 +137,6 @@
size_t pending_bytes_ = 0;
};
-FilePacketWriter::FilePacketWriter(FILE* fd) : fd_(fd) {}
-
-FilePacketWriter::~FilePacketWriter() {
- fflush(fd_);
-}
-
-bool FilePacketWriter::WritePackets(const std::vector<TracePacket>& packets) {
- for (const TracePacket& packet : packets) {
- Preamble preamble;
- size_t size = GetPreamble<kPacketId>(packet.size(), &preamble);
- if (fwrite(preamble.data(), 1, size, fd_) != size)
- return false;
- for (const Slice& slice : packet.slices()) {
- if (fwrite(reinterpret_cast<const char*>(slice.start), 1, slice.size,
- fd_) != slice.size) {
- return false;
- }
- }
- }
-
- return true;
-}
-
ZipPacketWriter::ZipPacketWriter(std::unique_ptr<PacketWriter> writer)
: writer_(std::move(writer)),
buf_(base::PagedMemory::Allocate(kMaxPacketSize)),
@@ -179,7 +191,7 @@
// Reinitialize the compresser if needed:
if (!is_compressing_) {
memset(&stream_, 0, sizeof(stream_));
- CheckEq(deflateInit(&stream_, 9), Z_OK);
+ CheckEq(deflateInit(&stream_, 6), Z_OK);
is_compressing_ = true;
stream_.next_out = start_;
stream_.avail_out = static_cast<unsigned int>(end_ - start_);
@@ -237,6 +249,8 @@
pending_bytes_ += size;
}
+#endif // PERFETTO_BUILDFLAG(PERFETTO_ZLIB)
+
} // namespace
PacketWriter::PacketWriter() {}
@@ -247,9 +261,11 @@
return std::unique_ptr<PacketWriter>(new FilePacketWriter(fd));
}
+#if PERFETTO_BUILDFLAG(PERFETTO_ZLIB)
std::unique_ptr<PacketWriter> CreateZipPacketWriter(
std::unique_ptr<PacketWriter> writer) {
return std::unique_ptr<PacketWriter>(new ZipPacketWriter(std::move(writer)));
}
+#endif
} // namespace perfetto
diff --git a/src/perfetto_cmd/packet_writer_unittest.cc b/src/perfetto_cmd/packet_writer_unittest.cc
index c1fab21..fbf9603 100644
--- a/src/perfetto_cmd/packet_writer_unittest.cc
+++ b/src/perfetto_cmd/packet_writer_unittest.cc
@@ -21,8 +21,7 @@
#include <random>
-#include <zlib.h>
-
+#include "perfetto/base/build_config.h"
#include "perfetto/ext/base/file_utils.h"
#include "perfetto/ext/base/scoped_file.h"
#include "perfetto/ext/base/temp_file.h"
@@ -34,6 +33,10 @@
#include "protos/perfetto/trace/trace.gen.h"
#include "protos/perfetto/trace/trace_packet.gen.h"
+#if PERFETTO_BUILDFLAG(PERFETTO_ZLIB)
+#include <zlib.h>
+#endif
+
namespace perfetto {
namespace {
@@ -51,6 +54,7 @@
return packet;
}
+#if PERFETTO_BUILDFLAG(PERFETTO_ZLIB)
std::string Decompress(const std::string& data) {
uint8_t out[1024];
@@ -76,6 +80,7 @@
inflateEnd(&stream);
return s;
}
+#endif // PERFETTO_BUILDFLAG(PERFETTO_ZLIB)
TEST(PacketWriterTest, FilePacketWriter) {
base::TempFile tmp = base::TempFile::Create();
@@ -105,6 +110,8 @@
EXPECT_EQ(trace.packet()[0].for_testing().str(), "abc");
}
+#if PERFETTO_BUILDFLAG(PERFETTO_ZLIB)
+
TEST(PacketWriterTest, ZipPacketWriter) {
base::TempFile tmp = base::TempFile::Create();
base::ScopedResource<FILE*, fclose, nullptr> f(
@@ -281,5 +288,7 @@
EXPECT_EQ(packet_count, 1000u);
}
+#endif // PERFETTO_BUILDFLAG(PERFETTO_ZLIB)
+
} // namespace
} // namespace perfetto
diff --git a/src/perfetto_cmd/perfetto_cmd.cc b/src/perfetto_cmd/perfetto_cmd.cc
index dff337c..bb48f6f 100644
--- a/src/perfetto_cmd/perfetto_cmd.cc
+++ b/src/perfetto_cmd/perfetto_cmd.cc
@@ -479,6 +479,10 @@
if (trace_config_->trace_uuid_lsb() == 0 &&
trace_config_->trace_uuid_msb() == 0) {
base::Uuid uuid = base::Uuidv4();
+ if (trace_config_->statsd_metadata().triggering_subscription_id()) {
+ uuid.set_lsb(
+ trace_config_->statsd_metadata().triggering_subscription_id());
+ }
uuid_ = uuid.ToString();
trace_config_->set_trace_uuid_msb(uuid.msb());
trace_config_->set_trace_uuid_lsb(uuid.lsb());
@@ -599,7 +603,11 @@
if (trace_config_->compression_type() ==
TraceConfig::COMPRESSION_TYPE_DEFLATE) {
if (packet_writer_) {
+#if PERFETTO_BUILDFLAG(PERFETTO_ZLIB)
packet_writer_ = CreateZipPacketWriter(std::move(packet_writer_));
+#else
+ PERFETTO_ELOG("Cannot compress. Zlib not enabled in the build config");
+#endif
} else {
PERFETTO_ELOG("Cannot compress when tracing directly to file.");
}
diff --git a/src/perfetto_cmd/perfetto_cmd_state.proto b/src/perfetto_cmd/perfetto_cmd_state.proto
index 1d0b14d..6337fb2 100644
--- a/src/perfetto_cmd/perfetto_cmd_state.proto
+++ b/src/perfetto_cmd/perfetto_cmd_state.proto
@@ -15,7 +15,6 @@
*/
syntax = "proto2";
-option optimize_for = LITE_RUNTIME;
package perfetto;
diff --git a/src/perfetto_cmd/perfetto_config.descriptor.h b/src/perfetto_cmd/perfetto_config.descriptor.h
index c630e83..f9e012e 100644
--- a/src/perfetto_cmd/perfetto_config.descriptor.h
+++ b/src/perfetto_cmd/perfetto_config.descriptor.h
@@ -25,7 +25,7 @@
// This file was autogenerated by tools/gen_binary_descriptors. Do not edit.
// SHA1(tools/gen_binary_descriptors)
-// f242f1ac484bbe7ba4c45e77b56ab588f8015196
+// d6628b15181dba5287e35b56b966b39ea93d42b1
// SHA1(protos/perfetto/config/perfetto_config.proto)
// 9bf7f741997f67724c7ee1b186b117708ac5228d
diff --git a/src/profiling/BUILD.gn b/src/profiling/BUILD.gn
index a11af0d..5a929b6 100644
--- a/src/profiling/BUILD.gn
+++ b/src/profiling/BUILD.gn
@@ -16,16 +16,12 @@
import("../../gn/test.gni")
source_set("deobfuscator") {
- sources = [
- "deobfuscator.cc",
- ]
+ sources = [ "deobfuscator.cc" ]
deps = [
"../../gn:default_deps",
"../../include/perfetto/ext/base:base",
]
- public_deps = [
- "../../include/perfetto/profiling:deobfuscator",
- ]
+ public_deps = [ "../../include/perfetto/profiling:deobfuscator" ]
}
perfetto_unittest_source_set("unittests") {
@@ -37,7 +33,5 @@
"../base",
"../base:test_support",
]
- sources = [
- "deobfuscator_unittest.cc",
- ]
+ sources = [ "deobfuscator_unittest.cc" ]
}
diff --git a/src/profiling/memory/BUILD.gn b/src/profiling/memory/BUILD.gn
index 1862fb4..6c4ef75 100644
--- a/src/profiling/memory/BUILD.gn
+++ b/src/profiling/memory/BUILD.gn
@@ -27,11 +27,9 @@
"../../../src/base:unix_socket",
"../../../src/profiling/memory:daemon",
"../../../src/profiling/memory:wire_protocol",
- "../../../src/tracing:ipc",
+ "../../../src/tracing/ipc/producer",
]
- sources = [
- "main.cc",
- ]
+ sources = [ "main.cc" ]
}
# This library gets loaded into (and executes in) arbitrary android processes.
@@ -48,9 +46,7 @@
shared_library("heapprofd_client") {
configs -= [ "//gn/standalone:android_liblog" ]
cflags = [ "-DPERFETTO_ANDROID_ASYNC_SAFE_LOG" ]
- deps = [
- ":malloc_hooks",
- ]
+ deps = [ ":malloc_hooks" ]
}
# This will export publicly visible symbols for the malloc_hooks.
@@ -68,16 +64,12 @@
"-isystem",
rebase_path("../../../buildtools/bionic/libc", root_build_dir),
]
- sources = [
- "malloc_hooks.cc",
- ]
+ sources = [ "malloc_hooks.cc" ]
}
} # if (perfetto_build_with_android)
source_set("wire_protocol") {
- public_deps = [
- "../../../gn:libunwindstack",
- ]
+ public_deps = [ "../../../gn:libunwindstack" ]
deps = [
":ring_buffer",
"../../../gn:default_deps",
@@ -133,9 +125,7 @@
"../../../gn:gtest_and_gmock",
"../../base",
]
- sources = [
- "shared_ring_buffer_unittest.cc",
- ]
+ sources = [ "shared_ring_buffer_unittest.cc" ]
}
source_set("daemon") {
@@ -148,8 +138,8 @@
"../../../protos/perfetto/config/profiling:cpp",
"../../base",
"../../base:unix_socket",
- "../../tracing",
- "../../tracing:ipc",
+ "../../tracing/core",
+ "../../tracing/ipc/producer",
]
public_deps = [
"../../../gn:libunwindstack",
@@ -190,9 +180,7 @@
"../../base",
"../../base:unix_socket",
]
- public_deps = [
- "../../../gn:libunwindstack",
- ]
+ public_deps = [ "../../../gn:libunwindstack" ]
sources = [
"client.cc",
"client.h",
@@ -213,7 +201,7 @@
"../../../include/perfetto/profiling:normalize",
"../../base",
"../../base:test_support",
- "../../tracing",
+ "../../tracing/core",
]
sources = [
"bookkeeping_unittest.cc",
@@ -244,9 +232,7 @@
"../../base",
"../../base:test_support",
]
- sources = [
- "heapprofd_end_to_end_test.cc",
- ]
+ sources = [ "heapprofd_end_to_end_test.cc" ]
if (start_daemons_for_testing) {
defines = [ "PERFETTO_START_DAEMONS_FOR_TESTING" ]
}
@@ -254,24 +240,20 @@
perfetto_fuzzer_test("unwinding_fuzzer") {
testonly = true
- sources = [
- "unwinding_fuzzer.cc",
- ]
+ sources = [ "unwinding_fuzzer.cc" ]
deps = [
":daemon",
":ring_buffer",
":wire_protocol",
"../../../gn:default_deps",
"../../base",
- "../../tracing",
+ "../../tracing/core",
]
}
perfetto_fuzzer_test("shared_ring_buffer_fuzzer") {
testonly = true
- sources = [
- "shared_ring_buffer_fuzzer.cc",
- ]
+ sources = [ "shared_ring_buffer_fuzzer.cc" ]
deps = [
":ring_buffer",
"../../../gn:default_deps",
@@ -281,9 +263,7 @@
perfetto_fuzzer_test("shared_ring_buffer_write_fuzzer") {
testonly = true
- sources = [
- "shared_ring_buffer_write_fuzzer.cc",
- ]
+ sources = [ "shared_ring_buffer_write_fuzzer.cc" ]
deps = [
":ring_buffer",
"../../../gn:default_deps",
diff --git a/src/profiling/memory/client.cc b/src/profiling/memory/client.cc
index 3b94ac6..ed65372 100644
--- a/src/profiling/memory/client.cc
+++ b/src/profiling/memory/client.cc
@@ -35,9 +35,9 @@
#include <new>
#include "perfetto/base/logging.h"
+#include "perfetto/base/thread_utils.h"
#include "perfetto/base/time.h"
#include "perfetto/ext/base/scoped_file.h"
-#include "perfetto/ext/base/thread_utils.h"
#include "perfetto/ext/base/unix_socket.h"
#include "perfetto/ext/base/utils.h"
#include "src/profiling/memory/sampler.h"
@@ -289,7 +289,8 @@
uint64_t alloc_size,
uint64_t alloc_address) {
if (PERFETTO_UNLIKELY(getpid() != pid_at_creation_)) {
- PERFETTO_LOG("Detected post-fork child situation, stopping profiling.");
+ PERFETTO_LOG(
+ "Detected post-fork child situation. Not profiling the child.");
return false;
}
diff --git a/src/profiling/memory/client_unittest.cc b/src/profiling/memory/client_unittest.cc
index e2f0500..68b2ee7 100644
--- a/src/profiling/memory/client_unittest.cc
+++ b/src/profiling/memory/client_unittest.cc
@@ -18,7 +18,7 @@
#include <thread>
-#include "perfetto/ext/base/thread_utils.h"
+#include "perfetto/base/thread_utils.h"
#include "perfetto/ext/base/unix_socket.h"
#include "test/gtest_and_gmock.h"
diff --git a/src/profiling/memory/heapprofd_end_to_end_test.cc b/src/profiling/memory/heapprofd_end_to_end_test.cc
index d698650..96d4f50 100644
--- a/src/profiling/memory/heapprofd_end_to_end_test.cc
+++ b/src/profiling/memory/heapprofd_end_to_end_test.cc
@@ -47,23 +47,6 @@
using ::testing::Bool;
using ::testing::Eq;
-class HeapprofdDelegate : public ThreadDelegate {
- public:
- HeapprofdDelegate(const std::string& producer_socket)
- : producer_socket_(producer_socket) {}
- ~HeapprofdDelegate() override = default;
-
- void Initialize(base::TaskRunner* task_runner) override {
- producer_.reset(
- new HeapprofdProducer(HeapprofdMode::kCentral, task_runner));
- producer_->ConnectWithRetries(producer_socket_.c_str());
- }
-
- private:
- std::string producer_socket_;
- std::unique_ptr<HeapprofdProducer> producer_;
-};
-
constexpr const char* kHeapprofdModeProperty = "heapprofd.userdebug.mode";
#if PERFETTO_BUILDFLAG(PERFETTO_OS_ANDROID)
diff --git a/src/profiling/memory/heapprofd_producer.cc b/src/profiling/memory/heapprofd_producer.cc
index 2497451..e077f34 100644
--- a/src/profiling/memory/heapprofd_producer.cc
+++ b/src/profiling/memory/heapprofd_producer.cc
@@ -39,7 +39,6 @@
constexpr char kHeapprofdDataSource[] = "android.heapprofd";
constexpr size_t kUnwinderThreads = 5;
-constexpr int kHeapprofdSignal = 36;
constexpr uint32_t kInitialConnectionBackoffMs = 100;
constexpr uint32_t kMaxConnectionBackoffMs = 30 * 1000;
@@ -49,6 +48,10 @@
constexpr uint64_t kDefaultShmemSize = 8 * 1048576; // ~8 MB
constexpr uint64_t kMaxShmemSize = 500 * 1048576; // ~500 MB
+// Constants specified by bionic, hardcoded here for simplicity.
+constexpr int kProfilingSignal = __SIGRTMIN + 4;
+constexpr int kHeapprofdSignalValue = 0;
+
std::vector<UnwindingWorker> MakeUnwindingWorkers(HeapprofdProducer* delegate,
size_t n) {
std::vector<UnwindingWorker> ret;
@@ -406,9 +409,12 @@
continue;
}
- PERFETTO_DLOG("Sending %d to %d", kHeapprofdSignal, pid);
- if (kill(pid, kHeapprofdSignal) != 0) {
- PERFETTO_DPLOG("kill");
+ PERFETTO_DLOG("Sending signal: %d (si_value: %d) to pid: %d",
+ kProfilingSignal, kHeapprofdSignalValue, pid);
+ union sigval signal_value;
+ signal_value.sival_int = kHeapprofdSignalValue;
+ if (sigqueue(pid, kProfilingSignal, signal_value) != 0) {
+ PERFETTO_DPLOG("sigqueue");
}
++pid_it;
}
diff --git a/src/profiling/memory/heapprofd_producer_unittest.cc b/src/profiling/memory/heapprofd_producer_unittest.cc
index 66bd452..4e4b6ed 100644
--- a/src/profiling/memory/heapprofd_producer_unittest.cc
+++ b/src/profiling/memory/heapprofd_producer_unittest.cc
@@ -41,7 +41,7 @@
MOCK_CONST_METHOD0(shared_buffer_page_size_kb, size_t());
MOCK_METHOD2(CreateTraceWriter,
std::unique_ptr<TraceWriter>(BufferID, BufferExhaustedPolicy));
- MOCK_METHOD0(GetInProcessShmemArbiter, SharedMemoryArbiter*());
+ MOCK_METHOD0(MaybeSharedMemoryArbiter, SharedMemoryArbiter*());
MOCK_METHOD1(ActivateTriggers, void(const std::vector<std::string>&));
MOCK_METHOD1(RegisterDataSource, void(const DataSourceDescriptor&));
diff --git a/src/profiling/memory/proc_utils.cc b/src/profiling/memory/proc_utils.cc
index 02f2c7d..6a4c16b 100644
--- a/src/profiling/memory/proc_utils.cc
+++ b/src/profiling/memory/proc_utils.cc
@@ -76,7 +76,8 @@
return false;
}
char cmdline[512];
- ssize_t rd = read(*fd, cmdline, sizeof(cmdline) - 1);
+ const size_t max_read_size = sizeof(cmdline) - 1;
+ ssize_t rd = read(*fd, cmdline, max_read_size);
if (rd == -1) {
PERFETTO_DPLOG("Failed to read %s", filename.c_str());
return false;
@@ -88,8 +89,12 @@
return false;
}
- // We did not manage to read the first argument.
- if (memchr(cmdline, '\0', static_cast<size_t>(rd)) == nullptr) {
+ // In some buggy kernels (before http://bit.ly/37R7qwL) /proc/pid/cmdline is
+ // not NUL-terminated (see b/147438623). If we read < max_read_size bytes
+ // assume we are hitting the aforementioned kernel bug and terminate anyways.
+ const size_t rd_u = static_cast<size_t>(rd);
+ if (rd_u >= max_read_size && memchr(cmdline, '\0', rd_u) == nullptr) {
+ // We did not manage to read the first argument.
PERFETTO_DLOG("Overflow reading cmdline for %" PRIdMAX,
static_cast<intmax_t>(pid));
errno = EOVERFLOW;
@@ -98,7 +103,7 @@
cmdline[rd] = '\0';
char* cmdline_start = cmdline;
- ssize_t size = NormalizeCmdLine(&cmdline_start, static_cast<size_t>(rd));
+ ssize_t size = NormalizeCmdLine(&cmdline_start, rd_u);
if (size == -1)
return false;
name->assign(cmdline_start, static_cast<size_t>(size));
diff --git a/src/profiling/memory/shared_ring_buffer.cc b/src/profiling/memory/shared_ring_buffer.cc
index 99a9c89..826425d 100644
--- a/src/profiling/memory/shared_ring_buffer.cc
+++ b/src/profiling/memory/shared_ring_buffer.cc
@@ -104,6 +104,18 @@
size_t outer_size = kMetaPageSize + size_ * 2 + kGuardSize;
munmap(meta_, outer_size);
}
+
+ // This is work-around for code like the following:
+ // https://android.googlesource.com/platform/libcore/+/4ecb71f94378716f88703b9f7548b5d24839262f/ojluni/src/main/native/UNIXProcess_md.c#427
+ // They fork, close all fds by iterating over /proc/self/fd using opendir.
+ // Unfortunately closedir calls free, which detects the fork, and then tries
+ // to destruct the Client that holds this SharedRingBuffer.
+ //
+ // ScopedResource crashes on failure to close, so we explicitly ignore
+ // failures here.
+ int fd = mem_fd_.release();
+ if (fd != -1)
+ close(fd);
}
void SharedRingBuffer::Initialize(base::ScopedFile mem_fd) {
diff --git a/src/profiling/memory/unwinding.cc b/src/profiling/memory/unwinding.cc
index 6b030c0..339077b 100644
--- a/src/profiling/memory/unwinding.cc
+++ b/src/profiling/memory/unwinding.cc
@@ -58,6 +58,8 @@
namespace profiling {
namespace {
+constexpr base::TimeMillis kMapsReparseInterval{500};
+
constexpr size_t kMaxFrames = 1000;
// We assume average ~300us per unwind. If we handle up to 1000 unwinds, this
@@ -155,6 +157,9 @@
std::string content;
if (!base::ReadFileDescriptor(*fd_, &content))
return false;
+
+ unwindstack::MapInfo* prev_map = nullptr;
+ unwindstack::MapInfo* prev_real_map = nullptr;
return android::procinfo::ReadMapFileContent(
&content[0], [&](uint64_t start, uint64_t end, uint16_t flags,
uint64_t pgoff, ino_t, const char* name) {
@@ -163,10 +168,12 @@
strncmp(name + 5, "ashmem/", 7) != 0) {
flags |= unwindstack::MAPS_FLAGS_DEVICE_MAP;
}
- unwindstack::MapInfo* prev_map =
- maps_.empty() ? nullptr : maps_.back().get();
maps_.emplace_back(
- new unwindstack::MapInfo(prev_map, start, end, pgoff, flags, name));
+ new unwindstack::MapInfo(prev_map, prev_real_map, start, end, pgoff, flags, name));
+ prev_map = maps_.back().get();
+ if (!prev_map->IsBlank()) {
+ prev_real_map = prev_map;
+ }
});
}
@@ -204,8 +211,14 @@
uint8_t error_code = 0;
for (int attempt = 0; attempt < 2; ++attempt) {
if (attempt > 0) {
+ if (metadata->last_maps_reparse_time + kMapsReparseInterval >
+ base::GetWallTimeMs()) {
+ PERFETTO_DLOG("Skipping reparse due to rate limit.");
+ break;
+ }
PERFETTO_DLOG("Reparsing maps");
metadata->ReparseMaps();
+ metadata->last_maps_reparse_time = base::GetWallTimeMs();
// Regs got invalidated by libuwindstack's speculative jump.
// Reset.
ReadFromRawData(regs.get(), alloc_metadata->register_data);
diff --git a/src/profiling/memory/unwinding.h b/src/profiling/memory/unwinding.h
index 39216fe..a702c64 100644
--- a/src/profiling/memory/unwinding.h
+++ b/src/profiling/memory/unwinding.h
@@ -27,6 +27,7 @@
#include <unwindstack/JitDebug.h>
#endif
+#include "perfetto/base/time.h"
#include "perfetto/ext/base/scoped_file.h"
#include "perfetto/ext/base/thread_task_runner.h"
#include "perfetto/ext/tracing/core/basic_types.h"
@@ -129,6 +130,7 @@
// The API of libunwindstack expects shared_ptr for Memory.
std::shared_ptr<unwindstack::Memory> fd_mem;
uint64_t reparses = 0;
+ base::TimeMillis last_maps_reparse_time{0};
#if PERFETTO_BUILDFLAG(PERFETTO_ANDROID_BUILD)
std::unique_ptr<unwindstack::JitDebug> jit_debug;
std::unique_ptr<unwindstack::DexFiles> dex_files;
diff --git a/src/profiling/perf/BUILD.gn b/src/profiling/perf/BUILD.gn
index b864674..80b0cb8 100644
--- a/src/profiling/perf/BUILD.gn
+++ b/src/profiling/perf/BUILD.gn
@@ -18,17 +18,12 @@
assert(enable_perfetto_traced_perf)
-# TODO(rsavitski): only building in-tree at the moment (so this build file is
-# only used for gen_android_bp, expect bitrot).
-
executable("traced_perf") {
deps = [
":traced_perf_main",
"../../../gn:default_deps",
]
- sources = [
- "main.cc",
- ]
+ sources = [ "main.cc" ]
}
source_set("traced_perf_main") {
@@ -36,7 +31,7 @@
":producer",
"../../../gn:default_deps",
"../../../src/base",
- "../../../src/tracing:ipc",
+ "../../../src/tracing/ipc/producer",
]
sources = [
"traced_perf.cc",
@@ -45,18 +40,18 @@
}
source_set("producer") {
- deps = [
+ public_deps = [
":unwind_support",
+ "../../../include/perfetto/tracing/core",
+ ]
+ deps = [
"../../../gn:default_deps",
"../../../protos/perfetto/config:cpp",
"../../../protos/perfetto/config/profiling:zero",
"../../../protos/perfetto/trace:zero",
"../../../src/base",
"../../../src/base:unix_socket",
- "../../../src/tracing:ipc",
- ]
- public_deps = [
- "../../../include/perfetto/tracing/core",
+ "../../../src/tracing/ipc/producer",
]
sources = [
"event_config.h",
@@ -68,9 +63,10 @@
}
source_set("unwind_support") {
+ public_deps = [ "../../../gn:libunwindstack" ]
deps = [
+ "../../../gn:bionic_kernel_uapi_headers",
"../../../gn:default_deps",
- "../../../gn:libunwindstack",
"../../../src/base",
]
sources = [
@@ -91,7 +87,5 @@
"../../../src/protozero",
"../../base",
]
- sources = [
- "event_config_unittest.cc",
- ]
+ sources = [ "event_config_unittest.cc" ]
}
diff --git a/src/profiling/perf/event_reader.cc b/src/profiling/perf/event_reader.cc
index a2d0e87..f7b297f 100644
--- a/src/profiling/perf/event_reader.cc
+++ b/src/profiling/perf/event_reader.cc
@@ -56,7 +56,8 @@
// cpu-scoped?
base::ScopedFile PerfEventOpen(const EventConfig& event_cfg) {
base::ScopedFile perf_fd{
- perf_event_open(event_cfg.perf_attr(), /*pid=*/-1, event_cfg.target_cpu(),
+ perf_event_open(event_cfg.perf_attr(), /*pid=*/-1,
+ static_cast<int>(event_cfg.target_cpu()),
/*group_fd=*/-1, PERF_FLAG_FD_CLOEXEC)};
return perf_fd;
}
diff --git a/src/profiling/perf/unwind_support.cc b/src/profiling/perf/unwind_support.cc
index 47dc3c0..a3cef1b 100644
--- a/src/profiling/perf/unwind_support.cc
+++ b/src/profiling/perf/unwind_support.cc
@@ -28,13 +28,13 @@
#include <unwindstack/Regs.h>
#include <unwindstack/RegsArm.h>
#include <unwindstack/RegsArm64.h>
+#include <unwindstack/RegsX86.h>
+#include <unwindstack/RegsX86_64.h>
#include <unwindstack/UserArm.h>
#include <unwindstack/UserArm64.h>
+#include <unwindstack/UserX86.h>
+#include <unwindstack/UserX86_64.h>
-// TODO(rsavitski): this includes the kernel uapi constant definitions (for
-// register sampling). For now hardcoded for in-tree builds (specifically,
-// bionic/include/kernel/). Standalone builds will need to source the headers
-// from elsewhere (without depending on the host machine's system headers).
#include <uapi/asm-arm/asm/perf_regs.h>
#include <uapi/asm-x86/asm/perf_regs.h>
#define perf_event_arm_regs perf_event_arm64_regs
@@ -46,6 +46,10 @@
namespace {
+constexpr size_t constexpr_max(size_t x, size_t y) {
+ return x > y ? x : y;
+}
+
template <typename T>
const char* ReadValue(T* value_out, const char* ptr) {
memcpy(value_out, reinterpret_cast<const void*>(ptr), sizeof(T));
@@ -57,17 +61,30 @@
// * 64 bit daemon, mixed bitness userspace
// Therefore give the kernel the mask corresponding to our build architecture.
// Register parsing handles the mixed userspace ABI cases.
+// For simplicity, we ask for as many registers as we can, even if not all of
+// them will be used during unwinding.
// TODO(rsavitski): cleanly detect 32 bit builds being side-loaded onto a system
// with 64 bit userspace processes.
uint64_t PerfUserRegsMask(unwindstack::ArchEnum arch) {
- // TODO(rsavitski): support the rest of the architectures.
- switch (arch) {
+ switch (static_cast<uint8_t>(arch)) { // cast to please -Wswitch-enum
case unwindstack::ARCH_ARM64:
return (1ULL << PERF_REG_ARM64_MAX) - 1;
case unwindstack::ARCH_ARM:
return ((1ULL << PERF_REG_ARM_MAX) - 1);
+ // perf on x86_64 doesn't allow sampling ds/es/fs/gs registers. See
+ // arch/x86/kernel/perf_regs.c in the kernel.
+ case unwindstack::ARCH_X86_64:
+ return (((1ULL << PERF_REG_X86_64_MAX) - 1) & ~(1ULL << PERF_REG_X86_DS) &
+ ~(1ULL << PERF_REG_X86_ES) & ~(1ULL << PERF_REG_X86_FS) &
+ ~(1ULL << PERF_REG_X86_GS));
+ // Note: excluding these segment registers might not be necessary on x86,
+ // but they won't be used anyway (so follow x64).
+ case unwindstack::ARCH_X86:
+ return ((1ULL << PERF_REG_X86_32_MAX) - 1) & ~(1ULL << PERF_REG_X86_DS) &
+ ~(1ULL << PERF_REG_X86_ES) & ~(1ULL << PERF_REG_X86_FS) &
+ ~(1ULL << PERF_REG_X86_GS);
default:
- PERFETTO_FATAL("Unsupported architecture (work in progress)");
+ PERFETTO_FATAL("Unsupported architecture");
}
}
@@ -86,59 +103,100 @@
// Register values as an array, indexed using the kernel uapi perf_events.h enum
// values. Unsampled values will be left as zeroes.
-// TODO(rsavitski): support all relevant architectures (allocate enough space
-// for the widest register bank).
struct RawRegisterData {
- static constexpr uint64_t kMaxSize = PERF_REG_ARM64_MAX;
+ static constexpr uint64_t kMaxSize =
+ constexpr_max(PERF_REG_ARM64_MAX,
+ constexpr_max(PERF_REG_ARM_MAX, PERF_REG_X86_64_MAX));
uint64_t regs[kMaxSize] = {};
};
+// First converts the |RawRegisterData| array to libunwindstack's "user"
+// register structs (which match the ptrace/coredump format, also available at
+// <sys/user.h>), then constructs the relevant unwindstack::Regs subclass out
+// of the latter.
std::unique_ptr<unwindstack::Regs> ToLibUnwindstackRegs(
const RawRegisterData& raw_regs,
unwindstack::ArchEnum arch) {
- // First converts the |RawRegisterData| array to libunwindstack's raw register
- // format, then constructs the relevant unwindstack::Regs subclass out of the
- // latter.
if (arch == unwindstack::ARCH_ARM64) {
static_assert(static_cast<int>(unwindstack::ARM64_REG_R0) ==
- static_cast<int>(PERF_REG_ARM64_X0),
+ static_cast<int>(PERF_REG_ARM64_X0) &&
+ static_cast<int>(unwindstack::ARM64_REG_R0) == 0,
"register layout mismatch");
static_assert(static_cast<int>(unwindstack::ARM64_REG_R30) ==
static_cast<int>(PERF_REG_ARM64_LR),
"register layout mismatch");
-
- unwindstack::arm64_user_regs arm64_user_regs;
- memset(&arm64_user_regs, 0, sizeof(arm64_user_regs));
- memcpy(&arm64_user_regs.regs[unwindstack::ARM64_REG_R0],
- &raw_regs.regs[PERF_REG_ARM64_X0],
- sizeof(uint64_t) * (PERF_REG_ARM64_LR - PERF_REG_ARM64_X0 + 1));
+ // Both the perf_event register order and the "user" format are derived from
+ // "struct pt_regs", so we can directly memcpy the first 31 regs (up to and
+ // including LR).
+ unwindstack::arm64_user_regs arm64_user_regs = {};
+ memcpy(&arm64_user_regs.regs[0], &raw_regs.regs[0],
+ sizeof(uint64_t) * (PERF_REG_ARM64_LR + 1));
arm64_user_regs.sp = raw_regs.regs[PERF_REG_ARM64_SP];
arm64_user_regs.pc = raw_regs.regs[PERF_REG_ARM64_PC];
-
return std::unique_ptr<unwindstack::Regs>(
unwindstack::RegsArm64::Read(&arm64_user_regs));
}
if (arch == unwindstack::ARCH_ARM) {
static_assert(static_cast<int>(unwindstack::ARM_REG_R0) ==
- static_cast<int>(PERF_REG_ARM_R0),
+ static_cast<int>(PERF_REG_ARM_R0) &&
+ static_cast<int>(unwindstack::ARM_REG_R0) == 0,
"register layout mismatch");
static_assert(static_cast<int>(unwindstack::ARM_REG_LAST) ==
static_cast<int>(PERF_REG_ARM_MAX),
"register layout mismatch");
-
- unwindstack::arm_user_regs arm_user_regs;
- memset(&arm_user_regs, 0, sizeof(arm_user_regs));
- for (size_t i = unwindstack::ARM_REG_R0; i < unwindstack::ARM_REG_LAST;
- i++) {
+ // As with arm64, the layouts match, but we need to downcast to u32.
+ unwindstack::arm_user_regs arm_user_regs = {};
+ for (size_t i = 0; i < unwindstack::ARM_REG_LAST; i++) {
arm_user_regs.regs[i] = static_cast<uint32_t>(raw_regs.regs[i]);
}
-
return std::unique_ptr<unwindstack::Regs>(
unwindstack::RegsArm::Read(&arm_user_regs));
}
- PERFETTO_FATAL("Unsupported architecture (work in progress)");
+ if (arch == unwindstack::ARCH_X86_64) {
+ // We've sampled more registers than what libunwindstack will use. Don't
+ // copy over cs/ss/flags.
+ unwindstack::x86_64_user_regs x86_64_user_regs = {};
+ x86_64_user_regs.rax = raw_regs.regs[PERF_REG_X86_AX];
+ x86_64_user_regs.rbx = raw_regs.regs[PERF_REG_X86_BX];
+ x86_64_user_regs.rcx = raw_regs.regs[PERF_REG_X86_CX];
+ x86_64_user_regs.rdx = raw_regs.regs[PERF_REG_X86_DX];
+ x86_64_user_regs.r8 = raw_regs.regs[PERF_REG_X86_R8];
+ x86_64_user_regs.r9 = raw_regs.regs[PERF_REG_X86_R9];
+ x86_64_user_regs.r10 = raw_regs.regs[PERF_REG_X86_R10];
+ x86_64_user_regs.r11 = raw_regs.regs[PERF_REG_X86_R11];
+ x86_64_user_regs.r12 = raw_regs.regs[PERF_REG_X86_R12];
+ x86_64_user_regs.r13 = raw_regs.regs[PERF_REG_X86_R13];
+ x86_64_user_regs.r14 = raw_regs.regs[PERF_REG_X86_R14];
+ x86_64_user_regs.r15 = raw_regs.regs[PERF_REG_X86_R15];
+ x86_64_user_regs.rdi = raw_regs.regs[PERF_REG_X86_DI];
+ x86_64_user_regs.rsi = raw_regs.regs[PERF_REG_X86_SI];
+ x86_64_user_regs.rbp = raw_regs.regs[PERF_REG_X86_BP];
+ x86_64_user_regs.rsp = raw_regs.regs[PERF_REG_X86_SP];
+ x86_64_user_regs.rip = raw_regs.regs[PERF_REG_X86_IP];
+ return std::unique_ptr<unwindstack::Regs>(
+ unwindstack::RegsX86_64::Read(&x86_64_user_regs));
+ }
+
+ if (arch == unwindstack::ARCH_X86) {
+ // We've sampled more registers than what libunwindstack will use. Don't
+ // copy over cs/ss/flags.
+ unwindstack::x86_user_regs x86_user_regs = {};
+ x86_user_regs.eax = static_cast<uint32_t>(raw_regs.regs[PERF_REG_X86_AX]);
+ x86_user_regs.ebx = static_cast<uint32_t>(raw_regs.regs[PERF_REG_X86_BX]);
+ x86_user_regs.ecx = static_cast<uint32_t>(raw_regs.regs[PERF_REG_X86_CX]);
+ x86_user_regs.edx = static_cast<uint32_t>(raw_regs.regs[PERF_REG_X86_DX]);
+ x86_user_regs.ebp = static_cast<uint32_t>(raw_regs.regs[PERF_REG_X86_BP]);
+ x86_user_regs.edi = static_cast<uint32_t>(raw_regs.regs[PERF_REG_X86_DI]);
+ x86_user_regs.esi = static_cast<uint32_t>(raw_regs.regs[PERF_REG_X86_SI]);
+ x86_user_regs.esp = static_cast<uint32_t>(raw_regs.regs[PERF_REG_X86_SP]);
+ x86_user_regs.eip = static_cast<uint32_t>(raw_regs.regs[PERF_REG_X86_IP]);
+ return std::unique_ptr<unwindstack::Regs>(
+ unwindstack::RegsX86::Read(&x86_user_regs));
+ }
+
+ PERFETTO_FATAL("Unsupported architecture");
}
} // namespace
@@ -164,7 +222,7 @@
RawRegisterData raw_regs{};
uint64_t regs_mask = PerfUserRegsMaskForCurrentArch();
for (size_t i = 0; regs_mask && (i < RawRegisterData::kMaxSize); i++) {
- if (regs_mask & (1u << i)) {
+ if (regs_mask & (1ULL << i)) {
parse_pos = ReadValue(&raw_regs.regs[i], parse_pos);
}
}
@@ -178,6 +236,7 @@
// the PC into the R15 slot, and treat the resulting RawRegisterData as an
// arm32 register bank. See "Fundamentals of ARMv8-A" (ARM DOC
// 100878_0100_en), page 28.
+ // x86-64 doesn't need any such fixups.
if (requested_arch == unwindstack::ARCH_ARM64 &&
sampled_abi == PERF_SAMPLE_REGS_ABI_32) {
raw_regs.regs[PERF_REG_ARM_PC] = raw_regs.regs[PERF_REG_ARM64_PC];
diff --git a/src/profiling/symbolizer/BUILD.gn b/src/profiling/symbolizer/BUILD.gn
index 3bbc385..69c9446 100644
--- a/src/profiling/symbolizer/BUILD.gn
+++ b/src/profiling/symbolizer/BUILD.gn
@@ -15,12 +15,8 @@
import("../../../gn/perfetto.gni")
source_set("symbolizer") {
- public_deps = [
- "../../../include/perfetto/ext/base",
- ]
- deps = [
- "../../../gn:default_deps",
- ]
+ public_deps = [ "../../../include/perfetto/ext/base" ]
+ deps = [ "../../../gn:default_deps" ]
sources = [
"local_symbolizer.cc",
"local_symbolizer.h",
diff --git a/src/protozero/BUILD.gn b/src/protozero/BUILD.gn
index e4cbd82..124bb56 100644
--- a/src/protozero/BUILD.gn
+++ b/src/protozero/BUILD.gn
@@ -43,9 +43,7 @@
static_library("libprotozero") {
complete_static_lib = true
- deps = [
- ":protozero",
- ]
+ deps = [ ":protozero" ]
}
perfetto_unittest_source_set("unittests") {
@@ -87,9 +85,7 @@
}
perfetto_fuzzer_test("protozero_decoder_fuzzer") {
- sources = [
- "proto_decoder_fuzzer.cc",
- ]
+ sources = [ "proto_decoder_fuzzer.cc" ]
deps = [
":protozero",
"../../gn:default_deps",
diff --git a/src/protozero/protoc_plugin/BUILD.gn b/src/protozero/protoc_plugin/BUILD.gn
index 4a9c7f4..a628be7 100644
--- a/src/protozero/protoc_plugin/BUILD.gn
+++ b/src/protozero/protoc_plugin/BUILD.gn
@@ -17,9 +17,7 @@
# The plugin that generates zero-copy serializers and deserializers. Those are
# the xxx.pbzero.h headers used all over the codebase.
perfetto_host_executable("protozero_plugin") {
- sources = [
- "protozero_plugin.cc",
- ]
+ sources = [ "protozero_plugin.cc" ]
deps = [
"../../../gn:default_deps",
"../../../gn:protoc_lib",
@@ -31,9 +29,7 @@
# This is used for core classes traced needs to know about such as
# DataSourceDescriptor.
perfetto_host_executable("cppgen_plugin") {
- sources = [
- "cppgen_plugin.cc",
- ]
+ sources = [ "cppgen_plugin.cc" ]
deps = [
"../../../gn:default_deps",
"../../../gn:protoc_lib",
diff --git a/src/protozero/test/example_proto/library.proto b/src/protozero/test/example_proto/library.proto
index 059080f..7ca4b17 100644
--- a/src/protozero/test/example_proto/library.proto
+++ b/src/protozero/test/example_proto/library.proto
@@ -15,7 +15,6 @@
*/
syntax = "proto2";
-option optimize_for = LITE_RUNTIME;
package protozero.test.protos;
diff --git a/src/protozero/test/example_proto/library_internals/galaxies.proto b/src/protozero/test/example_proto/library_internals/galaxies.proto
index d2a1e42..75b156a 100644
--- a/src/protozero/test/example_proto/library_internals/galaxies.proto
+++ b/src/protozero/test/example_proto/library_internals/galaxies.proto
@@ -15,7 +15,6 @@
*/
syntax = "proto2";
-option optimize_for = LITE_RUNTIME;
package protozero.test.protos;
diff --git a/src/protozero/test/example_proto/test_messages.descriptor.h b/src/protozero/test/example_proto/test_messages.descriptor.h
index 9c2bcfa..f27e4ec 100644
--- a/src/protozero/test/example_proto/test_messages.descriptor.h
+++ b/src/protozero/test/example_proto/test_messages.descriptor.h
@@ -25,17 +25,17 @@
// This file was autogenerated by tools/gen_binary_descriptors. Do not edit.
// SHA1(tools/gen_binary_descriptors)
-// f242f1ac484bbe7ba4c45e77b56ab588f8015196
+// d6628b15181dba5287e35b56b966b39ea93d42b1
// SHA1(src/protozero/test/example_proto/test_messages.proto)
-// 61c0771c4c18c994996335be97413d944ce8f80d
+// bd59c7719b091c8277d2dce867d28dfa5b40bab2
// This is the proto TestMessages encoded as a ProtoFileDescriptor to allow
// for reflection without libprotobuf full/non-lite protos.
namespace perfetto {
-constexpr std::array<uint8_t, 4181> kTestMessagesDescriptor{
- {0x0a, 0x66, 0x0a, 0x33, 0x73, 0x72, 0x63, 0x2f, 0x70, 0x72, 0x6f, 0x74,
+constexpr std::array<uint8_t, 4165> kTestMessagesDescriptor{
+ {0x0a, 0x62, 0x0a, 0x33, 0x73, 0x72, 0x63, 0x2f, 0x70, 0x72, 0x6f, 0x74,
0x6f, 0x7a, 0x65, 0x72, 0x6f, 0x2f, 0x74, 0x65, 0x73, 0x74, 0x2f, 0x65,
0x78, 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x5f, 0x70, 0x72, 0x6f, 0x74, 0x6f,
0x2f, 0x75, 0x70, 0x70, 0x65, 0x72, 0x5f, 0x69, 0x6d, 0x70, 0x6f, 0x72,
@@ -43,61 +43,60 @@
0x74, 0x6f, 0x7a, 0x65, 0x72, 0x6f, 0x2e, 0x74, 0x65, 0x73, 0x74, 0x2e,
0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x22, 0x14, 0x0a, 0x12, 0x54, 0x72,
0x69, 0x63, 0x6b, 0x79, 0x50, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x49, 0x6d,
- 0x70, 0x6f, 0x72, 0x74, 0x42, 0x02, 0x48, 0x03, 0x0a, 0xcc, 0x01, 0x0a,
- 0x41, 0x73, 0x72, 0x63, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x7a, 0x65,
- 0x72, 0x6f, 0x2f, 0x74, 0x65, 0x73, 0x74, 0x2f, 0x65, 0x78, 0x61, 0x6d,
- 0x70, 0x6c, 0x65, 0x5f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2f, 0x6c, 0x69,
- 0x62, 0x72, 0x61, 0x72, 0x79, 0x5f, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e,
- 0x61, 0x6c, 0x73, 0x2f, 0x67, 0x61, 0x6c, 0x61, 0x78, 0x69, 0x65, 0x73,
- 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x15, 0x70, 0x72, 0x6f, 0x74,
- 0x6f, 0x7a, 0x65, 0x72, 0x6f, 0x2e, 0x74, 0x65, 0x73, 0x74, 0x2e, 0x70,
- 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x1a, 0x33, 0x73, 0x72, 0x63, 0x2f, 0x70,
- 0x72, 0x6f, 0x74, 0x6f, 0x7a, 0x65, 0x72, 0x6f, 0x2f, 0x74, 0x65, 0x73,
- 0x74, 0x2f, 0x65, 0x78, 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x5f, 0x70, 0x72,
- 0x6f, 0x74, 0x6f, 0x2f, 0x75, 0x70, 0x70, 0x65, 0x72, 0x5f, 0x69, 0x6d,
- 0x70, 0x6f, 0x72, 0x74, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2a, 0x35,
- 0x0a, 0x06, 0x47, 0x61, 0x6c, 0x61, 0x78, 0x79, 0x12, 0x0d, 0x0a, 0x09,
- 0x4d, 0x49, 0x4c, 0x4b, 0x59, 0x5f, 0x57, 0x41, 0x59, 0x10, 0x01, 0x12,
- 0x0d, 0x0a, 0x09, 0x41, 0x4e, 0x44, 0x52, 0x4f, 0x4d, 0x45, 0x44, 0x41,
- 0x10, 0x02, 0x12, 0x0d, 0x0a, 0x09, 0x53, 0x55, 0x4e, 0x46, 0x4c, 0x4f,
- 0x57, 0x45, 0x52, 0x10, 0x03, 0x42, 0x02, 0x48, 0x03, 0x50, 0x00, 0x0a,
- 0xb4, 0x03, 0x0a, 0x2e, 0x73, 0x72, 0x63, 0x2f, 0x70, 0x72, 0x6f, 0x74,
- 0x6f, 0x7a, 0x65, 0x72, 0x6f, 0x2f, 0x74, 0x65, 0x73, 0x74, 0x2f, 0x65,
- 0x78, 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x5f, 0x70, 0x72, 0x6f, 0x74, 0x6f,
- 0x2f, 0x6c, 0x69, 0x62, 0x72, 0x61, 0x72, 0x79, 0x2e, 0x70, 0x72, 0x6f,
+ 0x70, 0x6f, 0x72, 0x74, 0x0a, 0xc8, 0x01, 0x0a, 0x41, 0x73, 0x72, 0x63,
+ 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x7a, 0x65, 0x72, 0x6f, 0x2f, 0x74,
+ 0x65, 0x73, 0x74, 0x2f, 0x65, 0x78, 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x5f,
+ 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2f, 0x6c, 0x69, 0x62, 0x72, 0x61, 0x72,
+ 0x79, 0x5f, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x73, 0x2f,
+ 0x67, 0x61, 0x6c, 0x61, 0x78, 0x69, 0x65, 0x73, 0x2e, 0x70, 0x72, 0x6f,
0x74, 0x6f, 0x12, 0x15, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x7a, 0x65, 0x72,
0x6f, 0x2e, 0x74, 0x65, 0x73, 0x74, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f,
- 0x73, 0x1a, 0x41, 0x73, 0x72, 0x63, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f,
+ 0x73, 0x1a, 0x33, 0x73, 0x72, 0x63, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f,
0x7a, 0x65, 0x72, 0x6f, 0x2f, 0x74, 0x65, 0x73, 0x74, 0x2f, 0x65, 0x78,
0x61, 0x6d, 0x70, 0x6c, 0x65, 0x5f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2f,
- 0x6c, 0x69, 0x62, 0x72, 0x61, 0x72, 0x79, 0x5f, 0x69, 0x6e, 0x74, 0x65,
- 0x72, 0x6e, 0x61, 0x6c, 0x73, 0x2f, 0x67, 0x61, 0x6c, 0x61, 0x78, 0x69,
- 0x65, 0x73, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x22, 0xa1, 0x02, 0x0a,
- 0x14, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x67, 0x61, 0x6c, 0x61, 0x63, 0x74,
- 0x69, 0x63, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x12, 0x42, 0x0a,
- 0x0d, 0x6f, 0x72, 0x69, 0x67, 0x69, 0x6e, 0x5f, 0x67, 0x61, 0x6c, 0x61,
- 0x78, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x1d, 0x2e, 0x70,
- 0x72, 0x6f, 0x74, 0x6f, 0x7a, 0x65, 0x72, 0x6f, 0x2e, 0x74, 0x65, 0x73,
- 0x74, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2e, 0x47, 0x61, 0x6c,
- 0x61, 0x78, 0x79, 0x52, 0x0c, 0x6f, 0x72, 0x69, 0x67, 0x69, 0x6e, 0x47,
- 0x61, 0x6c, 0x61, 0x78, 0x79, 0x12, 0x23, 0x0a, 0x0d, 0x6f, 0x72, 0x69,
- 0x67, 0x69, 0x6e, 0x5f, 0x70, 0x6c, 0x61, 0x6e, 0x65, 0x74, 0x18, 0x02,
- 0x20, 0x01, 0x28, 0x09, 0x52, 0x0c, 0x6f, 0x72, 0x69, 0x67, 0x69, 0x6e,
- 0x50, 0x6c, 0x61, 0x6e, 0x65, 0x74, 0x12, 0x4c, 0x0a, 0x12, 0x64, 0x65,
- 0x73, 0x74, 0x69, 0x6e, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x67, 0x61,
- 0x6c, 0x61, 0x78, 0x79, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x1d,
- 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x7a, 0x65, 0x72, 0x6f, 0x2e, 0x74,
- 0x65, 0x73, 0x74, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2e, 0x47,
- 0x61, 0x6c, 0x61, 0x78, 0x79, 0x52, 0x11, 0x64, 0x65, 0x73, 0x74, 0x69,
- 0x6e, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x47, 0x61, 0x6c, 0x61, 0x78, 0x79,
- 0x12, 0x2d, 0x0a, 0x12, 0x64, 0x65, 0x73, 0x74, 0x69, 0x6e, 0x61, 0x74,
- 0x69, 0x6f, 0x6e, 0x5f, 0x70, 0x6c, 0x61, 0x6e, 0x65, 0x74, 0x18, 0x04,
- 0x20, 0x01, 0x28, 0x09, 0x52, 0x11, 0x64, 0x65, 0x73, 0x74, 0x69, 0x6e,
- 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x50, 0x6c, 0x61, 0x6e, 0x65, 0x74, 0x12,
- 0x23, 0x0a, 0x0d, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x5f, 0x6d, 0x65, 0x73,
- 0x73, 0x61, 0x67, 0x65, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x0c,
- 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65,
- 0x42, 0x02, 0x48, 0x03, 0x50, 0x00, 0x0a, 0xe4, 0x1a, 0x0a, 0x34, 0x73,
+ 0x75, 0x70, 0x70, 0x65, 0x72, 0x5f, 0x69, 0x6d, 0x70, 0x6f, 0x72, 0x74,
+ 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2a, 0x35, 0x0a, 0x06, 0x47, 0x61,
+ 0x6c, 0x61, 0x78, 0x79, 0x12, 0x0d, 0x0a, 0x09, 0x4d, 0x49, 0x4c, 0x4b,
+ 0x59, 0x5f, 0x57, 0x41, 0x59, 0x10, 0x01, 0x12, 0x0d, 0x0a, 0x09, 0x41,
+ 0x4e, 0x44, 0x52, 0x4f, 0x4d, 0x45, 0x44, 0x41, 0x10, 0x02, 0x12, 0x0d,
+ 0x0a, 0x09, 0x53, 0x55, 0x4e, 0x46, 0x4c, 0x4f, 0x57, 0x45, 0x52, 0x10,
+ 0x03, 0x50, 0x00, 0x0a, 0xb0, 0x03, 0x0a, 0x2e, 0x73, 0x72, 0x63, 0x2f,
+ 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x7a, 0x65, 0x72, 0x6f, 0x2f, 0x74, 0x65,
+ 0x73, 0x74, 0x2f, 0x65, 0x78, 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x5f, 0x70,
+ 0x72, 0x6f, 0x74, 0x6f, 0x2f, 0x6c, 0x69, 0x62, 0x72, 0x61, 0x72, 0x79,
+ 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x15, 0x70, 0x72, 0x6f, 0x74,
+ 0x6f, 0x7a, 0x65, 0x72, 0x6f, 0x2e, 0x74, 0x65, 0x73, 0x74, 0x2e, 0x70,
+ 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x1a, 0x41, 0x73, 0x72, 0x63, 0x2f, 0x70,
+ 0x72, 0x6f, 0x74, 0x6f, 0x7a, 0x65, 0x72, 0x6f, 0x2f, 0x74, 0x65, 0x73,
+ 0x74, 0x2f, 0x65, 0x78, 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x5f, 0x70, 0x72,
+ 0x6f, 0x74, 0x6f, 0x2f, 0x6c, 0x69, 0x62, 0x72, 0x61, 0x72, 0x79, 0x5f,
+ 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x73, 0x2f, 0x67, 0x61,
+ 0x6c, 0x61, 0x78, 0x69, 0x65, 0x73, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f,
+ 0x22, 0xa1, 0x02, 0x0a, 0x14, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x67, 0x61,
+ 0x6c, 0x61, 0x63, 0x74, 0x69, 0x63, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67,
+ 0x65, 0x12, 0x42, 0x0a, 0x0d, 0x6f, 0x72, 0x69, 0x67, 0x69, 0x6e, 0x5f,
+ 0x67, 0x61, 0x6c, 0x61, 0x78, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0e,
+ 0x32, 0x1d, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x7a, 0x65, 0x72, 0x6f,
+ 0x2e, 0x74, 0x65, 0x73, 0x74, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73,
+ 0x2e, 0x47, 0x61, 0x6c, 0x61, 0x78, 0x79, 0x52, 0x0c, 0x6f, 0x72, 0x69,
+ 0x67, 0x69, 0x6e, 0x47, 0x61, 0x6c, 0x61, 0x78, 0x79, 0x12, 0x23, 0x0a,
+ 0x0d, 0x6f, 0x72, 0x69, 0x67, 0x69, 0x6e, 0x5f, 0x70, 0x6c, 0x61, 0x6e,
+ 0x65, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0c, 0x6f, 0x72,
+ 0x69, 0x67, 0x69, 0x6e, 0x50, 0x6c, 0x61, 0x6e, 0x65, 0x74, 0x12, 0x4c,
+ 0x0a, 0x12, 0x64, 0x65, 0x73, 0x74, 0x69, 0x6e, 0x61, 0x74, 0x69, 0x6f,
+ 0x6e, 0x5f, 0x67, 0x61, 0x6c, 0x61, 0x78, 0x79, 0x18, 0x03, 0x20, 0x01,
+ 0x28, 0x0e, 0x32, 0x1d, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x7a, 0x65,
+ 0x72, 0x6f, 0x2e, 0x74, 0x65, 0x73, 0x74, 0x2e, 0x70, 0x72, 0x6f, 0x74,
+ 0x6f, 0x73, 0x2e, 0x47, 0x61, 0x6c, 0x61, 0x78, 0x79, 0x52, 0x11, 0x64,
+ 0x65, 0x73, 0x74, 0x69, 0x6e, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x47, 0x61,
+ 0x6c, 0x61, 0x78, 0x79, 0x12, 0x2d, 0x0a, 0x12, 0x64, 0x65, 0x73, 0x74,
+ 0x69, 0x6e, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x70, 0x6c, 0x61, 0x6e,
+ 0x65, 0x74, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x11, 0x64, 0x65,
+ 0x73, 0x74, 0x69, 0x6e, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x50, 0x6c, 0x61,
+ 0x6e, 0x65, 0x74, 0x12, 0x23, 0x0a, 0x0d, 0x70, 0x72, 0x6f, 0x74, 0x6f,
+ 0x5f, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x18, 0x05, 0x20, 0x01,
+ 0x28, 0x0c, 0x52, 0x0c, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x4d, 0x65, 0x73,
+ 0x73, 0x61, 0x67, 0x65, 0x50, 0x00, 0x0a, 0xe0, 0x1a, 0x0a, 0x34, 0x73,
0x72, 0x63, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x7a, 0x65, 0x72, 0x6f,
0x2f, 0x74, 0x65, 0x73, 0x74, 0x2f, 0x65, 0x78, 0x61, 0x6d, 0x70, 0x6c,
0x65, 0x5f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2f, 0x74, 0x65, 0x73, 0x74,
@@ -224,19 +223,19 @@
0x72, 0x42, 0x61, 0x7a, 0x12, 0x16, 0x0a, 0x06, 0x62, 0x61, 0x72, 0x42,
0x61, 0x7a, 0x18, 0x02, 0x20, 0x01, 0x28, 0x08, 0x52, 0x06, 0x62, 0x61,
0x72, 0x42, 0x61, 0x7a, 0x12, 0x16, 0x0a, 0x06, 0x4d, 0x6f, 0x6f, 0x4d,
- 0x6f, 0x6f, 0x18, 0x03, 0x20, 0x01, 0x28, 0x08, 0x52, 0x06, 0x6d, 0x6f,
+ 0x6f, 0x6f, 0x18, 0x03, 0x20, 0x01, 0x28, 0x08, 0x52, 0x06, 0x4d, 0x6f,
0x6f, 0x4d, 0x6f, 0x6f, 0x12, 0x1e, 0x0a, 0x0a, 0x55, 0x52, 0x4c, 0x45,
0x6e, 0x63, 0x6f, 0x64, 0x65, 0x72, 0x18, 0x04, 0x20, 0x01, 0x28, 0x08,
- 0x52, 0x0a, 0x75, 0x52, 0x4c, 0x45, 0x6e, 0x63, 0x6f, 0x64, 0x65, 0x72,
+ 0x52, 0x0a, 0x55, 0x52, 0x4c, 0x45, 0x6e, 0x63, 0x6f, 0x64, 0x65, 0x72,
0x12, 0x12, 0x0a, 0x04, 0x58, 0x4d, 0x61, 0x70, 0x18, 0x05, 0x20, 0x01,
- 0x28, 0x08, 0x52, 0x04, 0x78, 0x4d, 0x61, 0x70, 0x12, 0x21, 0x0a, 0x0d,
+ 0x28, 0x08, 0x52, 0x04, 0x58, 0x4d, 0x61, 0x70, 0x12, 0x21, 0x0a, 0x0d,
0x55, 0x72, 0x4c, 0x45, 0x5f, 0x6e, 0x63, 0x6f, 0x5f, 0x5f, 0x64, 0x65,
- 0x72, 0x18, 0x06, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0a, 0x75, 0x72, 0x4c,
+ 0x72, 0x18, 0x06, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0a, 0x55, 0x72, 0x4c,
0x45, 0x4e, 0x63, 0x6f, 0x44, 0x65, 0x72, 0x12, 0x1a, 0x0a, 0x09, 0x5f,
0x5f, 0x62, 0x69, 0x67, 0x42, 0x61, 0x6e, 0x67, 0x18, 0x07, 0x20, 0x01,
- 0x28, 0x08, 0x52, 0x07, 0x62, 0x69, 0x67, 0x42, 0x61, 0x6e, 0x67, 0x12,
+ 0x28, 0x08, 0x52, 0x07, 0x42, 0x69, 0x67, 0x42, 0x61, 0x6e, 0x67, 0x12,
0x0e, 0x0a, 0x02, 0x55, 0x32, 0x18, 0x08, 0x20, 0x01, 0x28, 0x08, 0x52,
- 0x02, 0x75, 0x32, 0x12, 0x1a, 0x0a, 0x09, 0x62, 0x61, 0x6e, 0x67, 0x42,
+ 0x02, 0x55, 0x32, 0x12, 0x1a, 0x0a, 0x09, 0x62, 0x61, 0x6e, 0x67, 0x42,
0x69, 0x67, 0x5f, 0x5f, 0x18, 0x09, 0x20, 0x01, 0x28, 0x08, 0x52, 0x07,
0x62, 0x61, 0x6e, 0x67, 0x42, 0x69, 0x67, 0x22, 0x8f, 0x01, 0x0a, 0x14,
0x50, 0x61, 0x63, 0x6b, 0x65, 0x64, 0x52, 0x65, 0x70, 0x65, 0x61, 0x74,
@@ -383,7 +382,7 @@
0xff, 0xff, 0xff, 0x01, 0x2a, 0x1f, 0x0a, 0x07, 0x42, 0x69, 0x67, 0x45,
0x6e, 0x75, 0x6d, 0x12, 0x09, 0x0a, 0x05, 0x42, 0x45, 0x47, 0x49, 0x4e,
0x10, 0x0a, 0x12, 0x09, 0x0a, 0x03, 0x45, 0x4e, 0x44, 0x10, 0x94, 0x91,
- 0x06, 0x42, 0x02, 0x48, 0x03}};
+ 0x06}};
} // namespace perfetto
diff --git a/src/protozero/test/example_proto/test_messages.proto b/src/protozero/test/example_proto/test_messages.proto
index 298b77f..f8f2d31 100644
--- a/src/protozero/test/example_proto/test_messages.proto
+++ b/src/protozero/test/example_proto/test_messages.proto
@@ -15,7 +15,6 @@
*/
syntax = "proto2";
-option optimize_for = LITE_RUNTIME;
package protozero.test.protos;
diff --git a/src/protozero/test/example_proto/upper_import.proto b/src/protozero/test/example_proto/upper_import.proto
index 486eff9..4479c25 100644
--- a/src/protozero/test/example_proto/upper_import.proto
+++ b/src/protozero/test/example_proto/upper_import.proto
@@ -15,7 +15,6 @@
*/
syntax = "proto2";
-option optimize_for = LITE_RUNTIME;
package protozero.test.protos;
diff --git a/src/trace_processor/BUILD.gn b/src/trace_processor/BUILD.gn
index a6fd002..c057068 100644
--- a/src/trace_processor/BUILD.gn
+++ b/src/trace_processor/BUILD.gn
@@ -23,11 +23,11 @@
# The library which eases processing of Perfetto traces by exposing reading
# friendly APIs.
-static_library("trace_processor") {
- complete_static_lib = true
- deps = [
- ":lib",
- ]
+if (enable_perfetto_trace_processor_sqlite) {
+ static_library("trace_processor") {
+ complete_static_lib = true
+ deps = [ ":lib" ]
+ }
}
if (enable_perfetto_ui) {
@@ -86,8 +86,8 @@
"forwarding_trace_parser.cc",
"forwarding_trace_parser.h",
"ftrace_utils.h",
- "gzip_trace_parser.cc",
- "gzip_trace_parser.h",
+ "global_args_tracker.cc",
+ "global_args_tracker.h",
"heap_profile_tracker.cc",
"heap_profile_tracker.h",
"importers/ftrace/ftrace_module.cc",
@@ -136,18 +136,16 @@
"trace_storage.h",
"track_tracker.cc",
"track_tracker.h",
- "variadic.h",
"virtual_destructors.cc",
]
-
deps = [
":descriptors",
"../../gn:default_deps",
- "../../gn:zlib",
"../base",
"../protozero",
"containers",
"tables",
+ "types",
]
public_deps = [
"../../include/perfetto/trace_processor:storage",
@@ -165,6 +163,13 @@
"../../protos/perfetto/trace/sys_stats:zero",
"../../protos/perfetto/trace/track_event:zero",
]
+ if (enable_perfetto_zlib) {
+ sources += [
+ "gzip_trace_parser.cc",
+ "gzip_trace_parser.h",
+ ]
+ deps += [ "../../gn:zlib" ]
+ }
if (enable_perfetto_trace_processor_json_import) {
sources += [
"importers/json/json_trace_parser.cc",
@@ -238,9 +243,7 @@
"syscalls_armeabi.h",
"syscalls_x86_64.h",
]
- public_deps = [
- ":storage_minimal",
- ]
+ public_deps = [ ":storage_minimal" ]
deps = [
"../../include/perfetto/ext/base:base",
"../../include/perfetto/ext/traced:sys_stats_counters",
@@ -250,6 +253,7 @@
"../../protos/perfetto/trace/gpu:zero",
"../../protos/perfetto/trace/interned_data:zero",
"../protozero",
+ "types",
]
if (enable_perfetto_trace_processor_json) {
public_deps += [ "../../gn:jsoncpp" ]
@@ -274,129 +278,116 @@
"../../gn:jsoncpp",
"../base",
]
- public_deps = [
- "../../include/perfetto/ext/trace_processor:export_json",
+ public_deps = [ "../../include/perfetto/ext/trace_processor:export_json" ]
+ }
+}
+
+if (enable_perfetto_trace_processor_sqlite) {
+ source_set("lib") {
+ sources = [
+ "filtered_row_index.cc",
+ "filtered_row_index.h",
+ "read_trace.cc",
+ "row_iterators.cc",
+ "row_iterators.h",
+ "sched_slice_table.cc",
+ "sched_slice_table.h",
+ "span_join_operator_table.cc",
+ "span_join_operator_table.h",
+ "sql_stats_table.cc",
+ "sql_stats_table.h",
+ "sqlite_experimental_flamegraph_table.cc",
+ "sqlite_experimental_flamegraph_table.h",
+ "sqlite_raw_table.cc",
+ "sqlite_raw_table.h",
+ "stats_table.cc",
+ "stats_table.h",
+ "storage_columns.cc",
+ "storage_columns.h",
+ "storage_schema.cc",
+ "storage_schema.h",
+ "storage_table.cc",
+ "storage_table.h",
+ "trace_processor.cc",
+ "trace_processor_impl.cc",
+ "trace_processor_impl.h",
+ "window_operator_table.cc",
+ "window_operator_table.h",
+ ]
+
+ deps = [
+ ":storage_full",
+ "../../gn:default_deps",
+ "../../gn:sqlite",
+ "../../protos/perfetto/metrics:zero",
+ "../../protos/perfetto/metrics/android:zero",
+ "../../protos/perfetto/trace/ftrace:zero",
+ "../base",
+ "db:lib",
+ "metrics:lib",
+ "sqlite",
+ "tables",
+ "types",
+ ]
+ public_deps = [ "../../include/perfetto/trace_processor" ]
+ if (enable_perfetto_trace_processor_json) {
+ deps += [ ":export_json" ]
+ }
+ }
+
+ perfetto_host_executable("trace_processor_shell") {
+ deps = [
+ ":lib",
+ "../../gn:default_deps",
+ "../../gn:protoc_lib",
+ "../../src/profiling/symbolizer",
+ "../../src/profiling/symbolizer:symbolize_database",
+ "../base",
+ "metrics:lib",
+ ]
+ if (enable_perfetto_version_gen) {
+ deps += [ "../../gn/standalone:gen_git_revision" ]
+ }
+ if (enable_perfetto_trace_processor_linenoise) {
+ deps += [ "../../gn:linenoise" ]
+ }
+ if (enable_perfetto_trace_processor_httpd) {
+ deps += [ "rpc:httpd" ]
+ }
+ sources = [
+ "proto_to_json.cc",
+ "proto_to_json.h",
+ "trace_processor_shell.cc",
]
}
-}
-
-source_set("lib") {
- sources = [
- "args_table.cc",
- "args_table.h",
- "filtered_row_index.cc",
- "filtered_row_index.h",
- "gfp_flags.cc",
- "gfp_flags.h",
- "process_table.cc",
- "process_table.h",
- "raw_table.cc",
- "raw_table.h",
- "read_trace.cc",
- "row_iterators.cc",
- "row_iterators.h",
- "sched_slice_table.cc",
- "sched_slice_table.h",
- "span_join_operator_table.cc",
- "span_join_operator_table.h",
- "sql_stats_table.cc",
- "sql_stats_table.h",
- "stats_table.cc",
- "stats_table.h",
- "storage_columns.cc",
- "storage_columns.h",
- "storage_schema.cc",
- "storage_schema.h",
- "storage_table.cc",
- "storage_table.h",
- "thread_table.cc",
- "thread_table.h",
- "trace_processor.cc",
- "trace_processor_impl.cc",
- "trace_processor_impl.h",
- "window_operator_table.cc",
- "window_operator_table.h",
- ]
-
- deps = [
- ":storage_full",
- "../../gn:default_deps",
- "../../gn:sqlite",
- "../../protos/perfetto/metrics:zero",
- "../../protos/perfetto/metrics/android:zero",
- "../../protos/perfetto/trace/ftrace:zero",
- "../base",
- "db:lib",
- "metrics:lib",
- "sqlite",
- "tables",
- ]
- public_deps = [
- "../../include/perfetto/trace_processor",
- ]
- if (enable_perfetto_trace_processor_json) {
- deps += [ ":export_json" ]
- }
-}
-
-perfetto_host_executable("trace_processor_shell") {
- deps = [
- ":lib",
- "../../gn:default_deps",
- "../../gn:protoc_lib",
- "../../src/profiling/symbolizer",
- "../../src/profiling/symbolizer:symbolize_database",
- "../base",
- "metrics:lib",
- ]
- if (enable_perfetto_version_gen) {
- deps += [ "../../gn/standalone:gen_git_revision" ]
- }
- if (enable_perfetto_trace_processor_linenoise) {
- deps += [ "../../gn:linenoise" ]
- }
- if (enable_perfetto_trace_processor_httpd) {
- deps += [ "rpc:httpd" ]
- }
- sources = [
- "proto_to_json.cc",
- "proto_to_json.h",
- "trace_processor_shell.cc",
- ]
-}
+} # if (enable_perfetto_trace_processor_sqlite)
perfetto_unittest_source_set("unittests") {
testonly = true
sources = [
- "args_table_unittest.cc",
"clock_tracker_unittest.cc",
"event_tracker_unittest.cc",
- "filtered_row_index_unittest.cc",
"forwarding_trace_parser_unittest.cc",
"ftrace_utils_unittest.cc",
"heap_profile_tracker_unittest.cc",
"importers/proto/args_table_utils_unittest.cc",
+ "importers/proto/heap_graph_tracker_unittest.cc",
"importers/proto/heap_graph_walker_unittest.cc",
"importers/proto/proto_trace_parser_unittest.cc",
"importers/systrace/systrace_parser_unittest.cc",
- "process_table_unittest.cc",
"process_tracker_unittest.cc",
"protozero_to_text_unittests.cc",
"sched_slice_table_unittest.cc",
"slice_tracker_unittest.cc",
- "span_join_operator_table_unittest.cc",
"syscall_tracker_unittest.cc",
- "thread_table_unittest.cc",
"trace_sorter_unittest.cc",
]
deps = [
":descriptors",
- ":lib",
":protozero_to_text",
":storage_full",
"../../gn:default_deps",
"../../gn:gtest_and_gmock",
- "../../gn:sqlite",
"../../protos/perfetto/common:zero",
"../../protos/perfetto/trace:minimal_zero",
"../../protos/perfetto/trace:zero",
@@ -414,11 +405,22 @@
"../protozero:testing_messages_zero",
"containers:unittests",
"db:unittests",
- "sqlite",
- "sqlite:unittests",
"tables:unittests",
]
+ if (enable_perfetto_trace_processor_sqlite) {
+ sources += [
+ "filtered_row_index_unittest.cc",
+ "span_join_operator_table_unittest.cc",
+ ]
+ deps += [
+ ":lib",
+ "../../gn:sqlite",
+ "sqlite",
+ "sqlite:unittests",
+ ]
+ }
+
if (enable_perfetto_trace_processor_json) {
if (enable_perfetto_trace_processor_json_import) {
sources += [
@@ -445,30 +447,29 @@
source_set("integrationtests") {
testonly = true
- sources = [
- "trace_database_integrationtest.cc",
- ]
- deps = [
- ":lib",
- ":storage_full",
- "../../gn:default_deps",
- "../../gn:gtest_and_gmock",
- "../base",
- "../base:test_support",
- "sqlite",
- ]
-
- if (enable_perfetto_trace_processor_json_import) {
- deps += [ "../../gn:jsoncpp" ]
+ sources = []
+ deps = []
+ if (enable_perfetto_trace_processor_sqlite) {
+ sources += [ "trace_database_integrationtest.cc" ]
+ deps += [
+ ":lib",
+ ":storage_full",
+ "../../gn:default_deps",
+ "../../gn:gtest_and_gmock",
+ "../base",
+ "../base:test_support",
+ "sqlite",
+ ]
+ if (enable_perfetto_trace_processor_json_import) {
+ deps += [ "../../gn:jsoncpp" ]
+ }
}
}
if (enable_perfetto_trace_processor_json) {
source_set("storage_minimal_smoke_tests") {
testonly = true
- sources = [
- "storage_minimal_smoke_test.cc",
- ]
+ sources = [ "storage_minimal_smoke_test.cc" ]
deps = [
":export_json",
":storage_minimal",
@@ -483,9 +484,7 @@
perfetto_fuzzer_test("trace_processor_fuzzer") {
testonly = true
- sources = [
- "trace_parsing_fuzzer.cc",
- ]
+ sources = [ "trace_parsing_fuzzer.cc" ]
deps = [
":storage_full",
"../../gn:default_deps",
diff --git a/src/trace_processor/args_table.cc b/src/trace_processor/args_table.cc
deleted file mode 100644
index 64b407c..0000000
--- a/src/trace_processor/args_table.cc
+++ /dev/null
@@ -1,265 +0,0 @@
-/*
- * Copyright (C) 2018 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.
- */
-
-#include "src/trace_processor/args_table.h"
-
-#include "src/trace_processor/sqlite/sqlite_utils.h"
-
-namespace perfetto {
-namespace trace_processor {
-
-namespace {
-PERFETTO_ALWAYS_INLINE
-bool TreatedAsInteger(Variadic v) {
- return v.type == Variadic::Type::kInt || v.type == Variadic::Type::kBool ||
- v.type == Variadic::Type::kPointer || v.type == Variadic::Type::kUint;
-}
-
-PERFETTO_ALWAYS_INLINE
-bool TreatedAsString(Variadic v) {
- return v.type == Variadic::Type::kString || v.type == Variadic::Type::kJson;
-}
-
-PERFETTO_ALWAYS_INLINE
-int64_t AsInt64(Variadic v) {
- if (v.type == Variadic::Type::kInt)
- return v.int_value;
- if (v.type == Variadic::Type::kBool)
- return static_cast<int64_t>(v.bool_value);
- if (v.type == Variadic::Type::kUint)
- return static_cast<int64_t>(v.uint_value);
- if (v.type == Variadic::Type::kPointer)
- return static_cast<int64_t>(v.pointer_value);
- PERFETTO_FATAL("invalid Variadic type");
-}
-
-PERFETTO_ALWAYS_INLINE
-StringId AsStringId(Variadic v) {
- if (v.type == Variadic::Type::kString)
- return v.string_value;
- if (v.type == Variadic::Type::kJson)
- return v.json_value;
- PERFETTO_FATAL("invalid Variadic type");
-}
-} // namespace
-
-ArgsTable::ArgsTable(sqlite3*, const TraceStorage* storage)
- : storage_(storage) {}
-
-void ArgsTable::RegisterTable(sqlite3* db, const TraceStorage* storage) {
- SqliteTable::Register<ArgsTable>(db, storage, "args");
-}
-
-StorageSchema ArgsTable::CreateStorageSchema() {
- const auto& args = storage_->args();
- return StorageSchema::Builder()
- .AddOrderedNumericColumn("arg_set_id", &args.set_ids())
- .AddStringColumn("flat_key", &args.flat_keys(), &storage_->string_pool())
- .AddStringColumn("key", &args.keys(), &storage_->string_pool())
- .AddColumn<ValueColumn>("int_value", Variadic::Type::kInt, storage_)
- .AddColumn<ValueColumn>("string_value", Variadic::Type::kString, storage_)
- .AddColumn<ValueColumn>("real_value", Variadic::Type::kReal, storage_)
- .Build({"arg_set_id", "key"});
-}
-
-uint32_t ArgsTable::RowCount() {
- return static_cast<uint32_t>(storage_->args().args_count());
-}
-
-int ArgsTable::BestIndex(const QueryConstraints& qc, BestIndexInfo* info) {
- if (HasEqConstraint(qc, "arg_set_id")) {
- info->estimated_cost = 1;
- } else {
- info->estimated_cost = static_cast<uint32_t>(storage_->args().args_count());
- }
- return SQLITE_OK;
-}
-
-ArgsTable::ValueColumn::ValueColumn(std::string col_name,
- Variadic::Type type,
- const TraceStorage* storage)
- : StorageColumn(col_name, false /* hidden */),
- type_(type),
- storage_(storage) {
- PERFETTO_CHECK(type == Variadic::Type::kInt ||
- type == Variadic::Type::kReal ||
- type == Variadic::Type::kString);
-}
-
-void ArgsTable::ValueColumn::ReportResult(sqlite3_context* ctx,
- uint32_t row) const {
- const auto& value = storage_->args().arg_values()[row];
- switch (type_) {
- // Integer column, returns all integer-like variadic values (as an int64_t).
- case Variadic::Type::kInt: {
- if (!TreatedAsInteger(value)) {
- sqlite3_result_null(ctx);
- return;
- }
- sqlite_utils::ReportSqliteResult(ctx, AsInt64(value));
- return;
- }
-
- // Float column, returns only float values.
- case Variadic::Type::kReal: {
- if (value.type != Variadic::Type::kReal) {
- sqlite3_result_null(ctx);
- return;
- }
- sqlite_utils::ReportSqliteResult(ctx, value.real_value);
- return;
- }
-
- // String column, returns string & json variadic values (as a string).
- case Variadic::Type::kString: {
- if (!TreatedAsString(value)) {
- sqlite3_result_null(ctx);
- return;
- }
- const char* str = storage_->GetString(AsStringId(value)).c_str();
- sqlite3_result_text(ctx, str, -1, sqlite_utils::kSqliteStatic);
- return;
- }
-
- case Variadic::Type::kBool:
- case Variadic::Type::kUint:
- case Variadic::Type::kPointer:
- case Variadic::Type::kJson:
- PERFETTO_FATAL("Unexpected column type");
- }
-}
-
-ArgsTable::ValueColumn::Bounds ArgsTable::ValueColumn::BoundFilter(
- int,
- sqlite3_value*) const {
- return Bounds{};
-}
-
-void ArgsTable::ValueColumn::Filter(int op,
- sqlite3_value* value,
- FilteredRowIndex* index) const {
- switch (type_) {
- // Integer column, returns all integer-like variadic values (as an int64_t).
- case Variadic::Type::kInt: {
- bool op_is_null = sqlite_utils::IsOpIsNull(op);
- auto predicate = sqlite_utils::CreateNumericPredicate<int64_t>(op, value);
- index->FilterRows(
- [this, predicate, op_is_null](uint32_t row) PERFETTO_ALWAYS_INLINE {
- const Variadic& arg = storage_->args().arg_values()[row];
- if (!TreatedAsInteger(arg)) {
- return op_is_null;
- }
- return predicate(AsInt64(arg));
- });
- break;
- }
-
- // Float column, returns only float values.
- case Variadic::Type::kReal: {
- bool op_is_null = sqlite_utils::IsOpIsNull(op);
- auto predicate = sqlite_utils::CreateNumericPredicate<double>(op, value);
- index->FilterRows(
- [this, predicate, op_is_null](uint32_t row) PERFETTO_ALWAYS_INLINE {
- const auto& arg = storage_->args().arg_values()[row];
- return arg.type == Variadic::Type::kReal ? predicate(arg.real_value)
- : op_is_null;
- });
- break;
- }
-
- // String column, returns string & json variadic values (as a string).
- case Variadic::Type::kString: {
- auto predicate = sqlite_utils::CreateStringPredicate(op, value);
- index->FilterRows(
- [this, &predicate](uint32_t row) PERFETTO_ALWAYS_INLINE {
- const auto& arg = storage_->args().arg_values()[row];
- if (!TreatedAsString(arg)) {
- return predicate(nullptr);
- }
- return predicate(storage_->GetString(AsStringId(arg)).c_str());
- });
- break;
- }
- case Variadic::Type::kBool:
- case Variadic::Type::kUint:
- case Variadic::Type::kPointer:
- case Variadic::Type::kJson:
- PERFETTO_FATAL("Unexpected column type");
- }
-}
-
-ArgsTable::ValueColumn::Comparator ArgsTable::ValueColumn::Sort(
- const QueryConstraints::OrderBy& ob) const {
- if (ob.desc) {
- return [this](uint32_t f, uint32_t s) { return -CompareRefsAsc(f, s); };
- }
- return [this](uint32_t f, uint32_t s) { return CompareRefsAsc(f, s); };
-}
-
-int ArgsTable::ValueColumn::CompareRefsAsc(uint32_t f, uint32_t s) const {
- const auto& arg_f = storage_->args().arg_values()[f];
- const auto& arg_s = storage_->args().arg_values()[s];
- switch (type_) {
- // Integer column, returns all integer-like variadic values (as an int64_t).
- case Variadic::Type::kInt: {
- if (TreatedAsInteger(arg_f) && TreatedAsInteger(arg_s)) {
- return sqlite_utils::CompareValuesAsc(AsInt64(arg_f), AsInt64(arg_s));
- } else if (TreatedAsInteger(arg_f)) {
- return 1; // second value treated as null
- } else if (TreatedAsInteger(arg_s)) {
- return -1; // first value treated as null
- }
- return 0;
- }
-
- // Float column, returns only float values.
- case Variadic::Type::kReal: {
- if (arg_f.type == Variadic::Type::kReal &&
- arg_s.type == Variadic::Type::kReal) {
- return sqlite_utils::CompareValuesAsc(arg_f.real_value,
- arg_s.real_value);
- } else if (arg_f.type == Variadic::Type::kReal) {
- return 1; // second value treated as null
- } else if (arg_s.type == Variadic::Type::kReal) {
- return -1; // first value treated as null
- }
- return 0;
- }
-
- // String column, returns string & json variadic values (as a string).
- case Variadic::Type::kString: {
- if (TreatedAsString(arg_f) && TreatedAsString(arg_s)) {
- const auto& f_str = storage_->GetString(AsStringId(arg_f));
- const auto& s_str = storage_->GetString(AsStringId(arg_s));
- return sqlite_utils::CompareValuesAsc(f_str, s_str);
- } else if (TreatedAsString(arg_f)) {
- return 1; // second value treated as null
- } else if (TreatedAsString(arg_s)) {
- return -1; // first value treated as null
- }
- return 0;
- }
- case Variadic::Type::kBool:
- case Variadic::Type::kUint:
- case Variadic::Type::kPointer:
- case Variadic::Type::kJson:
- PERFETTO_FATAL("Unexpected column type");
- }
- PERFETTO_FATAL("Never reached"); // for gcc
-}
-
-} // namespace trace_processor
-} // namespace perfetto
diff --git a/src/trace_processor/args_table.h b/src/trace_processor/args_table.h
deleted file mode 100644
index 8243457..0000000
--- a/src/trace_processor/args_table.h
+++ /dev/null
@@ -1,84 +0,0 @@
-/*
- * Copyright (C) 2018 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.
- */
-
-#ifndef SRC_TRACE_PROCESSOR_ARGS_TABLE_H_
-#define SRC_TRACE_PROCESSOR_ARGS_TABLE_H_
-
-#include "src/trace_processor/storage_table.h"
-#include "src/trace_processor/trace_storage.h"
-#include "src/trace_processor/variadic.h"
-
-namespace perfetto {
-namespace trace_processor {
-
-class ArgsTable : public StorageTable {
- public:
- static void RegisterTable(sqlite3* db, const TraceStorage* storage);
-
- ArgsTable(sqlite3*, const TraceStorage*);
-
- // StorageTable implementation.
- StorageSchema CreateStorageSchema() override;
- uint32_t RowCount() override;
- int BestIndex(const QueryConstraints&, BestIndexInfo*) override;
-
- private:
- class ValueColumn final : public StorageColumn {
- public:
- ValueColumn(std::string col_name,
- Variadic::Type type,
- const TraceStorage* storage);
-
- void ReportResult(sqlite3_context* ctx, uint32_t row) const override;
-
- Bounds BoundFilter(int op, sqlite3_value* sqlite_val) const override;
-
- void Filter(int op, sqlite3_value* value, FilteredRowIndex*) const override;
-
- Comparator Sort(const QueryConstraints::OrderBy& ob) const override;
-
- bool HasOrdering() const override { return false; }
-
- SqlValue::Type GetType() const override {
- switch (type_) {
- case Variadic::Type::kInt:
- case Variadic::Type::kUint:
- case Variadic::Type::kPointer:
- case Variadic::Type::kBool:
- return SqlValue::Type::kLong;
- case Variadic::Type::kJson:
- case Variadic::Type::kString:
- return SqlValue::Type::kString;
- case Variadic::Type::kReal:
- return SqlValue::Type::kDouble;
- }
- PERFETTO_FATAL("Not reached"); // For gcc
- }
-
- private:
- int CompareRefsAsc(uint32_t f, uint32_t s) const;
-
- Variadic::Type type_;
- const TraceStorage* storage_ = nullptr;
- };
-
- const TraceStorage* const storage_;
-};
-
-} // namespace trace_processor
-} // namespace perfetto
-
-#endif // SRC_TRACE_PROCESSOR_ARGS_TABLE_H_
diff --git a/src/trace_processor/args_table_unittest.cc b/src/trace_processor/args_table_unittest.cc
deleted file mode 100644
index de6bec7..0000000
--- a/src/trace_processor/args_table_unittest.cc
+++ /dev/null
@@ -1,313 +0,0 @@
-/*
- * Copyright (C) 2018 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.
- */
-
-#include "src/trace_processor/args_table.h"
-#include "src/trace_processor/sqlite/scoped_db.h"
-#include "src/trace_processor/trace_processor_context.h"
-#include "src/trace_processor/trace_storage.h"
-#include "test/gtest_and_gmock.h"
-
-namespace perfetto {
-namespace trace_processor {
-namespace {
-
-class ArgsTableUnittest : public ::testing::Test {
- public:
- ArgsTableUnittest() {
- sqlite3* db = nullptr;
- PERFETTO_CHECK(sqlite3_initialize() == SQLITE_OK);
- PERFETTO_CHECK(sqlite3_open(":memory:", &db) == SQLITE_OK);
- db_.reset(db);
-
- context_.storage.reset(new TraceStorage());
- ArgsTable::RegisterTable(db_.get(), context_.storage.get());
- }
-
- void PrepareValidStatement(const std::string& sql) {
- int size = static_cast<int>(sql.size());
- sqlite3_stmt* stmt;
- ASSERT_EQ(sqlite3_prepare_v2(*db_, sql.c_str(), size, &stmt, nullptr),
- SQLITE_OK);
- stmt_.reset(stmt);
- }
-
- const char* GetColumnAsText(int colId) {
- return reinterpret_cast<const char*>(sqlite3_column_text(*stmt_, colId));
- }
-
- void AssertArgRowValues(int arg_set_id,
- const char* flat_key,
- const char* key,
- base::Optional<int64_t> int_value,
- base::Optional<const char*> string_value,
- base::Optional<double> real_value);
-
- protected:
- TraceProcessorContext context_;
- ScopedDb db_;
- ScopedStmt stmt_;
-};
-
-// Test helper.
-void ArgsTableUnittest::AssertArgRowValues(
- int arg_set_id,
- const char* flat_key,
- const char* key,
- base::Optional<int64_t> int_value,
- base::Optional<const char*> string_value,
- base::Optional<double> real_value) {
- ASSERT_EQ(sqlite3_column_int(*stmt_, 0), arg_set_id);
- ASSERT_STREQ(GetColumnAsText(1), flat_key);
- ASSERT_STREQ(GetColumnAsText(2), key);
- if (int_value.has_value()) {
- ASSERT_EQ(sqlite3_column_int64(*stmt_, 3), int_value.value());
- } else {
- ASSERT_EQ(sqlite3_column_type(*stmt_, 3), SQLITE_NULL);
- }
- if (string_value.has_value()) {
- ASSERT_STREQ(GetColumnAsText(4), string_value.value());
- } else {
- ASSERT_EQ(sqlite3_column_type(*stmt_, 4), SQLITE_NULL);
- }
- if (real_value.has_value()) {
- ASSERT_DOUBLE_EQ(sqlite3_column_double(*stmt_, 5), real_value.value());
- } else {
- ASSERT_EQ(sqlite3_column_type(*stmt_, 5), SQLITE_NULL);
- }
-}
-
-TEST_F(ArgsTableUnittest, IntValue) {
- static const char kFlatKey[] = "flat_key";
- static const char kKey[] = "key";
- static const int kValue = 123;
-
- TraceStorage::Args::Arg arg;
- arg.flat_key = context_.storage->InternString(kFlatKey);
- arg.key = context_.storage->InternString(kKey);
- arg.value = Variadic::Integer(kValue);
-
- context_.storage->mutable_args()->AddArgSet({arg}, 0, 1);
-
- PrepareValidStatement("SELECT * FROM args");
-
- ASSERT_EQ(sqlite3_step(*stmt_), SQLITE_ROW);
- AssertArgRowValues(1, kFlatKey, kKey, kValue, base::nullopt, base::nullopt);
- ASSERT_EQ(sqlite3_step(*stmt_), SQLITE_DONE);
-}
-
-TEST_F(ArgsTableUnittest, StringValue) {
- static const char kFlatKey[] = "flat_key";
- static const char kKey[] = "key";
- static const char kValue[] = "123";
-
- TraceStorage::Args::Arg arg;
- arg.flat_key = context_.storage->InternString(kFlatKey);
- arg.key = context_.storage->InternString(kKey);
- arg.value = Variadic::String(context_.storage->InternString(kValue));
-
- context_.storage->mutable_args()->AddArgSet({arg}, 0, 1);
-
- PrepareValidStatement("SELECT * FROM args");
-
- ASSERT_EQ(sqlite3_step(*stmt_), SQLITE_ROW);
- AssertArgRowValues(1, kFlatKey, kKey, base::nullopt, kValue, base::nullopt);
- ASSERT_EQ(sqlite3_step(*stmt_), SQLITE_DONE);
-}
-
-TEST_F(ArgsTableUnittest, RealValue) {
- static const char kFlatKey[] = "flat_key";
- static const char kKey[] = "key";
- static const double kValue = 0.123;
-
- TraceStorage::Args::Arg arg;
- arg.flat_key = context_.storage->InternString(kFlatKey);
- arg.key = context_.storage->InternString(kKey);
- arg.value = Variadic::Real(kValue);
-
- context_.storage->mutable_args()->AddArgSet({arg}, 0, 1);
-
- PrepareValidStatement("SELECT * FROM args");
-
- ASSERT_EQ(sqlite3_step(*stmt_), SQLITE_ROW);
- AssertArgRowValues(1, kFlatKey, kKey, base::nullopt, base::nullopt, kValue);
- ASSERT_EQ(sqlite3_step(*stmt_), SQLITE_DONE);
-}
-
-TEST_F(ArgsTableUnittest, BoolValueTreatedAsInt) {
- static const char kFlatKey[] = "flat_key";
- static const char kKey[] = "key";
- static const bool kValue = true;
-
- TraceStorage::Args::Arg arg;
- arg.flat_key = context_.storage->InternString(kFlatKey);
- arg.key = context_.storage->InternString(kKey);
- arg.value = Variadic::Boolean(kValue);
-
- context_.storage->mutable_args()->AddArgSet({arg}, 0, 1);
-
- // Boolean returned in the "int_value" column, and is comparable to an integer
- // literal.
- PrepareValidStatement("SELECT * FROM args WHERE int_value = 1");
- ASSERT_EQ(sqlite3_step(*stmt_), SQLITE_ROW);
- AssertArgRowValues(1, kFlatKey, kKey, kValue, base::nullopt, base::nullopt);
- ASSERT_EQ(sqlite3_step(*stmt_), SQLITE_DONE);
-}
-
-TEST_F(ArgsTableUnittest, PointerValueTreatedAsInt) {
- static const uint64_t kSmallValue = 1ull << 30;
- static const uint64_t kTopBitSetValue = 1ull << 63;
-
- TraceStorage::Args::Arg arg;
- arg.flat_key = context_.storage->InternString("flat_key_small");
- arg.key = context_.storage->InternString("key_small");
- arg.value = Variadic::Pointer(kSmallValue);
-
- TraceStorage::Args::Arg arg2;
- arg2.flat_key = context_.storage->InternString("flat_key_large");
- arg2.key = context_.storage->InternString("key_large");
- arg2.value = Variadic::Pointer(kTopBitSetValue);
-
- context_.storage->mutable_args()->AddArgSet({arg, arg2}, 0, 2);
-
- // Pointer returned in the "int_value" column, as a signed 64 bit. And is
- // comparable to an integer literal.
-
- static const int64_t kExpectedSmallValue = static_cast<int64_t>(kSmallValue);
- PrepareValidStatement(std::string("SELECT * FROM args WHERE int_value = ") +
- std::to_string(kExpectedSmallValue));
- ASSERT_EQ(sqlite3_step(*stmt_), SQLITE_ROW);
- AssertArgRowValues(1, "flat_key_small", "key_small", kExpectedSmallValue,
- base::nullopt, base::nullopt);
- ASSERT_EQ(sqlite3_step(*stmt_), SQLITE_DONE);
-
- static const int64_t kExpectedTopBitSetValue =
- static_cast<int64_t>(kTopBitSetValue); // negative
- PrepareValidStatement(std::string("SELECT * FROM args WHERE int_value = ") +
- std::to_string(kExpectedTopBitSetValue));
- ASSERT_EQ(sqlite3_step(*stmt_), SQLITE_ROW);
- AssertArgRowValues(1, "flat_key_large", "key_large", kExpectedTopBitSetValue,
- base::nullopt, base::nullopt);
- ASSERT_EQ(sqlite3_step(*stmt_), SQLITE_DONE);
-}
-
-TEST_F(ArgsTableUnittest, UintValueTreatedAsInt) {
- static const uint64_t kSmallValue = 1ull << 30;
- static const uint64_t kTopBitSetValue = 1ull << 63;
-
- TraceStorage::Args::Arg arg;
- arg.flat_key = context_.storage->InternString("flat_key_small");
- arg.key = context_.storage->InternString("key_small");
- arg.value = Variadic::UnsignedInteger(kSmallValue);
-
- TraceStorage::Args::Arg arg2;
- arg2.flat_key = context_.storage->InternString("flat_key_large");
- arg2.key = context_.storage->InternString("key_large");
- arg2.value = Variadic::UnsignedInteger(kTopBitSetValue);
-
- context_.storage->mutable_args()->AddArgSet({arg, arg2}, 0, 2);
-
- // Unsigned returned in the "int_value" column, as a signed 64 bit. And is
- // comparable to an integer literal.
-
- static const int64_t kExpectedSmallValue = static_cast<int64_t>(kSmallValue);
- PrepareValidStatement(std::string("SELECT * FROM args WHERE int_value = ") +
- std::to_string(kExpectedSmallValue));
- ASSERT_EQ(sqlite3_step(*stmt_), SQLITE_ROW);
- AssertArgRowValues(1, "flat_key_small", "key_small", kExpectedSmallValue,
- base::nullopt, base::nullopt);
- ASSERT_EQ(sqlite3_step(*stmt_), SQLITE_DONE);
-
- static const int64_t kExpectedTopBitSetValue =
- static_cast<int64_t>(kTopBitSetValue); // negative
- PrepareValidStatement(std::string("SELECT * FROM args WHERE int_value = ") +
- std::to_string(kExpectedTopBitSetValue));
- ASSERT_EQ(sqlite3_step(*stmt_), SQLITE_ROW);
- AssertArgRowValues(1, "flat_key_large", "key_large", kExpectedTopBitSetValue,
- base::nullopt, base::nullopt);
- ASSERT_EQ(sqlite3_step(*stmt_), SQLITE_DONE);
-}
-
-TEST_F(ArgsTableUnittest, IntegerLikeValuesSortByIntRepresentation) {
- static const char kFlatKey[] = "flat_key";
- static const char kKey[] = "key";
-
- TraceStorage::Args::Arg bool_arg_true;
- bool_arg_true.flat_key = context_.storage->InternString(kFlatKey);
- bool_arg_true.key = context_.storage->InternString(kKey);
- bool_arg_true.value = Variadic::Boolean(true);
-
- TraceStorage::Args::Arg bool_arg_false;
- bool_arg_false.flat_key = context_.storage->InternString(kFlatKey);
- bool_arg_false.key = context_.storage->InternString(kKey);
- bool_arg_false.value = Variadic::Boolean(false);
-
- TraceStorage::Args::Arg pointer_arg_42;
- pointer_arg_42.flat_key = context_.storage->InternString(kFlatKey);
- pointer_arg_42.key = context_.storage->InternString(kKey);
- pointer_arg_42.value = Variadic::Pointer(42);
-
- TraceStorage::Args::Arg unsigned_arg_10;
- unsigned_arg_10.flat_key = context_.storage->InternString(kFlatKey);
- unsigned_arg_10.key = context_.storage->InternString(kKey);
- unsigned_arg_10.value = Variadic::UnsignedInteger(10);
-
- // treated as null by the int_value column
- TraceStorage::Args::Arg string_arg;
- string_arg.flat_key = context_.storage->InternString(kFlatKey);
- string_arg.key = context_.storage->InternString(kKey);
- string_arg.value =
- Variadic::String(context_.storage->InternString("string_content"));
-
- context_.storage->mutable_args()->AddArgSet(
- {bool_arg_true, bool_arg_false, pointer_arg_42, unsigned_arg_10,
- string_arg},
- 0, 5);
-
- // Ascending sort by int representations:
- // { null (string), 0 (false), 1 (true), 10, 42 }
- PrepareValidStatement("SELECT * FROM args ORDER BY int_value ASC");
- ASSERT_EQ(sqlite3_step(*stmt_), SQLITE_ROW);
- AssertArgRowValues(1, kFlatKey, kKey, base::nullopt, "string_content",
- base::nullopt);
- ASSERT_EQ(sqlite3_step(*stmt_), SQLITE_ROW);
- AssertArgRowValues(1, kFlatKey, kKey, 0, base::nullopt, base::nullopt);
- ASSERT_EQ(sqlite3_step(*stmt_), SQLITE_ROW);
- AssertArgRowValues(1, kFlatKey, kKey, 1, base::nullopt, base::nullopt);
- ASSERT_EQ(sqlite3_step(*stmt_), SQLITE_ROW);
- AssertArgRowValues(1, kFlatKey, kKey, 10, base::nullopt, base::nullopt);
- ASSERT_EQ(sqlite3_step(*stmt_), SQLITE_ROW);
- AssertArgRowValues(1, kFlatKey, kKey, 42, base::nullopt, base::nullopt);
- ASSERT_EQ(sqlite3_step(*stmt_), SQLITE_DONE);
-
- // Desceding order.
- PrepareValidStatement("SELECT * FROM args ORDER BY int_value DESC");
- ASSERT_EQ(sqlite3_step(*stmt_), SQLITE_ROW);
- AssertArgRowValues(1, kFlatKey, kKey, 42, base::nullopt, base::nullopt);
- ASSERT_EQ(sqlite3_step(*stmt_), SQLITE_ROW);
- AssertArgRowValues(1, kFlatKey, kKey, 10, base::nullopt, base::nullopt);
- ASSERT_EQ(sqlite3_step(*stmt_), SQLITE_ROW);
- AssertArgRowValues(1, kFlatKey, kKey, 1, base::nullopt, base::nullopt);
- ASSERT_EQ(sqlite3_step(*stmt_), SQLITE_ROW);
- AssertArgRowValues(1, kFlatKey, kKey, 0, base::nullopt, base::nullopt);
- ASSERT_EQ(sqlite3_step(*stmt_), SQLITE_ROW);
- AssertArgRowValues(1, kFlatKey, kKey, base::nullopt, "string_content",
- base::nullopt);
- ASSERT_EQ(sqlite3_step(*stmt_), SQLITE_DONE);
-}
-
-} // namespace
-} // namespace trace_processor
-} // namespace perfetto
diff --git a/src/trace_processor/args_tracker.cc b/src/trace_processor/args_tracker.cc
index 4f143c5..a0114ce 100644
--- a/src/trace_processor/args_tracker.cc
+++ b/src/trace_processor/args_tracker.cc
@@ -27,7 +27,7 @@
Flush();
}
-void ArgsTracker::AddArg(TableId table,
+void ArgsTracker::AddArg(Column* arg_set_id,
uint32_t row,
StringId flat_key,
StringId key,
@@ -35,7 +35,7 @@
args_.emplace_back();
auto* rid_arg = &args_.back();
- rid_arg->table = table;
+ rid_arg->column = arg_set_id;
rid_arg->row = row;
rid_arg->flat_key = flat_key;
rid_arg->key = key;
@@ -43,7 +43,7 @@
}
void ArgsTracker::Flush() {
- using Arg = TraceStorage::Args::Arg;
+ using Arg = GlobalArgsTracker::Arg;
if (args_.empty())
return;
@@ -51,63 +51,42 @@
// We sort here because a single packet may add multiple args with different
// rowids.
auto comparator = [](const Arg& f, const Arg& s) {
- return f.table < s.table && f.row < s.row;
+ // We only care that all args for a specific arg set appear in a contiguous
+ // block, but not about the relative order of one block to another. The
+ // simplest way to achieve that is to sort by table column pointer & row,
+ // which identify the arg set.
+ return f.column < s.column && f.row < s.row;
};
std::stable_sort(args_.begin(), args_.end(), comparator);
- auto* storage = context_->storage.get();
for (uint32_t i = 0; i < args_.size();) {
const auto& arg = args_[i];
- auto table_id = arg.table;
+ Column* column = arg.column;
auto row = arg.row;
uint32_t next_rid_idx = i + 1;
while (next_rid_idx < args_.size() &&
- table_id == args_[next_rid_idx].table &&
+ column == args_[next_rid_idx].column &&
row == args_[next_rid_idx].row) {
next_rid_idx++;
}
ArgSetId set_id =
- storage->mutable_args()->AddArgSet(args_, i, next_rid_idx);
- switch (table_id) {
- case TableId::kRawEvents:
- storage->mutable_raw_events()->set_arg_set_id(row, set_id);
- break;
- case TableId::kCounterValues:
- storage->mutable_counter_table()->mutable_arg_set_id()->Set(row,
- set_id);
- break;
- case TableId::kInstants:
- storage->mutable_instant_table()->mutable_arg_set_id()->Set(row,
- set_id);
- break;
- case TableId::kNestableSlices:
- storage->mutable_slice_table()->mutable_arg_set_id()->Set(row, set_id);
- break;
- // Special case: overwrites the metadata table row.
- case TableId::kMetadataTable:
- storage->mutable_metadata_table()->mutable_int_value()->Set(row,
- set_id);
- break;
- case TableId::kTrack:
- storage->mutable_track_table()->mutable_source_arg_set_id()->Set(
- row, set_id);
- break;
- case TableId::kVulkanMemoryAllocation:
- storage->mutable_vulkan_memory_allocations_table()
- ->mutable_arg_set_id()
- ->Set(row, set_id);
- break;
- case TableId::kInvalid:
- case TableId::kSched:
- PERFETTO_FATAL("Unsupported table to insert args into");
- }
+ context_->global_args_tracker->AddArgSet(args_, i, next_rid_idx);
+ column->Set(row, SqlValue::Long(set_id));
+
i = next_rid_idx;
}
args_.clear();
}
+ArgsTracker::BoundInserter::BoundInserter(ArgsTracker* args_tracker,
+ Column* arg_set_id_column,
+ uint32_t row)
+ : args_tracker_(args_tracker),
+ arg_set_id_column_(arg_set_id_column),
+ row_(row) {}
+
ArgsTracker::BoundInserter::~BoundInserter() {}
} // namespace trace_processor
diff --git a/src/trace_processor/args_tracker.h b/src/trace_processor/args_tracker.h
index 90062a8..9acccfb 100644
--- a/src/trace_processor/args_tracker.h
+++ b/src/trace_processor/args_tracker.h
@@ -17,9 +17,10 @@
#ifndef SRC_TRACE_PROCESSOR_ARGS_TRACKER_H_
#define SRC_TRACE_PROCESSOR_ARGS_TRACKER_H_
+#include "src/trace_processor/global_args_tracker.h"
#include "src/trace_processor/trace_processor_context.h"
#include "src/trace_processor/trace_storage.h"
-#include "src/trace_processor/variadic.h"
+#include "src/trace_processor/types/variadic.h"
namespace perfetto {
namespace trace_processor {
@@ -33,41 +34,86 @@
// args should be associated with.
class BoundInserter {
public:
- BoundInserter(ArgsTracker* args_tracker, TableId table, uint32_t row)
- : args_tracker_(args_tracker), table_(table), row_(row) {}
virtual ~BoundInserter();
// Adds an arg with the same key and flat_key.
- void AddArg(StringId key, Variadic v) { AddArg(key, key, v); }
-
- // Virtual for testing.
- virtual void AddArg(StringId flat_key, StringId key, Variadic v) {
- args_tracker_->AddArg(table_, row_, flat_key, key, v);
+ BoundInserter& AddArg(StringId key, Variadic v) {
+ return AddArg(key, key, v);
}
+ // Virtual for testing.
+ virtual BoundInserter& AddArg(StringId flat_key, StringId key, Variadic v) {
+ args_tracker_->AddArg(arg_set_id_column_, row_, flat_key, key, v);
+ return *this;
+ }
+
+ protected:
+ BoundInserter(ArgsTracker* args_tracker,
+ Column* arg_set_id_column,
+ uint32_t row);
+
private:
+ friend class ArgsTracker;
+
ArgsTracker* args_tracker_ = nullptr;
- TableId table_ = TableId::kInvalid;
+ Column* arg_set_id_column_ = nullptr;
uint32_t row_ = 0;
};
explicit ArgsTracker(TraceProcessorContext*);
virtual ~ArgsTracker();
- // Adds a arg for this row id with the given key and value.
- // Virtual for testing.
- virtual void AddArg(TableId table,
- uint32_t row,
- StringId flat_key,
- StringId key,
- Variadic);
+ BoundInserter AddArgsTo(RawId id) {
+ return AddArgsTo(context_->storage->mutable_raw_table(), id);
+ }
+
+ BoundInserter AddArgsTo(CounterId id) {
+ return AddArgsTo(context_->storage->mutable_counter_table(), id);
+ }
+
+ BoundInserter AddArgsTo(InstantId id) {
+ return AddArgsTo(context_->storage->mutable_instant_table(), id);
+ }
+
+ BoundInserter AddArgsTo(SliceId id) {
+ return AddArgsTo(context_->storage->mutable_slice_table(), id);
+ }
+
+ BoundInserter AddArgsTo(MetadataId id) {
+ auto* table = context_->storage->mutable_metadata_table();
+ uint32_t row = *table->id().IndexOf(id);
+ return BoundInserter(this, table->mutable_int_value(), row);
+ }
+
+ BoundInserter AddArgsTo(TrackId id) {
+ auto* table = context_->storage->mutable_track_table();
+ uint32_t row = *table->id().IndexOf(id);
+ return BoundInserter(this, table->mutable_source_arg_set_id(), row);
+ }
+
+ BoundInserter AddArgsTo(VulkanAllocId id) {
+ return AddArgsTo(
+ context_->storage->mutable_vulkan_memory_allocations_table(), id);
+ }
// Commits the added args to storage.
// Virtual for testing.
virtual void Flush();
private:
- std::vector<TraceStorage::Args::Arg> args_;
+ template <typename Table>
+ BoundInserter AddArgsTo(Table* table, typename Table::Id id) {
+ uint32_t row = *table->id().IndexOf(id);
+ return BoundInserter(this, table->mutable_arg_set_id(), row);
+ }
+
+ void AddArg(Column* arg_set_id,
+ uint32_t row,
+ StringId flat_key,
+ StringId key,
+ Variadic);
+
+ std::vector<GlobalArgsTracker::Arg> args_;
TraceProcessorContext* const context_;
};
diff --git a/src/trace_processor/clock_tracker.cc b/src/trace_processor/clock_tracker.cc
index 696a110..43a6819 100644
--- a/src/trace_processor/clock_tracker.cc
+++ b/src/trace_processor/clock_tracker.cc
@@ -41,6 +41,10 @@
void ClockTracker::AddSnapshot(const std::vector<ClockValue>& clocks) {
const auto snapshot_id = cur_snapshot_id_++;
+ // Clear the cache
+ static_assert(std::is_trivial<decltype(cache_)>::value, "must be trivial");
+ memset(&cache_[0], 0, sizeof(cache_));
+
// Compute the fingerprint of the snapshot by hashing all clock ids. This is
// used by the clock pathfinding logic.
base::Hash hasher;
@@ -192,25 +196,33 @@
return ClockPath(); // invalid path.
}
-base::Optional<int64_t> ClockTracker::Convert(ClockId src_clock_id,
- int64_t src_timestamp,
- ClockId target_clock_id) {
- // TODO(primiano): optimization: I bet A simple LRU cache of the form
- // (src_clock_id, target_clock_id, latest_timestamp, translation_ns) might
- // speed up most conversion allowing to skip FindPath and the iterations.
-
+base::Optional<int64_t> ClockTracker::ConvertSlowpath(ClockId src_clock_id,
+ int64_t src_timestamp,
+ ClockId target_clock_id) {
PERFETTO_DCHECK(!IsReservedSeqScopedClockId(src_clock_id));
PERFETTO_DCHECK(!IsReservedSeqScopedClockId(target_clock_id));
+ context_->storage->IncrementStats(stats::clock_sync_cache_miss);
+
ClockPath path = FindPath(src_clock_id, target_clock_id);
if (!path.valid()) {
context_->storage->IncrementStats(stats::clock_sync_failure);
return base::nullopt;
}
+ // We can cache only single-path resolutions between two clocks.
+ // Caching multi-path resolutions is harder because the (src,target) tuple
+ // is not enough as a cache key: at any step the |ns| value can yield to a
+ // different choice of the next snapshot. Multi-path resolutions don't seem
+ // too frequent these days, so we focus only on caching the more frequent
+ // one-step resolutions (typically from any clock to the trace clock).
+ const bool cacheable = path.len == 1;
+ CachedClockPath cache_entry{};
+
// Iterate trough the path found and translate timestamps onto the new clock
// domain on each step, until the target domain is reached.
- int64_t ns = GetClock(src_clock_id)->ToNs(src_timestamp);
+ ClockDomain* src_domain = GetClock(src_clock_id);
+ int64_t ns = src_domain->ToNs(src_timestamp);
for (uint32_t i = 0; i < path.len; ++i) {
const ClockGraphEdge edge = path.at(i);
ClockDomain* cur_clock = GetClock(std::get<0>(edge));
@@ -246,12 +258,33 @@
// The translated timestamp is the relative delta of the source timestamp
// from the closest snapshot found (ns - *it), plus the timestamp in
// the new clock domain for the same snapshot id.
- ns = (ns - *it) + next_timestamp_ns;
+ const int64_t adj = next_timestamp_ns - *it;
+ ns += adj;
+
+ // On the first iteration, keep track of the bounds for the cache entry.
+ // This will allow future Convert() calls to skip the pathfinder logic
+ // as long as the query stays within the bound.
+ if (cacheable) {
+ PERFETTO_DCHECK(i == 0);
+ const int64_t kInt64Min = std::numeric_limits<int64_t>::min();
+ const int64_t kInt64Max = std::numeric_limits<int64_t>::max();
+ cache_entry.min_ts_ns = it == ts_vec.begin() ? kInt64Min : *it;
+ auto ubound = it + 1;
+ cache_entry.max_ts_ns = ubound == ts_vec.end() ? kInt64Max : *ubound;
+ cache_entry.translation_ns = adj;
+ }
// The last clock in the path must be the target clock.
PERFETTO_DCHECK(i < path.len - 1 || std::get<1>(edge) == target_clock_id);
}
+ if (cacheable) {
+ cache_entry.src = src_clock_id;
+ cache_entry.src_domain = src_domain;
+ cache_entry.target = target_clock_id;
+ cache_[rnd_() % cache_.size()] = cache_entry;
+ }
+
return ns;
}
diff --git a/src/trace_processor/clock_tracker.h b/src/trace_processor/clock_tracker.h
index c261249..63fe8e1 100644
--- a/src/trace_processor/clock_tracker.h
+++ b/src/trace_processor/clock_tracker.h
@@ -21,6 +21,7 @@
#include <array>
#include <map>
+#include <random>
#include <set>
#include <vector>
@@ -154,9 +155,27 @@
// This is typically called by the code that reads the ClockSnapshot packet.
void AddSnapshot(const std::vector<ClockValue>&);
+ // Converts a timestamp between two clock domains. Tries to use the cache
+ // first (only for single-path resolutions), then falls back on path finding
+ // as described in the header.
base::Optional<int64_t> Convert(ClockId src_clock_id,
int64_t src_timestamp,
- ClockId target_clock_id);
+ ClockId target_clock_id) {
+ if (PERFETTO_LIKELY(!cache_lookups_disabled_for_testing_)) {
+ for (const auto& ce : cache_) {
+ if (ce.src != src_clock_id || ce.target != target_clock_id)
+ continue;
+ int64_t ns = ce.src_domain->ToNs(src_timestamp);
+ if (ns >= ce.min_ts_ns && ns < ce.max_ts_ns)
+ return ns + ce.translation_ns;
+ }
+ }
+ return ConvertSlowpath(src_clock_id, src_timestamp, target_clock_id);
+ }
+
+ base::Optional<int64_t> ConvertSlowpath(ClockId src_clock_id,
+ int64_t src_timestamp,
+ ClockId target_clock_id);
base::Optional<int64_t> ToTraceTime(ClockId clock_id, int64_t timestamp) {
if (clock_id == trace_time_clock_id_)
@@ -169,6 +188,10 @@
trace_time_clock_id_ = clock_id;
}
+ void set_cache_lookups_disabled_for_testing(bool v) {
+ cache_lookups_disabled_for_testing_ = v;
+ }
+
private:
using SnapshotHash = uint32_t;
@@ -245,6 +268,17 @@
}
};
+ // Holds data for cached entries. At the moment only single-path resolution
+ // are cached.
+ struct CachedClockPath {
+ ClockId src;
+ ClockId target;
+ ClockDomain* src_domain;
+ int64_t min_ts_ns;
+ int64_t max_ts_ns;
+ int64_t translation_ns;
+ };
+
ClockTracker(const ClockTracker&) = delete;
ClockTracker& operator=(const ClockTracker&) = delete;
@@ -261,6 +295,9 @@
std::map<ClockId, ClockDomain> clocks_;
std::set<ClockGraphEdge> graph_;
std::set<ClockId> non_monotonic_clocks_;
+ std::array<CachedClockPath, 2> cache_{};
+ bool cache_lookups_disabled_for_testing_ = false;
+ std::minstd_rand rnd_; // For cache eviction.
uint32_t cur_snapshot_id_ = 0;
};
diff --git a/src/trace_processor/clock_tracker_unittest.cc b/src/trace_processor/clock_tracker_unittest.cc
index e1628af..2fc8e59 100644
--- a/src/trace_processor/clock_tracker_unittest.cc
+++ b/src/trace_processor/clock_tracker_unittest.cc
@@ -16,6 +16,8 @@
#include "src/trace_processor/clock_tracker.h"
+#include <random>
+
#include "perfetto/ext/base/optional.h"
#include "src/trace_processor/trace_processor_context.h"
#include "src/trace_processor/trace_storage.h"
@@ -207,6 +209,55 @@
EXPECT_EQ(*ct_.ToTraceTime(c66_2, 4 /* abs 30 */), 129000);
}
+// Tests that the cache doesn't affect the results of Convert() in unexpected
+// ways.
+TEST_F(ClockTrackerTest, CacheDoesntAffectResults) {
+ std::minstd_rand rnd;
+ int last_mono = 0;
+ int last_boot = 0;
+ int last_raw = 0;
+ static const int increments[] = {1, 2, 10};
+ for (int i = 0; i < 1000; i++) {
+ last_mono += increments[rnd() % base::ArraySize(increments)];
+ last_boot += increments[rnd() % base::ArraySize(increments)];
+ ct_.AddSnapshot({{MONOTONIC, last_mono}, {BOOTTIME, last_boot}});
+
+ last_raw += increments[rnd() % base::ArraySize(increments)];
+ last_boot += increments[rnd() % base::ArraySize(increments)];
+ ct_.AddSnapshot({{MONOTONIC_RAW, last_raw}, {BOOTTIME, last_boot}});
+ }
+
+ for (int i = 0; i < 1000; i++) {
+ int64_t val = static_cast<int64_t>(rnd()) % 10000;
+ for (int j = 0; j < 5; j++) {
+ ClockTracker::ClockId src;
+ ClockTracker::ClockId tgt;
+ if (j == 0) {
+ std::tie(src, tgt) = std::make_tuple(MONOTONIC, BOOTTIME);
+ } else if (j == 1) {
+ std::tie(src, tgt) = std::make_tuple(MONOTONIC_RAW, BOOTTIME);
+ } else if (j == 2) {
+ std::tie(src, tgt) = std::make_tuple(BOOTTIME, MONOTONIC);
+ } else if (j == 3) {
+ std::tie(src, tgt) = std::make_tuple(BOOTTIME, MONOTONIC_RAW);
+ } else if (j == 4) {
+ std::tie(src, tgt) = std::make_tuple(MONOTONIC_RAW, MONOTONIC);
+ } else {
+ PERFETTO_FATAL("j out of bounds");
+ }
+ // It will still write the cache, just not lookup.
+ ct_.set_cache_lookups_disabled_for_testing(true);
+ auto not_cached = ct_.Convert(src, val, tgt);
+
+ // This should 100% hit the cache.
+ ct_.set_cache_lookups_disabled_for_testing(false);
+ auto cached = ct_.Convert(src, val, tgt);
+
+ ASSERT_EQ(not_cached, cached);
+ }
+ }
+}
+
} // namespace
} // namespace trace_processor
} // namespace perfetto
diff --git a/src/trace_processor/containers/bit_vector.cc b/src/trace_processor/containers/bit_vector.cc
index 0ec5bcc..a2308f3 100644
--- a/src/trace_processor/containers/bit_vector.cc
+++ b/src/trace_processor/containers/bit_vector.cc
@@ -54,19 +54,19 @@
return SetBitsIterator(this);
}
-void BitVector::UpdateSetBits(const BitVector& other) {
- PERFETTO_DCHECK(other.size() == GetNumBitsSet());
+void BitVector::UpdateSetBits(const BitVector& o) {
+ PERFETTO_DCHECK(o.size() <= GetNumBitsSet());
- // For each set bit in this bitvector, we lookup whether |other| has the
- // bit set. If not, we clear the bit.
+ // For each set bit in this bitvector, we lookup whether the bit in |other|
+ // at that index (if in bounds) is set. If not, we clear the bit.
for (auto it = IterateSetBits(); it; it.Next()) {
- if (!other.IsSet(it.ordinal()))
+ if (it.ordinal() >= o.size() || !o.IsSet(it.ordinal()))
it.Clear();
}
// After the loop, we should have precisely the same number of bits
// set as |other|.
- PERFETTO_DCHECK(GetNumBitsSet() == other.GetNumBitsSet());
+ PERFETTO_DCHECK(o.GetNumBitsSet() == GetNumBitsSet());
}
} // namespace trace_processor
diff --git a/src/trace_processor/containers/bit_vector.h b/src/trace_processor/containers/bit_vector.h
index 58b9e23..bfd8b4f 100644
--- a/src/trace_processor/containers/bit_vector.h
+++ b/src/trace_processor/containers/bit_vector.h
@@ -107,8 +107,8 @@
PERFETTO_DCHECK(it != counts_.begin());
// Go back one block to find the block which has the bit we are looking for.
- uint16_t block_idx =
- static_cast<uint16_t>(std::distance(counts_.begin(), it) - 1);
+ uint32_t block_idx =
+ static_cast<uint32_t>(std::distance(counts_.begin(), it) - 1);
// Figure out how many set bits forward we are looking inside the block
// by taking away the number of bits at the start of the block from n.
@@ -265,6 +265,42 @@
size_ = size;
}
+ // Creates a BitVector of size |end| with the bits between |start| and |end|
+ // filled by calling the filler function |f(index of bit)|.
+ //
+ // As an example, suppose Range(3, 7, [](x) { return x < 5 }). This would
+ // result in the following bitvector:
+ // [0 0 0 1 1 0 0 0]
+ template <typename Filler = bool(uint32_t)>
+ static BitVector Range(uint32_t start, uint32_t end, Filler f) {
+ // Compute the block index and bitvector index where we start and end
+ // working one block at a time.
+ uint32_t start_fast_block = BlockCeil(start);
+ uint32_t start_fast_idx = BlockToIndex(start_fast_block);
+ uint32_t end_fast_block = BlockFloor(end);
+ uint32_t end_fast_idx = BlockToIndex(end_fast_block);
+
+ // First, create the BitVector up to |start| then fill up to
+ // |start_fast_index| with values from the filler.
+ BitVector bv(start, false);
+ for (uint32_t i = start; i < start_fast_idx; ++i) {
+ bv.Append(f(i));
+ }
+
+ // At this point we can work one block at a time.
+ for (uint32_t i = start_fast_block; i < end_fast_block; ++i) {
+ bv.counts_.emplace_back(bv.GetNumBitsSet());
+ bv.blocks_.emplace_back(Block::FromFiller(bv.size_, f));
+ bv.size_ += Block::kBits;
+ }
+
+ // Add the last few elements to finish up to |end|.
+ for (uint32_t i = end_fast_idx; i < end; ++i) {
+ bv.Append(f(i));
+ }
+ return bv;
+ }
+
// Updates the ith set bit of this bitvector with the value of
// |other.IsSet(i)|.
//
@@ -296,6 +332,17 @@
// }
SetBitsIterator IterateSetBits() const;
+ // Returns the approximate cost (in bytes) of storing a bitvector with size
+ // |n|. This can be used to make decisions about whether using a BitVector is
+ // worthwhile.
+ // This cost should not be treated as exact - it just gives an indication of
+ // the memory needed.
+ static constexpr uint32_t ApproxBytesCost(uint32_t n) {
+ // The two main things making up a bitvector is the cost of the blocks of
+ // bits and the cost of the counts vector.
+ return BlockCeil(n) * Block::kBits + BlockCeil(n) * sizeof(uint32_t);
+ }
+
private:
friend class internal::BaseIterator;
friend class internal::AllBitsIterator;
@@ -325,15 +372,18 @@
// Returns whether the bit at the given index is set.
bool IsSet(uint32_t idx) const {
PERFETTO_DCHECK(idx < kBits);
- return (word >> idx) & 1ull;
+ return (word_ >> idx) & 1ull;
}
+ // Bitwise ors the given |mask| to the current value.
+ void Or(uint64_t mask) { word_ |= mask; }
+
// Sets the bit at the given index to true.
void Set(uint32_t idx) {
PERFETTO_DCHECK(idx < kBits);
// Or the value for the true shifted up to |idx| with the word.
- word |= 1ull << idx;
+ Or(1ull << idx);
}
// Sets the bit at the given index to false.
@@ -341,11 +391,11 @@
PERFETTO_DCHECK(idx < kBits);
// And the integer of all bits set apart from |idx| with the word.
- word &= ~(1ull << idx);
+ word_ &= ~(1ull << idx);
}
// Clears all the bits (i.e. sets the atom to zero).
- void ClearAll() { word = 0; }
+ void ClearAll() { word_ = 0; }
// Returns the index of the nth set bit.
// Undefined if |n| >= |GetNumBitsSet()|.
@@ -367,13 +417,13 @@
//
// The code below was taken from the paper
// http://vigna.di.unimi.it/ftp/papers/Broadword.pdf
- uint64_t s = word - ((word & 0xAAAAAAAAAAAAAAAA) >> 1);
+ uint64_t s = word_ - ((word_ & 0xAAAAAAAAAAAAAAAA) >> 1);
s = (s & 0x3333333333333333) + ((s >> 2) & 0x3333333333333333);
s = ((s + (s >> 4)) & 0x0F0F0F0F0F0F0F0F) * L8;
uint64_t b = (BwLessThan(s, n * L8) >> 7) * L8 >> 53 & ~7ull;
uint64_t l = n - ((s << 8) >> b & 0xFF);
- s = (BwGtZero(((word >> b & 0xFF) * L8) & 0x8040201008040201) >> 7) * L8;
+ s = (BwGtZero(((word_ >> b & 0xFF) * L8) & 0x8040201008040201) >> 7) * L8;
uint64_t ret = b + ((BwLessThan(s, l * L8) >> 7) * L8 >> 56);
@@ -384,7 +434,7 @@
uint32_t GetNumBitsSet() const {
// We use __builtin_popcountll here as it's available natively for the two
// targets we care most about (x64 and WASM).
- return static_cast<uint32_t>(__builtin_popcountll(word));
+ return static_cast<uint32_t>(__builtin_popcountll(word_));
}
// Returns the number of set bits up to and including the bit at |idx|.
@@ -400,13 +450,13 @@
// all bits after this point.
void ClearAfter(uint32_t idx) {
PERFETTO_DCHECK(idx < kBits);
- word = WordUntil(idx);
+ word_ = WordUntil(idx);
}
// Sets all bits between the bit at |start| and |end| (inclusive).
void Set(uint32_t start, uint32_t end) {
uint32_t diff = end - start;
- word |= (MaskAllBitsSetUntil(diff) << static_cast<uint64_t>(start));
+ word_ |= (MaskAllBitsSetUntil(diff) << static_cast<uint64_t>(start));
}
private:
@@ -447,7 +497,7 @@
uint64_t mask = MaskAllBitsSetUntil(idx);
// Finish up by anding the the atom with the computed msk.
- return word & mask;
+ return word_ & mask;
}
// Return a mask of all the bits up to and including bit at |idx|.
@@ -468,7 +518,7 @@
return top - 1u;
}
- uint64_t word = 0;
+ uint64_t word_ = 0;
};
// Represents a group of bits with a bitcount such that it is
@@ -483,7 +533,7 @@
class Block {
public:
// See class documentation for how these constants are chosen.
- static constexpr uint32_t kWords = 8;
+ static constexpr uint16_t kWords = 8;
static constexpr uint32_t kBits = kWords * BitWord::kBits;
// Returns whether the bit at the given address is set.
@@ -589,6 +639,24 @@
words_[end.word_idx].Set(0, end.bit_idx);
}
+ template <typename Filler>
+ static Block FromFiller(uint32_t offset, Filler f) {
+ // We choose to iterate the bits as the outer loop as this allows us
+ // to reuse the mask and the bit offset between iterations of the loop.
+ // This makes a small (but noticable) impact in the performance of this
+ // function.
+ Block b;
+ for (uint32_t i = 0; i < BitWord::kBits; ++i) {
+ uint64_t mask = 1ull << i;
+ uint32_t offset_with_bit = offset + i;
+ for (uint32_t j = 0; j < Block::kWords; ++j) {
+ bool res = f(offset_with_bit + j * BitWord::kBits);
+ b.words_[j].Or(res ? mask : 0);
+ }
+ }
+ return b;
+ }
+
private:
std::array<BitWord, kWords> words_{};
};
@@ -631,6 +699,17 @@
blocks_[end.block_idx].Set(kFirstBlockOffset, end.block_offset);
}
+ // Helper function to append a bit. Generally, prefer to call AppendTrue
+ // or AppendFalse instead of this function if you know the type - they will
+ // be faster.
+ void Append(bool value) {
+ if (value) {
+ AppendTrue();
+ } else {
+ AppendFalse();
+ }
+ }
+
static Address IndexToAddress(uint32_t idx) {
Address a;
a.block_idx = idx / Block::kBits;
@@ -647,6 +726,29 @@
addr.block_offset.bit_idx;
}
+ // Rounds |idx| up to the nearest block boundary and returns the block
+ // index. If |idx| is already on a block boundary, the current block is
+ // returned.
+ //
+ // This is useful to be able to find indices where "fast" algorithms can start
+ // which work on entire blocks.
+ static constexpr uint32_t BlockCeil(uint32_t idx) {
+ // Adding |Block::kBits - 1| gives us a quick way to get the ceil. We
+ // do this instead of adding 1 at the end because that gives incorrect
+ // answers for index % Block::kBits == 0.
+ return (idx + Block::kBits - 1) / Block::kBits;
+ }
+
+ // Returns the index of the block which would store |idx|.
+ static constexpr uint32_t BlockFloor(uint32_t idx) {
+ return idx / Block::kBits;
+ }
+
+ // Converts a block index to a index in the BitVector.
+ static constexpr uint32_t BlockToIndex(uint32_t block) {
+ return block * Block::kBits;
+ }
+
uint32_t size_ = 0;
std::vector<uint32_t> counts_;
std::vector<Block> blocks_;
diff --git a/src/trace_processor/containers/bit_vector_benchmark.cc b/src/trace_processor/containers/bit_vector_benchmark.cc
index b4a0c27..6578e73 100644
--- a/src/trace_processor/containers/bit_vector_benchmark.cc
+++ b/src/trace_processor/containers/bit_vector_benchmark.cc
@@ -17,6 +17,7 @@
#include <benchmark/benchmark.h>
#include "src/trace_processor/containers/bit_vector.h"
+#include "src/trace_processor/containers/bit_vector_iterators.h"
namespace {
@@ -27,15 +28,40 @@
}
void BitVectorArgs(benchmark::internal::Benchmark* b) {
- b->Arg(64);
+ std::vector<int> set_percentages;
+ if (IsBenchmarkFunctionalOnly()) {
+ set_percentages = std::vector<int>{50};
+ } else {
+ set_percentages = std::vector<int>{0, 1, 5, 50, 95, 99, 100};
+ }
- if (!IsBenchmarkFunctionalOnly()) {
- b->Arg(512);
- b->Arg(8192);
- b->Arg(123456);
- b->Arg(1234567);
+ for (int percentage : set_percentages) {
+ b->Args({64, percentage});
+
+ if (!IsBenchmarkFunctionalOnly()) {
+ b->Args({512, percentage});
+ b->Args({8192, percentage});
+ b->Args({123456, percentage});
+ b->Args({1234567, percentage});
+ }
}
}
+
+BitVector BvWithSizeAndSetPercentage(uint32_t size, uint32_t set_percentage) {
+ static constexpr uint32_t kRandomSeed = 29;
+ std::minstd_rand0 rnd_engine(kRandomSeed);
+
+ BitVector bv;
+ for (uint32_t i = 0; i < size; ++i) {
+ if (rnd_engine() % 100 < set_percentage) {
+ bv.AppendTrue();
+ } else {
+ bv.AppendFalse();
+ }
+ }
+ return bv;
+}
+
} // namespace
static void BM_BitVectorAppendTrue(benchmark::State& state) {
@@ -61,15 +87,9 @@
std::minstd_rand0 rnd_engine(kRandomSeed);
uint32_t size = static_cast<uint32_t>(state.range(0));
+ uint32_t set_percentage = static_cast<uint32_t>(state.range(1));
- BitVector bv;
- for (uint32_t i = 0; i < size; ++i) {
- if (rnd_engine() % 2) {
- bv.AppendTrue();
- } else {
- bv.AppendFalse();
- }
- }
+ BitVector bv = BvWithSizeAndSetPercentage(size, set_percentage);
static constexpr uint32_t kPoolSize = 1024 * 1024;
std::vector<bool> bit_pool(kPoolSize);
@@ -93,15 +113,9 @@
std::minstd_rand0 rnd_engine(kRandomSeed);
uint32_t size = static_cast<uint32_t>(state.range(0));
+ uint32_t set_percentage = static_cast<uint32_t>(state.range(1));
- BitVector bv;
- for (uint32_t i = 0; i < size; ++i) {
- if (rnd_engine() % 2) {
- bv.AppendTrue();
- } else {
- bv.AppendFalse();
- }
- }
+ BitVector bv = BvWithSizeAndSetPercentage(size, set_percentage);
static constexpr uint32_t kPoolSize = 1024 * 1024;
std::vector<uint32_t> row_pool(kPoolSize);
@@ -123,19 +137,15 @@
std::minstd_rand0 rnd_engine(kRandomSeed);
uint32_t size = static_cast<uint32_t>(state.range(0));
+ uint32_t set_percentage = static_cast<uint32_t>(state.range(1));
- BitVector bv;
- for (uint32_t i = 0; i < size; ++i) {
- if (rnd_engine() % 2) {
- bv.AppendTrue();
- } else {
- bv.AppendFalse();
- }
- }
-
+ BitVector bv = BvWithSizeAndSetPercentage(size, set_percentage);
static constexpr uint32_t kPoolSize = 1024 * 1024;
std::vector<uint32_t> row_pool(kPoolSize);
uint32_t set_bit_count = bv.GetNumBitsSet();
+ if (set_bit_count == 0)
+ return;
+
for (uint32_t i = 0; i < kPoolSize; ++i) {
row_pool[i] = rnd_engine() % set_bit_count;
}
@@ -153,11 +163,12 @@
std::minstd_rand0 rnd_engine(kRandomSeed);
uint32_t size = static_cast<uint32_t>(state.range(0));
+ uint32_t set_percentage = static_cast<uint32_t>(state.range(1));
uint32_t count = 0;
BitVector bv;
for (uint32_t i = 0; i < size; ++i) {
- bool value = rnd_engine() % 2;
+ bool value = rnd_engine() % 100 < set_percentage;
if (value) {
bv.AppendTrue();
} else {
@@ -200,16 +211,39 @@
}
BENCHMARK(BM_BitVectorResize);
+static void BM_BitVectorRangeFixedSize(benchmark::State& state) {
+ static constexpr uint32_t kRandomSeed = 42;
+ std::minstd_rand0 rnd_engine(kRandomSeed);
+
+ uint32_t size = static_cast<uint32_t>(state.range(0));
+ uint32_t set_percentage = static_cast<uint32_t>(state.range(1));
+
+ std::vector<uint32_t> resize_fill_pool(size);
+ for (uint32_t i = 0; i < size; ++i) {
+ resize_fill_pool[i] = rnd_engine() % 100 < set_percentage ? 90 : 100;
+ }
+
+ for (auto _ : state) {
+ auto filler = [&resize_fill_pool](uint32_t i) PERFETTO_ALWAYS_INLINE {
+ return resize_fill_pool[i] < 95;
+ };
+ BitVector bv = BitVector::Range(0, size, filler);
+ benchmark::ClobberMemory();
+ }
+}
+BENCHMARK(BM_BitVectorRangeFixedSize)->Apply(BitVectorArgs);
+
static void BM_BitVectorUpdateSetBits(benchmark::State& state) {
static constexpr uint32_t kRandomSeed = 42;
std::minstd_rand0 rnd_engine(kRandomSeed);
uint32_t size = static_cast<uint32_t>(state.range(0));
+ uint32_t set_percentage = static_cast<uint32_t>(state.range(1));
BitVector bv;
BitVector picker;
for (uint32_t i = 0; i < size; ++i) {
- bool value = rnd_engine() % 2;
+ bool value = rnd_engine() % 100 < set_percentage;
if (value) {
bv.AppendTrue();
@@ -234,3 +268,16 @@
}
}
BENCHMARK(BM_BitVectorUpdateSetBits)->Apply(BitVectorArgs);
+
+static void BM_BitVectorSetBitsIterator(benchmark::State& state) {
+ uint32_t size = static_cast<uint32_t>(state.range(0));
+ uint32_t set_percentage = static_cast<uint32_t>(state.range(1));
+
+ BitVector bv = BvWithSizeAndSetPercentage(size, set_percentage);
+ for (auto _ : state) {
+ for (auto it = bv.IterateSetBits(); it; it.Next()) {
+ benchmark::DoNotOptimize(it.index());
+ }
+ }
+}
+BENCHMARK(BM_BitVectorSetBitsIterator)->Apply(BitVectorArgs);
diff --git a/src/trace_processor/containers/bit_vector_iterators.h b/src/trace_processor/containers/bit_vector_iterators.h
index 0047812..62094ff 100644
--- a/src/trace_processor/containers/bit_vector_iterators.h
+++ b/src/trace_processor/containers/bit_vector_iterators.h
@@ -132,6 +132,16 @@
// Increments the iterator to point to the next bit.
void Next() { SetIndex(index() + 1); }
+ // Increments the iterator to skip the next |n| bits and point to the
+ // following one.
+ // Precondition: n >= 1 & index() + n <= size().
+ void Skip(uint32_t n) {
+ PERFETTO_DCHECK(n >= 1);
+ PERFETTO_DCHECK(index() + n <= size());
+
+ SetIndex(index() + n);
+ }
+
// Returns whether the iterator is valid.
operator bool() const { return index() < size(); }
};
diff --git a/src/trace_processor/containers/bit_vector_unittest.cc b/src/trace_processor/containers/bit_vector_unittest.cc
index e185afd..4a78c2c 100644
--- a/src/trace_processor/containers/bit_vector_unittest.cc
+++ b/src/trace_processor/containers/bit_vector_unittest.cc
@@ -237,6 +237,22 @@
ASSERT_TRUE(bv.IsSet(4));
}
+TEST(BitVectorUnittest, UpdateSetBitsSmallerPicker) {
+ BitVector bv(6, false);
+ bv.Set(1);
+ bv.Set(2);
+ bv.Set(4);
+
+ BitVector picker(2u, true);
+ picker.Clear(1);
+
+ bv.UpdateSetBits(picker);
+
+ ASSERT_TRUE(bv.IsSet(1));
+ ASSERT_FALSE(bv.IsSet(2));
+ ASSERT_FALSE(bv.IsSet(4));
+}
+
TEST(BitVectorUnittest, IterateAllBitsConst) {
BitVector bv;
for (uint32_t i = 0; i < 12345; ++i) {
@@ -383,6 +399,18 @@
ASSERT_FALSE(it);
}
+TEST(BitVectorUnittest, Range) {
+ BitVector bv =
+ BitVector::Range(1, 1025, [](uint32_t t) { return t % 3 == 0; });
+
+ ASSERT_FALSE(bv.IsSet(0));
+ for (uint32_t i = 1; i < 1025; ++i) {
+ ASSERT_EQ(i % 3 == 0, bv.IsSet(i));
+ }
+ ASSERT_EQ(bv.size(), 1025u);
+ ASSERT_EQ(bv.GetNumBitsSet(), 341u);
+}
+
TEST(BitVectorUnittest, QueryStressTest) {
BitVector bv;
std::vector<bool> bool_vec;
diff --git a/src/trace_processor/containers/row_map.cc b/src/trace_processor/containers/row_map.cc
index b10d0cb..0a3def0 100644
--- a/src/trace_processor/containers/row_map.cc
+++ b/src/trace_processor/containers/row_map.cc
@@ -36,9 +36,9 @@
uint32_t end,
const BitVector& selector) {
PERFETTO_DCHECK(start <= end);
- PERFETTO_DCHECK(end - start == selector.size());
+ PERFETTO_DCHECK(selector.size() <= end - start);
- // If |start| == 0 and |end - start| == |selector.size()| (which is a
+ // If |start| == 0 and |selector.size()| <= |end - start| (which is a
// precondition for this function), the BitVector we generate is going to be
// exactly |selector|.
//
@@ -49,8 +49,11 @@
if (start == 0u)
return RowMap(selector.Copy());
+ // We only need to resize to |start| + |selector.size()| as we know any rows
+ // not covered by |selector| are going to be removed below.
BitVector bv(start, false);
- bv.Resize(end, true);
+ bv.Resize(start + selector.size(), true);
+
bv.UpdateSetBits(selector);
return RowMap(std::move(bv));
}
diff --git a/src/trace_processor/containers/row_map.h b/src/trace_processor/containers/row_map.h
index cac8f2e..8cf91f1 100644
--- a/src/trace_processor/containers/row_map.h
+++ b/src/trace_processor/containers/row_map.h
@@ -242,16 +242,19 @@
PERFETTO_FATAL("For GCC");
}
+ // Returns whether this rowmap is empty.
+ bool empty() const { return size() == 0; }
+
// Returns the row at index |row|.
uint32_t Get(uint32_t idx) const {
PERFETTO_DCHECK(idx < size());
switch (mode_) {
case Mode::kRange:
- return start_idx_ + idx;
+ return GetRange(idx);
case Mode::kBitVector:
- return bit_vector_.IndexOfNthSet(idx);
+ return GetBitVector(idx);
case Mode::kIndexVector:
- return index_vector_[idx];
+ return GetIndexVector(idx);
}
PERFETTO_FATAL("For GCC");
}
@@ -392,7 +395,7 @@
}
// TODO(lalitm): improve efficiency of this if we end up needing it.
- RemoveIf([&other](uint32_t row) { return !other.Contains(row); });
+ Filter([&other](uint32_t row) { return other.Contains(row); });
}
// Filters the current RowMap into the RowMap given by |out| based on the
@@ -421,7 +424,7 @@
void FilterInto(RowMap* out, Predicate p) const {
PERFETTO_DCHECK(size() >= out->size());
- if (out->size() == 0) {
+ if (out->empty()) {
// If the output RowMap is empty, we don't need to do anything.
return;
}
@@ -438,41 +441,52 @@
// cases where |out| has only a few entries so we can scan |out| instead of
// scanning |this|.
- // TODO(lalit): investigate whether we should also scan |out| if |this| is
- // a range or index vector as, in those cases, it would be fast to lookup
- // |this| by index.
-
- // We choose to full scan |this| rather than |out| as the performance
- // penalty of incorrectly scanning |out| is much worse than mistakely
- // scanning |this|.
- // This is because scans on |out| involve an indexed lookup on |this| which
- // (in the case of a bitvector) can be very expensive. On the other hand,
- // scanning |this| means we never have to do indexed lookups but we may
- // scan many more rows than necessary (as they may have already been
- // excluded in out).
- FilterIntoScanSelf(out, p);
- }
-
- template <typename Comparator>
- void StableSort(std::vector<uint32_t>* out, Comparator c) const {
+ // Ideally, we'd always just scan the rows in |out| and keep those which
+ // meet |p|. However, if |this| is a BitVector, we end up needing expensive
+ // |IndexOfNthSet| calls (as we need to lookup the row before passing it to
+ // |p|).
switch (mode_) {
case Mode::kRange: {
- StableSort(out, c, [this](uint32_t off) { return start_idx_ + off; });
+ auto ip = [this, p](uint32_t idx) { return p(GetRange(idx)); };
+ out->Filter(ip);
break;
}
case Mode::kBitVector: {
- StableSort(out, c, [this](uint32_t off) {
- return bit_vector_.IndexOfNthSet(off);
- });
+ FilterIntoScanSelfBv(out, p);
break;
}
case Mode::kIndexVector: {
- StableSort(out, c, [this](uint32_t off) { return index_vector_[off]; });
+ auto ip = [this, p](uint32_t row) { return p(GetIndexVector(row)); };
+ out->Filter(ip);
break;
}
}
}
+ template <typename Comparator = bool(uint32_t, uint32_t)>
+ void StableSort(std::vector<uint32_t>* out, Comparator c) const {
+ switch (mode_) {
+ case Mode::kRange:
+ std::stable_sort(out->begin(), out->end(),
+ [this, c](uint32_t a, uint32_t b) {
+ return c(GetRange(a), GetRange(b));
+ });
+ break;
+ case Mode::kBitVector:
+ std::stable_sort(out->begin(), out->end(),
+ [this, c](uint32_t a, uint32_t b) {
+ return c(GetBitVector(a), GetBitVector(b));
+ });
+ break;
+ case Mode::kIndexVector:
+ std::stable_sort(out->begin(), out->end(),
+ [this, c](uint32_t a, uint32_t b) {
+ return c(GetIndexVector(a), GetIndexVector(b));
+ });
+ break;
+ }
+ }
+
// Returns the iterator over the rows in this RowMap.
Iterator IterateRows() const { return Iterator(this); }
@@ -486,29 +500,35 @@
kIndexVector,
};
- // Filters the current RowMap into |out| by performing a full scan on |this|.
- // See |FilterInto| for a full breakdown of the semantics of this function.
+ // Filters the indices in |out| by keeping those which meet |p|.
template <typename Predicate>
- void FilterIntoScanSelf(RowMap* out, Predicate p) const {
+ void Filter(Predicate p) {
switch (mode_) {
case Mode::kRange:
- FilterIntoScanSelf(out, RangeIterator(this), p);
+ FilterRange(p);
break;
- case Mode::kBitVector:
- FilterIntoScanSelf(out, bit_vector_.IterateSetBits(), p);
+ case Mode::kBitVector: {
+ for (auto it = bit_vector_.IterateSetBits(); it; it.Next()) {
+ if (!p(it.index()))
+ it.Clear();
+ }
break;
- case Mode::kIndexVector:
- FilterIntoScanSelf(out, IndexVectorIterator(this), p);
+ }
+ case Mode::kIndexVector: {
+ auto ret = std::remove_if(index_vector_.begin(), index_vector_.end(),
+ [p](uint32_t i) { return !p(i); });
+ index_vector_.erase(ret, index_vector_.end());
break;
+ }
}
}
// Filters the current RowMap into |out| by performing a full scan on |this|
- // using the |it|, a strongly typed iterator on |this| (a strongly typed
- // iterator is used for performance reasons).
+ // where |this| is a BitVector.
// See |FilterInto| for a full breakdown of the semantics of this function.
- template <typename Iterator, typename Predicate>
- void FilterIntoScanSelf(RowMap* out, Iterator it, Predicate p) const {
+ template <typename Predicate>
+ void FilterIntoScanSelfBv(RowMap* out, Predicate p) const {
+ auto it = bit_vector_.IterateSetBits();
switch (out->mode_) {
case Mode::kRange: {
// TODO(lalitm): investigate whether we can reuse the data inside
@@ -556,6 +576,53 @@
}
}
+ template <typename Predicate>
+ void FilterRange(Predicate p) {
+ uint32_t count = end_idx_ - start_idx_;
+
+ // Optimization: if we are only going to scan a few rows, it's not
+ // worth the haslle of working with a BitVector.
+ constexpr uint32_t kSmallRangeLimit = 2048;
+ bool is_small_range = count < kSmallRangeLimit;
+
+ // Optimization: weif the cost of a BitVector is more than the highest
+ // possible cost an index vector could have, use the index vector.
+ uint32_t bit_vector_cost = BitVector::ApproxBytesCost(end_idx_);
+ uint32_t index_vector_cost_ub = sizeof(uint32_t) * count;
+
+ // If either of the conditions hold which make it better to use an
+ // index vector, use it instead.
+ if (is_small_range || index_vector_cost_ub <= bit_vector_cost) {
+ // Try and strike a good balance between not making the vector too
+ // big and good performance.
+ std::vector<uint32_t> iv(std::min(kSmallRangeLimit, count));
+
+ uint32_t out_idx = 0;
+ for (uint32_t i = 0; i < count; ++i) {
+ // If we reach the capacity add another small set of indices.
+ if (PERFETTO_UNLIKELY(out_idx == iv.size()))
+ iv.resize(iv.size() + kSmallRangeLimit);
+
+ // We keep this branch free by always writing the index but only
+ // incrementing the out index if the return value is true.
+ bool value = p(i + start_idx_);
+ iv[out_idx] = i + start_idx_;
+ out_idx += value;
+ }
+
+ // Make the vector the correct size and as small as possible.
+ iv.resize(out_idx);
+ iv.shrink_to_fit();
+
+ *this = RowMap(std::move(iv));
+ return;
+ }
+
+ // Otherwise, create a bitvector which spans the full range using
+ // |p| as the filler for the bits between start and end.
+ *this = RowMap(BitVector::Range(start_idx_, end_idx_, p));
+ }
+
void InsertIntoBitVector(uint32_t row) {
PERFETTO_DCHECK(mode_ == Mode::kBitVector);
@@ -564,41 +631,17 @@
bit_vector_.Set(row);
}
- // Removes any row where |p(row)| returns false from this RowMap.
- template <typename Predicate>
- void RemoveIf(Predicate p) {
- switch (mode_) {
- case Mode::kRange: {
- bit_vector_.Resize(start_idx_, false);
- for (uint32_t i = start_idx_; i < end_idx_; ++i) {
- if (p(i))
- bit_vector_.AppendFalse();
- else
- bit_vector_.AppendTrue();
- }
- *this = RowMap(std::move(bit_vector_));
- break;
- }
- case Mode::kBitVector: {
- for (auto it = bit_vector_.IterateSetBits(); it; it.Next()) {
- if (p(it.index()))
- it.Clear();
- }
- break;
- }
- case Mode::kIndexVector: {
- auto it = std::remove_if(index_vector_.begin(), index_vector_.end(), p);
- index_vector_.erase(it, index_vector_.end());
- break;
- }
- }
+ PERFETTO_ALWAYS_INLINE uint32_t GetRange(uint32_t idx) const {
+ PERFETTO_DCHECK(mode_ == Mode::kRange);
+ return start_idx_ + idx;
}
-
- template <typename Comparator, typename Indexer>
- void StableSort(std::vector<uint32_t>* out, Comparator c, Indexer i) const {
- std::stable_sort(
- out->begin(), out->end(),
- [&c, &i](uint32_t a, uint32_t b) { return c(i(a), i(b)); });
+ PERFETTO_ALWAYS_INLINE uint32_t GetBitVector(uint32_t idx) const {
+ PERFETTO_DCHECK(mode_ == Mode::kBitVector);
+ return bit_vector_.IndexOfNthSet(idx);
+ }
+ PERFETTO_ALWAYS_INLINE uint32_t GetIndexVector(uint32_t idx) const {
+ PERFETTO_DCHECK(mode_ == Mode::kIndexVector);
+ return index_vector_[idx];
}
RowMap SelectRowsSlow(const RowMap& selector) const;
diff --git a/src/trace_processor/containers/row_map_unittest.cc b/src/trace_processor/containers/row_map_unittest.cc
index c85b5fe..fde10d5 100644
--- a/src/trace_processor/containers/row_map_unittest.cc
+++ b/src/trace_processor/containers/row_map_unittest.cc
@@ -195,6 +195,15 @@
ASSERT_EQ(res.Get(1u), 30u);
}
+TEST(RowMapUnittest, SelectRangeWithSmallBitVector) {
+ RowMap rm(27, 31);
+ RowMap picker(BitVector{false, true});
+ auto res = rm.SelectRows(picker);
+
+ ASSERT_EQ(res.size(), 1u);
+ ASSERT_EQ(res.Get(0u), 28u);
+}
+
TEST(RowMapUnittest, SelectBitVectorWithBitVector) {
RowMap rm(BitVector{true, false, true, true, false, true});
RowMap picker(BitVector{true, false, false, true});
@@ -205,6 +214,15 @@
ASSERT_EQ(res.Get(1u), 5u);
}
+TEST(RowMapUnittest, SelectBitVectorWithSmallBitVector) {
+ RowMap rm(BitVector{true, false, true, true, false, true});
+ RowMap picker(BitVector{false, true});
+ auto res = rm.SelectRows(picker);
+
+ ASSERT_EQ(res.size(), 1u);
+ ASSERT_EQ(res.Get(0u), 2u);
+}
+
TEST(RowMapUnittest, SelectIndexVectorWithBitVector) {
RowMap rm(std::vector<uint32_t>{0u, 2u, 3u, 5u});
RowMap picker(BitVector{true, false, false, true});
@@ -330,6 +348,26 @@
ASSERT_EQ(filter.Get(1u), 5u);
}
+TEST(RowMapUnittest, FilterIntoOffsetRangeWithRange) {
+ RowMap rm(100000, 100010);
+ RowMap filter(4, 7);
+ rm.FilterInto(&filter, [](uint32_t row) { return row == 100004u; });
+
+ ASSERT_EQ(filter.size(), 1u);
+ ASSERT_EQ(filter.Get(0u), 4u);
+}
+
+TEST(RowMapUnittest, FilterIntoLargeRangeWithRange) {
+ RowMap rm(0, 100000);
+ RowMap filter(0, 100000);
+ rm.FilterInto(&filter, [](uint32_t row) { return row % 2 == 0; });
+
+ ASSERT_EQ(filter.size(), 100000u / 2);
+ for (uint32_t i = 0; i < 100000 / 2; ++i) {
+ ASSERT_EQ(filter.Get(i), i * 2);
+ }
+}
+
TEST(RowMapUnittest, FilterIntoBitVectorWithRange) {
RowMap rm(
BitVector{true, false, false, true, false, true, false, true, true});
diff --git a/src/trace_processor/containers/string_pool.cc b/src/trace_processor/containers/string_pool.cc
index 020de1c..fd65195 100644
--- a/src/trace_processor/containers/string_pool.cc
+++ b/src/trace_processor/containers/string_pool.cc
@@ -24,61 +24,90 @@
namespace perfetto {
namespace trace_processor {
-StringPool::StringPool(size_t block_size_bytes)
- : block_size_bytes_(block_size_bytes > 0 ? block_size_bytes
- : kDefaultBlockSize) {
- blocks_.emplace_back(block_size_bytes_);
+// static
+constexpr size_t StringPool::kNumBlockIndexBits;
+// static
+constexpr size_t StringPool::kNumBlockOffsetBits;
+// static
+constexpr size_t StringPool::kLargeStringFlagBitMask;
+// static
+constexpr size_t StringPool::kBlockOffsetBitMask;
+// static
+constexpr size_t StringPool::kBlockIndexBitMask;
+// static
+constexpr size_t StringPool::kBlockSizeBytes;
+// static
+constexpr size_t StringPool::kMinLargeStringSizeBytes;
+
+StringPool::StringPool() {
+ static_assert(
+ StringPool::kMinLargeStringSizeBytes <= StringPool::kBlockSizeBytes + 1,
+ "minimum size of large strings must be small enough to support any "
+ "string that doesn't fit in a Block.");
+
+ blocks_.emplace_back(kBlockSizeBytes);
// Reserve a slot for the null string.
- PERFETTO_CHECK(blocks_.back().TryInsert(NullTermStringView()));
+ PERFETTO_CHECK(blocks_.back().TryInsert(NullTermStringView()).first);
}
StringPool::~StringPool() = default;
-StringPool::StringPool(StringPool&&) noexcept = default;
+StringPool::StringPool(StringPool&&) = default;
StringPool& StringPool::operator=(StringPool&&) = default;
StringPool::Id StringPool::InsertString(base::StringView str, uint64_t hash) {
// Try and find enough space in the current block for the string and the
// metadata (varint-encoded size + the string data + the null terminator).
- const uint8_t* ptr = blocks_.back().TryInsert(str);
- if (PERFETTO_UNLIKELY(!ptr)) {
- // This means the block did not have enough space. This should only happen
- // if the block size is small.
- PERFETTO_CHECK(block_size_bytes_ <= std::numeric_limits<uint32_t>::max());
-
- // Add a new block to store the data. If the string is larger that the
- // default block size, add a bigger block exlusively for this string.
- if (str.size() + kMaxMetadataSize > block_size_bytes_) {
- blocks_.emplace_back(str.size() +
- base::AlignUp<base::kPageSize>(kMaxMetadataSize));
+ bool success;
+ uint32_t offset;
+ std::tie(success, offset) = blocks_.back().TryInsert(str);
+ if (PERFETTO_UNLIKELY(!success)) {
+ // The block did not have enough space for the string. If the string is
+ // large, add it into the |large_strings_| vector, to avoid discarding a
+ // large portion of the current block's memory. This also enables us to
+ // support strings that wouldn't fit into a single block. Otherwise, add a
+ // new block to store the string.
+ if (str.size() + kMaxMetadataSize >= kMinLargeStringSizeBytes) {
+ return InsertLargeString(str, hash);
} else {
- blocks_.emplace_back(block_size_bytes_);
+ blocks_.emplace_back(kBlockSizeBytes);
}
// Try and reserve space again - this time we should definitely succeed.
- ptr = blocks_.back().TryInsert(str);
- PERFETTO_CHECK(ptr);
+ std::tie(success, offset) = blocks_.back().TryInsert(str);
+ PERFETTO_CHECK(success);
}
- // Finish by computing the id of the pointer and adding a mapping from the
- // hash to the string_id.
- Id string_id = PtrToId(ptr);
+ // Compute the id from the block index and offset and add a mapping from the
+ // hash to the id.
+ Id string_id = Id::BlockString(blocks_.size() - 1, offset);
string_index_.emplace(hash, string_id);
return string_id;
}
-const uint8_t* StringPool::Block::TryInsert(base::StringView str) {
+StringPool::Id StringPool::InsertLargeString(base::StringView str,
+ uint64_t hash) {
+ large_strings_.emplace_back(new std::string(str.begin(), str.size()));
+ // Compute id from the index and add a mapping from the hash to the id.
+ Id string_id = Id::LargeString(large_strings_.size() - 1);
+ string_index_.emplace(hash, string_id);
+ return string_id;
+}
+
+std::pair<bool /*success*/, uint32_t /*offset*/> StringPool::Block::TryInsert(
+ base::StringView str) {
auto str_size = str.size();
size_t max_pos = static_cast<size_t>(pos_) + str_size + kMaxMetadataSize;
if (max_pos > size_)
- return nullptr;
+ return std::make_pair(false, 0u);
// Ensure that we commit up until the end of the string to memory.
mem_.EnsureCommitted(max_pos);
// Get where we should start writing this string.
- uint8_t* begin = Get(pos_);
+ uint32_t offset = pos_;
+ uint8_t* begin = Get(offset);
// First write the size of the string using varint encoding.
uint8_t* end = protozero::proto_utils::WriteVarInt(str_size, begin);
@@ -95,55 +124,59 @@
// Update the end of the block and return the pointer to the string.
pos_ = OffsetOf(end);
- return begin;
+ return std::make_pair(true, offset);
}
StringPool::Iterator::Iterator(const StringPool* pool) : pool_(pool) {}
StringPool::Iterator& StringPool::Iterator::operator++() {
- PERFETTO_DCHECK(block_id_ < pool_->blocks_.size());
+ if (block_index_ < pool_->blocks_.size()) {
+ // Try and go to the next string in the current block.
+ const auto& block = pool_->blocks_[block_index_];
- // Try and go to the next string in the current block.
- const auto& block = pool_->blocks_[block_id_];
+ // Find the size of the string at the current offset in the block
+ // and increment the offset by that size.
+ uint32_t str_size = 0;
+ const uint8_t* ptr = block.Get(block_offset_);
+ ptr = ReadSize(ptr, &str_size);
+ ptr += str_size + 1;
+ block_offset_ = block.OffsetOf(ptr);
- // Find the size of the string at the current offset in the block
- // and increment the offset by that size.
- uint32_t str_size = 0;
- const uint8_t* ptr = block.Get(block_offset_);
- ptr = ReadSize(ptr, &str_size);
- ptr += str_size + 1;
- block_offset_ = block.OffsetOf(ptr);
+ // If we're out of bounds for this block, go to the start of the next block.
+ if (block.pos() <= block_offset_) {
+ block_index_++;
+ block_offset_ = 0;
+ }
- // If we're out of bounds for this block, go to the start of the next block.
- if (block.pos() <= block_offset_) {
- block_id_++;
- block_offset_ = 0;
+ return *this;
}
+
+ // Advance to the next string from |large_strings_|.
+ PERFETTO_DCHECK(large_strings_index_ < pool_->large_strings_.size());
+ large_strings_index_++;
return *this;
}
StringPool::Iterator::operator bool() const {
- return block_id_ < pool_->blocks_.size();
+ return block_index_ < pool_->blocks_.size() ||
+ large_strings_index_ < pool_->large_strings_.size();
}
NullTermStringView StringPool::Iterator::StringView() {
- PERFETTO_DCHECK(block_id_ < pool_->blocks_.size());
- PERFETTO_DCHECK(block_offset_ < pool_->blocks_[block_id_].pos());
-
- // If we're at (0, 0), we have the null string.
- if (block_id_ == 0 && block_offset_ == 0)
- return NullTermStringView();
- return GetFromPtr(pool_->blocks_[block_id_].Get(block_offset_));
+ return pool_->Get(StringId());
}
StringPool::Id StringPool::Iterator::StringId() {
- PERFETTO_DCHECK(block_id_ < pool_->blocks_.size());
- PERFETTO_DCHECK(block_offset_ < pool_->blocks_[block_id_].pos());
+ if (block_index_ < pool_->blocks_.size()) {
+ PERFETTO_DCHECK(block_offset_ < pool_->blocks_[block_index_].pos());
- // If we're at (0, 0), we have the null string which has id 0.
- if (block_id_ == 0 && block_offset_ == 0)
- return 0;
- return pool_->PtrToId(pool_->blocks_[block_id_].Get(block_offset_));
+ // If we're at (0, 0), we have the null string which has id 0.
+ if (block_index_ == 0 && block_offset_ == 0)
+ return Id::Null();
+ return Id::BlockString(block_index_, block_offset_);
+ }
+ PERFETTO_DCHECK(large_strings_index_ < pool_->large_strings_.size());
+ return Id::LargeString(large_strings_index_);
}
} // namespace trace_processor
diff --git a/src/trace_processor/containers/string_pool.h b/src/trace_processor/containers/string_pool.h
index bdfc39f..11ae91c 100644
--- a/src/trace_processor/containers/string_pool.h
+++ b/src/trace_processor/containers/string_pool.h
@@ -31,22 +31,12 @@
namespace perfetto {
namespace trace_processor {
-// On 64-bit platforms, the string pool is implemented as a mmaped buffer
-// of 4GB with the id being equal ot the offset into this buffer of the string.
-// On 32-bit platforms instead, the implementation allocates 32MB blocks of
-// mmaped memory with the pointer being directly converted to the id.
-constexpr size_t kDefaultBlockSize =
- sizeof(void*) == 8
- ? static_cast<size_t>(4ull * 1024ull * 1024ull * 1024ull) /* 4GB */
- : 32ull * 1024ull * 1024ull /* 32MB */;
-
// Interns strings in a string pool and hands out compact StringIds which can
// be used to retrieve the string in O(1).
class StringPool {
public:
struct Id {
Id() = default;
- constexpr Id(uint32_t i) : id(i) {}
bool operator==(const Id& other) const { return other.id == id; }
bool operator!=(const Id& other) const { return !(other == *this); }
@@ -54,6 +44,42 @@
bool is_null() const { return id == 0u; }
+ bool is_large_string() const { return id & kLargeStringFlagBitMask; }
+
+ uint32_t block_offset() const { return id & kBlockOffsetBitMask; }
+
+ uint32_t block_index() const {
+ return (id & kBlockIndexBitMask) >> kNumBlockOffsetBits;
+ }
+
+ uint32_t large_string_index() const {
+ PERFETTO_DCHECK(is_large_string());
+ return id & ~kLargeStringFlagBitMask;
+ }
+
+ uint32_t raw_id() const { return id; }
+
+ static Id LargeString(size_t index) {
+ PERFETTO_DCHECK(index <= static_cast<uint32_t>(index));
+ PERFETTO_DCHECK(!(index & kLargeStringFlagBitMask));
+ return Id(kLargeStringFlagBitMask | static_cast<uint32_t>(index));
+ }
+
+ static Id BlockString(size_t index, uint32_t offset) {
+ PERFETTO_DCHECK(index < (1u << (kNumBlockIndexBits + 1)));
+ PERFETTO_DCHECK(offset < (1u << (kNumBlockOffsetBits + 1)));
+ return Id(~kLargeStringFlagBitMask &
+ (static_cast<uint32_t>(index << kNumBlockOffsetBits) |
+ (offset & kBlockOffsetBitMask)));
+ }
+
+ static constexpr Id Raw(uint32_t raw) { return Id(raw); }
+
+ static constexpr Id Null() { return Id(0u); }
+
+ private:
+ constexpr Id(uint32_t i) : id(i) {}
+
uint32_t id;
};
@@ -70,15 +96,16 @@
private:
const StringPool* pool_ = nullptr;
- uint32_t block_id_ = 0;
+ uint32_t block_index_ = 0;
uint32_t block_offset_ = 0;
+ uint32_t large_strings_index_ = 0;
};
- StringPool(size_t block_size_bytes = kDefaultBlockSize);
+ StringPool();
~StringPool();
// Allow std::move().
- StringPool(StringPool&&) noexcept;
+ StringPool(StringPool&&);
StringPool& operator=(StringPool&&);
// Disable implicit copy.
@@ -87,7 +114,7 @@
Id InternString(base::StringView str) {
if (str.data() == nullptr)
- return Id(0);
+ return Id::Null();
auto hash = str.Hash();
auto id_it = string_index_.find(hash);
@@ -100,7 +127,7 @@
base::Optional<Id> GetId(base::StringView str) const {
if (str.data() == nullptr)
- return Id(0u);
+ return Id::Null();
auto hash = str.Hash();
auto id_it = string_index_.find(hash);
@@ -112,9 +139,11 @@
}
NullTermStringView Get(Id id) const {
- if (id.id == 0)
+ if (id.is_null())
return NullTermStringView();
- return GetFromPtr(IdToPtr(id));
+ if (id.is_large_string())
+ return GetLargeString(id);
+ return GetFromBlockPtr(IdToPtr(id));
}
Iterator CreateIterator() const { return Iterator(this); }
@@ -143,11 +172,12 @@
return static_cast<uint8_t*>(mem_.Get()) + offset;
}
- const uint8_t* TryInsert(base::StringView str);
+ std::pair<bool /*success*/, uint32_t /*offset*/> TryInsert(
+ base::StringView str);
uint32_t OffsetOf(const uint8_t* ptr) const {
PERFETTO_DCHECK(Get(0) < ptr &&
- ptr < Get(static_cast<uint32_t>(size_ - 1)));
+ ptr <= Get(static_cast<uint32_t>(size_ - 1)));
return static_cast<uint32_t>(ptr - Get(0));
}
@@ -160,43 +190,59 @@
};
friend class Iterator;
+ friend class StringPoolTest;
+
+ // StringPool IDs are 32-bit. If the MSB is 1, the remaining bits of the ID
+ // are an index into the |large_strings_| vector. Otherwise, the next 6 bits
+ // are the index of the Block in the pool, and the remaining 25 bits the
+ // offset of the encoded string inside the pool.
+ //
+ // [31] [30:25] [24:0]
+ // | | |
+ // | | +---- offset in block (or LSB of large string index).
+ // | +------------ block index (or MSB of large string index).
+ // +------------------- 1: large string, 0: string in a Block.
+ static constexpr size_t kNumBlockIndexBits = 6;
+ static constexpr size_t kNumBlockOffsetBits = 25;
+
+ static constexpr size_t kLargeStringFlagBitMask = 1u << 31;
+ static constexpr size_t kBlockOffsetBitMask = (1u << kNumBlockOffsetBits) - 1;
+ static constexpr size_t kBlockIndexBitMask =
+ 0xffffffff & ~kLargeStringFlagBitMask & ~kBlockOffsetBitMask;
+
+ static constexpr size_t kBlockSizeBytes = kBlockOffsetBitMask + 1; // 32 MB
+
+ // If a string doesn't fit into the current block, we can either start a new
+ // block or insert the string into the |large_strings_| vector. To maximize
+ // the used proportion of each block's memory, we only start a new block if
+ // the string isn't very large.
+ static constexpr size_t kMinLargeStringSizeBytes = kBlockSizeBytes / 8;
// Number of bytes to reserve for size and null terminator.
// This is the upper limit on metadata size: 5 bytes for max uint32,
// plus 1 byte for null terminator. The actual size may be lower.
static constexpr uint8_t kMaxMetadataSize = 6;
- // Inserts the string with the given hash into the pool
+ // Inserts the string with the given hash into the pool and return its Id.
Id InsertString(base::StringView, uint64_t hash);
- // |ptr| should point to the start of the string metadata (i.e. the first byte
- // of the size).
- Id PtrToId(const uint8_t* ptr) const {
- // For a 64 bit architecture, the id is the offset of the pointer inside
- // the one and only 4GB block.
- if (sizeof(void*) == 8) {
- PERFETTO_DCHECK(blocks_.size() == 1);
- return Id(blocks_.back().OffsetOf(ptr));
- }
-
- // On 32 bit architectures, the size of the pointer is 32-bit so we simply
- // use the pointer itself as the id.
- // Double cast needed because, on 64 archs, the compiler complains that we
- // are losing information.
- return Id(static_cast<uint32_t>(reinterpret_cast<uintptr_t>(ptr)));
- }
+ // Insert a large string into the pool and return its Id.
+ Id InsertLargeString(base::StringView, uint64_t hash);
// The returned pointer points to the start of the string metadata (i.e. the
// first byte of the size).
const uint8_t* IdToPtr(Id id) const {
- // For a 64 bit architecture, the pointer is simply the found by taking
- // the base of the 4GB block and adding the offset given by |id|.
- if (sizeof(void*) == 8) {
- PERFETTO_DCHECK(blocks_.size() == 1);
- return blocks_.back().Get(id.id);
- }
- // On a 32 bit architecture, the pointer is the same as the id.
- return reinterpret_cast<uint8_t*>(id.id);
+ // If the MSB is set, the ID represents an index into |large_strings_|, so
+ // shouldn't be converted into a block pointer.
+ PERFETTO_DCHECK(!id.is_large_string());
+
+ size_t block_index = id.block_index();
+ uint32_t block_offset = id.block_offset();
+
+ PERFETTO_DCHECK(block_index < blocks_.size());
+ PERFETTO_DCHECK(block_offset < blocks_[block_index].pos());
+
+ return blocks_[block_index].Get(block_offset);
}
// |ptr| should point to the start of the string metadata (i.e. the first byte
@@ -214,19 +260,30 @@
// |ptr| should point to the start of the string metadata (i.e. the first byte
// of the size).
- static NullTermStringView GetFromPtr(const uint8_t* ptr) {
+ static NullTermStringView GetFromBlockPtr(const uint8_t* ptr) {
uint32_t size = 0;
const uint8_t* str_ptr = ReadSize(ptr, &size);
return NullTermStringView(reinterpret_cast<const char*>(str_ptr), size);
}
- // The minimum size of a new block. A larger block may be created if a string
- // is added that is larger than this size.
- size_t block_size_bytes_;
+ // Lookup a string in the |large_strings_| vector. |id| should have the MSB
+ // set.
+ NullTermStringView GetLargeString(Id id) const {
+ PERFETTO_DCHECK(id.is_large_string());
+ size_t index = id.large_string_index();
+ PERFETTO_DCHECK(index < large_strings_.size());
+ const std::string* str = large_strings_[index].get();
+ return NullTermStringView(str->c_str(), str->size());
+ }
// The actual memory storing the strings.
std::vector<Block> blocks_;
+ // Any string that is too large to fit into a Block is stored separately
+ // (inside a unique_ptr to ensure any references to it remain valid even if
+ // |large_strings_| is resized).
+ std::vector<std::unique_ptr<std::string>> large_strings_;
+
// Maps hashes of strings to the Id in the string pool.
// TODO(lalitm): At some point we should benchmark just using a static
// hashtable of 1M elements, we can afford paying a fixed 8MB here
@@ -244,7 +301,7 @@
using result_type = size_t;
result_type operator()(const argument_type& r) const {
- return std::hash<uint32_t>{}(r.id);
+ return std::hash<uint32_t>{}(r.raw_id());
}
};
diff --git a/src/trace_processor/containers/string_pool_unittest.cc b/src/trace_processor/containers/string_pool_unittest.cc
index 0144d7c..eb6dc1b 100644
--- a/src/trace_processor/containers/string_pool_unittest.cc
+++ b/src/trace_processor/containers/string_pool_unittest.cc
@@ -16,66 +16,70 @@
#include "src/trace_processor/containers/string_pool.h"
+#include <array>
#include <random>
#include "test/gtest_and_gmock.h"
namespace perfetto {
namespace trace_processor {
+
+class StringPoolTest : public testing::Test {
+ protected:
+ static constexpr size_t kNumBlockOffsetBits = StringPool::kNumBlockOffsetBits;
+ static constexpr size_t kBlockIndexBitMask = StringPool::kBlockIndexBitMask;
+ static constexpr size_t kBlockSizeBytes = StringPool::kBlockSizeBytes;
+ static constexpr size_t kMinLargeStringSizeBytes =
+ StringPool::kMinLargeStringSizeBytes;
+
+ StringPool pool_;
+};
+
namespace {
-TEST(StringPoolTest, EmptyPool) {
- StringPool pool;
+TEST_F(StringPoolTest, EmptyPool) {
+ ASSERT_EQ(pool_.Get(StringPool::Id::Null()).c_str(), nullptr);
- ASSERT_EQ(pool.Get(0).c_str(), nullptr);
-
- auto it = pool.CreateIterator();
+ auto it = pool_.CreateIterator();
ASSERT_TRUE(it);
ASSERT_EQ(it.StringView().c_str(), nullptr);
ASSERT_FALSE(++it);
}
-TEST(StringPoolTest, InternAndRetrieve) {
- StringPool pool;
-
+TEST_F(StringPoolTest, InternAndRetrieve) {
static char kString[] = "Test String";
- auto id = pool.InternString(kString);
- ASSERT_STREQ(pool.Get(id).c_str(), kString);
- ASSERT_EQ(pool.Get(id), kString);
- ASSERT_EQ(id, pool.InternString(kString));
+ auto id = pool_.InternString(kString);
+ ASSERT_STREQ(pool_.Get(id).c_str(), kString);
+ ASSERT_EQ(pool_.Get(id), kString);
+ ASSERT_EQ(id, pool_.InternString(kString));
}
-TEST(StringPoolTest, NullPointerHandling) {
- StringPool pool;
-
- auto id = pool.InternString(NullTermStringView());
- ASSERT_EQ(id, 0u);
- ASSERT_EQ(pool.Get(id).c_str(), nullptr);
+TEST_F(StringPoolTest, NullPointerHandling) {
+ auto id = pool_.InternString(NullTermStringView());
+ ASSERT_TRUE(id.is_null());
+ ASSERT_EQ(pool_.Get(id).c_str(), nullptr);
}
-TEST(StringPoolTest, Iterator) {
- StringPool pool;
-
- auto it = pool.CreateIterator();
+TEST_F(StringPoolTest, Iterator) {
+ auto it = pool_.CreateIterator();
ASSERT_TRUE(it);
ASSERT_EQ(it.StringView().c_str(), nullptr);
ASSERT_FALSE(++it);
static char kString[] = "Test String";
- pool.InternString(kString);
+ pool_.InternString(kString);
- it = pool.CreateIterator();
+ it = pool_.CreateIterator();
ASSERT_TRUE(++it);
ASSERT_STREQ(it.StringView().c_str(), kString);
ASSERT_FALSE(++it);
}
-TEST(StringPoolTest, ConstIterator) {
- StringPool pool;
+TEST_F(StringPoolTest, ConstIterator) {
static char kString[] = "Test String";
- pool.InternString(kString);
+ pool_.InternString(kString);
- const StringPool& const_pool = pool;
+ const StringPool& const_pool = pool_;
auto it = const_pool.CreateIterator();
ASSERT_TRUE(it);
@@ -84,9 +88,10 @@
ASSERT_FALSE(++it);
}
-TEST(StringPoolTest, StressTest) {
- // First create a buffer with 8MB of random characters.
- constexpr size_t kBufferSize = 8 * 1024 * 1024;
+TEST_F(StringPoolTest, StressTest) {
+ // First create a buffer with 33MB of random characters, so that we insert
+ // into at least two chunks.
+ constexpr size_t kBufferSize = 33 * 1024 * 1024;
std::minstd_rand0 rnd_engine(0);
std::unique_ptr<char[]> buffer(new char[kBufferSize]);
for (size_t i = 0; i < kBufferSize; i++)
@@ -94,7 +99,6 @@
// Next create strings of length 0 to 16k in length from this buffer and
// intern them, storing their ids.
- StringPool pool;
std::multimap<StringPool::Id, base::StringView> string_map;
constexpr uint16_t kMaxStrSize = 16u * 1024u - 1;
for (size_t i = 0;;) {
@@ -103,44 +107,94 @@
break;
auto str = base::StringView(&buffer.get()[i], length);
- string_map.emplace(pool.InternString(str), str);
+ string_map.emplace(pool_.InternString(str), str);
i += length;
}
// Finally, iterate through each string in the string pool, check that all ids
// that match in the multimap are equal, and finish by checking we've removed
// every item in the multimap.
- for (auto it = pool.CreateIterator(); it; ++it) {
- ASSERT_EQ(it.StringView(), pool.Get(it.StringId()));
+ for (auto it = pool_.CreateIterator(); it; ++it) {
+ ASSERT_EQ(it.StringView(), pool_.Get(it.StringId()));
auto it_pair = string_map.equal_range(it.StringId());
for (auto in_it = it_pair.first; in_it != it_pair.second; ++in_it) {
- ASSERT_EQ(it.StringView(), in_it->second);
+ ASSERT_EQ(it.StringView(), in_it->second)
+ << it.StringId().raw_id() << ": " << it.StringView().Hash() << " vs "
+ << in_it->second.Hash();
}
string_map.erase(it_pair.first, it_pair.second);
}
ASSERT_EQ(string_map.size(), 0u);
}
-TEST(StringPoolTest, BigString) {
- constexpr size_t kBigStringSize = 33 * 1024 * 1024;
- std::unique_ptr<char[]> str1(new char[kBigStringSize + 1]);
- std::unique_ptr<char[]> str2(new char[kBigStringSize + 1]);
- for (size_t i = 0; i < kBigStringSize; i++) {
- str1.get()[i] = 'A' + static_cast<char>(i % 32);
- str2.get()[i] = 'A' + static_cast<char>((i + 7) % 32);
+TEST_F(StringPoolTest, BigString) {
+ // Two of these should fit into one block, but the third one should go into
+ // the |large_strings_| list.
+ constexpr size_t kBigStringSize = 15 * 1024 * 1024;
+ // Will fit into block 1 after two kBigStringSize strings.
+ constexpr size_t kSmallStringSize = 16 * 1024;
+ // Will not fit into block 1 anymore after 2*kBigStringSize and
+ // 2*kSmallStringSize, but is smaller than kMinLargeStringSizeBytes, so will
+ // start a new block.
+ constexpr size_t kMediumStringSize = 2 * 1024 * 1024;
+ // Would not fit into a block at all, so ahs to go into |large_strings_|.
+ constexpr size_t kEnormousStringSize = 33 * 1024 * 1024;
+
+ constexpr std::array<size_t, 8> kStringSizes = {
+ kBigStringSize, // block 1
+ kBigStringSize, // block 1
+ kBigStringSize, // large strings
+ kSmallStringSize, // block 1
+ kSmallStringSize, // block 1
+ kMediumStringSize, // block 2
+ kEnormousStringSize, // large strings
+ kBigStringSize // block 2
+ };
+
+ static_assert(kBigStringSize * 2 + kSmallStringSize * 2 + kMediumStringSize >
+ kBlockSizeBytes,
+ "medium string shouldn't fit into block 1 for this test");
+ static_assert(kMediumStringSize < kMinLargeStringSizeBytes,
+ "medium string should cause a new block for this test");
+
+ std::array<std::unique_ptr<char[]>, kStringSizes.size()> big_strings;
+ for (size_t i = 0; i < big_strings.size(); i++) {
+ big_strings[i].reset(new char[kStringSizes[i] + 1]);
+ for (size_t j = 0; j < kStringSizes[i]; j++) {
+ big_strings[i].get()[j] = 'A' + static_cast<char>((j + i) % 26);
+ }
+ big_strings[i].get()[kStringSizes[i]] = '\0';
}
- str1.get()[kBigStringSize] = '\0';
- str2.get()[kBigStringSize] = '\0';
- StringPool pool;
- StringPool::Id id1 =
- pool.InternString(base::StringView(str1.get(), kBigStringSize));
- StringPool::Id id2 =
- pool.InternString(base::StringView(str2.get(), kBigStringSize));
+ std::array<StringPool::Id, kStringSizes.size()> string_ids;
+ for (size_t i = 0; i < big_strings.size(); i++) {
+ string_ids[i] = pool_.InternString(
+ base::StringView(big_strings[i].get(), kStringSizes[i]));
+ // Interning it a second time should return the original id.
+ ASSERT_EQ(string_ids[i], pool_.InternString(base::StringView(
+ big_strings[i].get(), kStringSizes[i])));
+ }
- ASSERT_EQ(str1.get(), pool.Get(id1));
- ASSERT_EQ(str2.get(), pool.Get(id2));
+ ASSERT_FALSE(string_ids[0].is_large_string());
+ ASSERT_FALSE(string_ids[1].is_large_string());
+ ASSERT_TRUE(string_ids[2].is_large_string());
+ ASSERT_FALSE(string_ids[3].is_large_string());
+ ASSERT_FALSE(string_ids[4].is_large_string());
+ ASSERT_FALSE(string_ids[5].is_large_string());
+ ASSERT_TRUE(string_ids[6].is_large_string());
+ ASSERT_FALSE(string_ids[7].is_large_string());
+
+ ASSERT_EQ(string_ids[0].block_index(), 0u);
+ ASSERT_EQ(string_ids[1].block_index(), 0u);
+ ASSERT_EQ(string_ids[3].block_index(), 0u);
+ ASSERT_EQ(string_ids[4].block_index(), 0u);
+ ASSERT_EQ(string_ids[5].block_index(), 1u);
+ ASSERT_EQ(string_ids[7].block_index(), 1u);
+
+ for (size_t i = 0; i < big_strings.size(); i++) {
+ ASSERT_EQ(big_strings[i].get(), pool_.Get(string_ids[i]));
+ }
}
} // namespace
diff --git a/src/trace_processor/db/BUILD.gn b/src/trace_processor/db/BUILD.gn
index be92403..5e15f66 100644
--- a/src/trace_processor/db/BUILD.gn
+++ b/src/trace_processor/db/BUILD.gn
@@ -22,6 +22,7 @@
"table.cc",
"table.h",
"typed_column.h",
+ "typed_column_internal.h",
]
deps = [
"../../../gn:default_deps",
@@ -34,9 +35,7 @@
perfetto_unittest_source_set("unittests") {
testonly = true
- sources = [
- "compare_unittest.cc",
- ]
+ sources = [ "compare_unittest.cc" ]
deps = [
":lib",
"../../../gn:default_deps",
diff --git a/src/trace_processor/db/column.cc b/src/trace_processor/db/column.cc
index fd9f6b2..d8a88b2 100644
--- a/src/trace_processor/db/column.cc
+++ b/src/trace_processor/db/column.cc
@@ -239,6 +239,7 @@
return cmp(sparse_vector<T>().GetNonNull(idx)) >= 0;
});
break;
+ case FilterOp::kGlob:
case FilterOp::kLike:
rm->Intersect(RowMap());
break;
@@ -312,10 +313,11 @@
return v.data() != nullptr && compare::String(v, str_value) >= 0;
});
break;
+ case FilterOp::kGlob:
case FilterOp::kLike:
// TODO(lalitm): either call through to SQLite or reimplement
// like ourselves.
- PERFETTO_DLOG("Ignoring like constraint on string column");
+ PERFETTO_DLOG("Ignoring like/glob constraint on string column");
break;
case FilterOp::kIsNull:
case FilterOp::kIsNotNull:
@@ -372,6 +374,7 @@
return compare::Numeric(idx, id_value) >= 0;
});
break;
+ case FilterOp::kGlob:
case FilterOp::kLike:
rm->Intersect(RowMap());
break;
@@ -451,8 +454,8 @@
auto a_val = sv.GetNonNull(a_idx);
auto b_val = sv.GetNonNull(b_idx);
- int res = compare::Numeric(a_val, b_val);
- return desc ? res > 0 : res < 0;
+ return desc ? compare::Numeric(a_val, b_val) > 0
+ : compare::Numeric(a_val, b_val) < 0;
});
}
diff --git a/src/trace_processor/db/column.h b/src/trace_processor/db/column.h
index ee12912..7321502 100644
--- a/src/trace_processor/db/column.h
+++ b/src/trace_processor/db/column.h
@@ -41,6 +41,7 @@
kIsNull,
kIsNotNull,
kLike,
+ kGlob,
};
// Represents a constraint on a column.
@@ -146,6 +147,39 @@
PERFETTO_FATAL("For GCC");
}
+ // Sets the value of the column at the given |row|.
+ void Set(uint32_t row, SqlValue value) {
+ PERFETTO_CHECK(value.type == type());
+ switch (type_) {
+ case ColumnType::kInt32: {
+ mutable_sparse_vector<int32_t>()->Set(
+ row, static_cast<int32_t>(value.long_value));
+ break;
+ }
+ case ColumnType::kUint32: {
+ mutable_sparse_vector<uint32_t>()->Set(
+ row, static_cast<uint32_t>(value.long_value));
+ break;
+ }
+ case ColumnType::kInt64: {
+ mutable_sparse_vector<int64_t>()->Set(
+ row, static_cast<int64_t>(value.long_value));
+ break;
+ }
+ case ColumnType::kDouble: {
+ mutable_sparse_vector<double>()->Set(row, value.double_value);
+ break;
+ }
+ case ColumnType::kString: {
+ PERFETTO_FATAL(
+ "Setting a generic value on a string column is not implemented");
+ }
+ case ColumnType::kId: {
+ PERFETTO_FATAL("Cannot set value on a id column");
+ }
+ }
+ }
+
// Sorts |idx| in ascending or descending order (determined by |desc|) based
// on the contents of this column.
void StableSort(bool desc, std::vector<uint32_t>* idx) const;
@@ -180,7 +214,7 @@
// Returns the minimum value in this column. Returns nullopt if this column
// is empty.
base::Optional<SqlValue> Min() const {
- if (row_map().size() == 0)
+ if (row_map().empty())
return base::nullopt;
if (IsSorted())
@@ -194,7 +228,7 @@
// Returns the minimum value in this column. Returns nullopt if this column
// is empty.
base::Optional<SqlValue> Max() const {
- if (row_map().size() == 0)
+ if (row_map().empty())
return base::nullopt;
if (IsSorted())
@@ -275,13 +309,6 @@
JoinKey join_key() const { return JoinKey{col_idx_in_table_}; }
protected:
- // Returns the string at the index |idx|.
- // Should only be called when |type_| == ColumnType::kString.
- NullTermStringView GetStringPoolStringAtIdx(uint32_t idx) const {
- PERFETTO_DCHECK(type_ == ColumnType::kString);
- return string_pool_->Get(sparse_vector<StringPool::Id>().GetNonNull(idx));
- }
-
// Returns the backing sparse vector cast to contain data of type T.
// Should only be called when |type_| == ToColumnType<T>().
template <typename T>
@@ -298,17 +325,6 @@
return *static_cast<const SparseVector<T>*>(sparse_vector_);
}
- // Converts a primitive numeric value to an SqlValue of the correct type.
- template <typename T>
- static SqlValue NumericToSqlValue(T value) {
- if (std::is_same<T, double>::value) {
- return SqlValue::Double(value);
- } else if (std::is_convertible<T, int64_t>::value) {
- return SqlValue::Long(value);
- }
- PERFETTO_FATAL("Invalid type");
- }
-
const StringPool& string_pool() const { return *string_pool_; }
private:
@@ -451,6 +467,7 @@
rm->Intersect(RowMap(beg, row_map().size()));
return true;
}
+ case FilterOp::kGlob:
case FilterOp::kNe:
case FilterOp::kIsNull:
case FilterOp::kIsNotNull:
@@ -506,6 +523,13 @@
}
}
+ // Returns the string at the index |idx|.
+ // Should only be called when |type_| == ColumnType::kString.
+ NullTermStringView GetStringPoolStringAtIdx(uint32_t idx) const {
+ PERFETTO_DCHECK(type_ == ColumnType::kString);
+ return string_pool_->Get(sparse_vector<StringPool::Id>().GetNonNull(idx));
+ }
+
// type_ is used to cast sparse_vector_ to the correct type.
ColumnType type_ = ColumnType::kInt64;
void* sparse_vector_ = nullptr;
diff --git a/src/trace_processor/db/compare.h b/src/trace_processor/db/compare.h
index 9f3f9a5..0eb89b1 100644
--- a/src/trace_processor/db/compare.h
+++ b/src/trace_processor/db/compare.h
@@ -17,6 +17,7 @@
#ifndef SRC_TRACE_PROCESSOR_DB_COMPARE_H_
#define SRC_TRACE_PROCESSOR_DB_COMPARE_H_
+#include <algorithm>
#include <stdint.h>
#include "perfetto/ext/base/optional.h"
diff --git a/src/trace_processor/db/typed_column.h b/src/trace_processor/db/typed_column.h
index a7183f6..272d465 100644
--- a/src/trace_processor/db/typed_column.h
+++ b/src/trace_processor/db/typed_column.h
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2019 The Android Open Source Project
+ * Copyright (C) 2020 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.
@@ -18,11 +18,140 @@
#define SRC_TRACE_PROCESSOR_DB_TYPED_COLUMN_H_
#include "src/trace_processor/db/column.h"
+#include "src/trace_processor/db/typed_column_internal.h"
namespace perfetto {
namespace trace_processor {
+// TypedColumn<T>
+//
+// Introduction:
+// TypedColumn exists to allow efficient access to the data in a Column without
+// having to go through dynamic type checking. There are two main reasons for
+// this:
+// 1. Performance: dynamic type checking is not free and so if this is used
+// in a particularily hot codepath, the typechecking can be a significant
+// overhead.
+// 2. Ergonomics: having to convert back and forth from/to SqlValue causes
+// signifcant clutter in parts of the code which can already be quite hard
+// to follow (e.g. trackers like StackProfileTracker which perform cross
+// checking of various ids).
+//
+// Implementation:
+// TypedColumn is implemented as a memberless subclass of Column. This allows
+// us to reinterpret case from a Column* to a TypedColumn<T> where we know the
+// type T. The methods of TypedColumn are type-specialized methods of Column
+// which allow callers to pass raw types instead of using SqlValue.
+//
+// There are two helper classes (tc_internal::TypeHandler and
+// tc_internal::Serializer) where we specialize behaviour which needs to be
+// different based on T. See their class documentation and below for details
+// on their purpose.
+template <typename T>
+struct TypedColumn : public Column {
+ private:
+ using TH = tc_internal::TypeHandler<T>;
+
+ // The non-optional type of the data in this column.
+ using non_optional_type =
+ typename tc_internal::TypeHandler<T>::non_optional_type;
+
+ // The type of data in this column (including Optional wrapper if the type
+ // should be optional).
+ using get_type = typename tc_internal::TypeHandler<T>::get_type;
+
+ // The type which should be passed to SqlValue functions.
+ using sql_value_type = typename tc_internal::TypeHandler<T>::sql_value_type;
+
+ using Serializer = tc_internal::Serializer<non_optional_type>;
+
+ public:
+ // The type which should be stored in the SparseVector.
+ // Used by the macro code when actually constructing the SparseVectors.
+ using serialized_type = typename Serializer::serialized_type;
+
+ // Returns the data in the column at index |row|.
+ // Function chosen when TH::is_optional == true.
+ template <bool is_optional = TH::is_optional>
+ typename std::enable_if<is_optional, get_type>::type operator[](
+ uint32_t row) const {
+ return Serializer::Deserialize(sparse_vector().Get(row_map().Get(row)));
+ }
+
+ // Function chosen when TH::is_optional == false.
+ template <bool is_optional = TH::is_optional>
+ typename std::enable_if<!is_optional, get_type>::type operator[](
+ uint32_t row) const {
+ return Serializer::Deserialize(
+ sparse_vector().GetNonNull(row_map().Get(row)));
+ }
+
+ // Special function only for string types to allow retrieving the string
+ // directly from the column.
+ template <bool is_string = TH::is_string>
+ typename std::enable_if<is_string, NullTermStringView>::type GetString(
+ uint32_t row) const {
+ return string_pool().Get((*this)[row]);
+ }
+
+ // Sets the data in the column at index |row|.
+ void Set(uint32_t row, non_optional_type v) {
+ auto serialized = Serializer::Serialize(v);
+ mutable_sparse_vector()->Set(row_map().Get(row), serialized);
+ }
+
+ // Inserts the value at the end of the column.
+ void Append(T v) {
+ mutable_sparse_vector()->Append(Serializer::Serialize(v));
+ }
+
+ // Returns the row containing the given value in the Column.
+ base::Optional<uint32_t> IndexOf(sql_value_type v) const {
+ return Column::IndexOf(ToValue(v));
+ }
+
+ std::vector<get_type> ToVectorForTesting() const {
+ std::vector<T> result(row_map().size());
+ for (uint32_t i = 0; i < row_map().size(); ++i)
+ result[i] = (*this)[i];
+ return result;
+ }
+
+ // Helper functions to create constraints for the given value.
+ Constraint eq(sql_value_type v) const { return eq_value(ToValue(v)); }
+ Constraint gt(sql_value_type v) const { return gt_value(ToValue(v)); }
+ Constraint lt(sql_value_type v) const { return lt_value(ToValue(v)); }
+ Constraint ne(sql_value_type v) const { return ne_value(ToValue(v)); }
+ Constraint ge(sql_value_type v) const { return ge_value(ToValue(v)); }
+ Constraint le(sql_value_type v) const { return le_value(ToValue(v)); }
+
+ // Implements equality between two items of type |T|.
+ static constexpr bool Equals(T a, T b) { return TH::Equals(a, b); }
+
+ // Encodes the default flags for a column of the current type.
+ static constexpr uint32_t default_flags() {
+ return TH::is_optional ? Flag::kNoFlag : Flag::kNonNull;
+ }
+
+ private:
+ static SqlValue ToValue(double value) { return SqlValue::Double(value); }
+ static SqlValue ToValue(uint32_t value) { return SqlValue::Long(value); }
+ static SqlValue ToValue(int64_t value) { return SqlValue::Long(value); }
+ static SqlValue ToValue(NullTermStringView value) {
+ return SqlValue::String(value.c_str());
+ }
+
+ const SparseVector<serialized_type>& sparse_vector() const {
+ return Column::sparse_vector<serialized_type>();
+ }
+ SparseVector<serialized_type>* mutable_sparse_vector() {
+ return Column::mutable_sparse_vector<serialized_type>();
+ }
+};
+
// Represents a column containing ids.
+// TODO(lalitm): think about unifying this with TypedColumn in the
+// future.
template <typename Id>
struct IdColumn : public Column {
Id operator[](uint32_t row) const { return Id(row_map().Get(row)); }
@@ -39,168 +168,6 @@
Constraint le(uint32_t v) const { return le_value(SqlValue::Long(v)); }
};
-// Represents a column containing data with the given type T.
-//
-// This class exists as a memberless subclass of Column (i.e. sizeof(Column) ==
-// sizeof(TypedColumn<T>)); this is because Columns are type erased but we still
-// want low boilerplate methods to get/set rows in columns where we know the
-// type.
-template <typename T>
-struct TypedColumn : public Column {
- using StoredType = T;
-
- // Returns the data in the column at index |row|.
- T operator[](uint32_t row) const {
- return sparse_vector<T>().GetNonNull(row_map().Get(row));
- }
-
- // Sets the data in the column at index |row|.
- void Set(uint32_t row, T v) {
- mutable_sparse_vector<T>()->Set(row_map().Get(row), v);
- }
-
- // Inserts the value at the end of the column.
- void Append(T v) { mutable_sparse_vector<T>()->Append(v); }
-
- // Returns the row containing the given value in the Column.
- base::Optional<uint32_t> IndexOf(T v) const {
- return Column::IndexOf(NumericToSqlValue(v));
- }
-
- // Implements equality between two items of type |T|.
- static bool Equals(T a, T b) {
- // We need to use equal_to here as it could be T == double and because we
- // enable all compile time warnings, we will get complaints if we just use
- // a == b.
- return std::equal_to<T>()(a, b);
- }
-
- // Helper functions to create constraints for the given value.
- Constraint eq(T v) const { return eq_value(NumericToSqlValue(v)); }
- Constraint gt(T v) const { return gt_value(NumericToSqlValue(v)); }
- Constraint lt(T v) const { return lt_value(NumericToSqlValue(v)); }
- Constraint ne(T v) const { return ne_value(NumericToSqlValue(v)); }
- Constraint ge(T v) const { return ge_value(NumericToSqlValue(v)); }
- Constraint le(T v) const { return le_value(NumericToSqlValue(v)); }
-
- // Encodes the default flags for a column of the current type.
- static constexpr uint32_t default_flags() { return Flag::kNonNull; }
-};
-
-template <typename T>
-struct TypedColumn<base::Optional<T>> : public Column {
- using StoredType = T;
-
- // Returns the data in the column at index |row|.
- base::Optional<T> operator[](uint32_t row) const {
- return sparse_vector<T>().Get(row_map().Get(row));
- }
-
- // Sets the data in the column at index |row|.
- void Set(uint32_t row, T v) {
- mutable_sparse_vector<T>()->Set(row_map().Get(row), v);
- }
-
- // Inserts the value at the end of the column.
- void Append(base::Optional<T> v) { mutable_sparse_vector<T>()->Append(v); }
-
- // Implements equality between two items of type |T|.
- static bool Equals(base::Optional<T> a, base::Optional<T> b) {
- // We need to use equal_to here as it could be T == double and because we
- // enable all compile time warnings, we will get complaints if we just use
- // a == b. This is the same reason why we can't also just use equal_to using
- // a and b directly because the optional implementation of equality uses
- // == which again causes complaints.
- return a.has_value() == b.has_value() &&
- (!a.has_value() || std::equal_to<T>()(*a, *b));
- }
-
- // Helper functions to create constraints for the given value.
- Constraint eq(T v) const { return eq_value(NumericToSqlValue(v)); }
- Constraint gt(T v) const { return gt_value(NumericToSqlValue(v)); }
- Constraint lt(T v) const { return lt_value(NumericToSqlValue(v)); }
- Constraint ne(T v) const { return ne_value(NumericToSqlValue(v)); }
- Constraint ge(T v) const { return ge_value(NumericToSqlValue(v)); }
- Constraint le(T v) const { return le_value(NumericToSqlValue(v)); }
-
- // Encodes the default flags for a column of the current type.
- static constexpr uint32_t default_flags() { return Flag::kNoFlag; }
-};
-
-template <>
-struct TypedColumn<StringPool::Id> : public Column {
- using StoredType = StringPool::Id;
-
- // Returns the data in the column at index |row|.
- StringPool::Id operator[](uint32_t row) const {
- return sparse_vector<StringPool::Id>().GetNonNull(row_map().Get(row));
- }
-
- // Returns the string in the column by looking up the id at |row| in the
- // StringPool.
- NullTermStringView GetString(uint32_t row) const {
- return GetStringPoolStringAtIdx(row_map().Get(row));
- }
-
- // Sets the data in the column at index |row|.
- void Set(uint32_t row, StringPool::Id v) {
- mutable_sparse_vector<StringPool::Id>()->Set(row_map().Get(row), v);
- }
-
- // Inserts the value at the end of the column.
- void Append(StringPool::Id v) {
- mutable_sparse_vector<StringPool::Id>()->Append(v);
- }
-
- // Returns the row containing the given value in the Column.
- base::Optional<uint32_t> IndexOf(StringPool::Id v) const {
- return Column::IndexOf(SqlValue::String(string_pool().Get(v).c_str()));
- }
-
- // Returns the row containing the given value in the Column.
- base::Optional<uint32_t> IndexOf(NullTermStringView v) const {
- return Column::IndexOf(SqlValue::String(v.c_str()));
- }
-
- // Implements equality between two items of type |T|.
- static bool Equals(StringPool::Id a, StringPool::Id b) { return a == b; }
-
- // Helper functions to create constraints for the given value.
- Constraint eq(const char* v) const { return eq_value(SqlValue::String(v)); }
- Constraint gt(const char* v) const { return gt_value(SqlValue::String(v)); }
- Constraint lt(const char* v) const { return lt_value(SqlValue::String(v)); }
- Constraint ne(const char* v) const { return ne_value(SqlValue::String(v)); }
- Constraint ge(const char* v) const { return ge_value(SqlValue::String(v)); }
- Constraint le(const char* v) const { return le_value(SqlValue::String(v)); }
-
- static constexpr uint32_t default_flags() { return Flag::kNonNull; }
-};
-
-template <>
-struct TypedColumn<base::Optional<StringPool::Id>>
- : public TypedColumn<StringPool::Id> {
- // Inserts the value at the end of the column.
- void Append(base::Optional<StringPool::Id> v) {
- // Since StringPool::Id == 0 is always treated as null, rewrite
- // base::nullopt -> 0 to remove an extra check at filter time for
- // base::nullopt. Instead, that code can assume that the SparseVector
- // layer always returns a valid id and can handle the nullability at the
- // stringpool level.
- // TODO(lalitm): remove this special casing if we migrate all tables over
- // to macro tables and find that we can remove support for null stringids
- // in the stringpool.
- return TypedColumn<StringPool::Id>::Append(v ? *v : StringPool::Id(0u));
- }
-
- // Implements equality between two items of type |T|.
- static bool Equals(base::Optional<StringPool::Id> a,
- base::Optional<StringPool::Id> b) {
- return a == b;
- }
-
- static constexpr uint32_t default_flags() { return Flag::kNonNull; }
-};
-
} // namespace trace_processor
} // namespace perfetto
diff --git a/src/trace_processor/db/typed_column_internal.h b/src/trace_processor/db/typed_column_internal.h
new file mode 100644
index 0000000..181a3a2
--- /dev/null
+++ b/src/trace_processor/db/typed_column_internal.h
@@ -0,0 +1,151 @@
+/*
+ * Copyright (C) 2020 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.
+ */
+
+#ifndef SRC_TRACE_PROCESSOR_DB_TYPED_COLUMN_INTERNAL_H_
+#define SRC_TRACE_PROCESSOR_DB_TYPED_COLUMN_INTERNAL_H_
+
+#include "src/trace_processor/db/column.h"
+
+namespace perfetto {
+namespace trace_processor {
+namespace tc_internal {
+
+// Serializer converts between the "public" type used by the rest of trace
+// processor and the type we store in the SparseVector.
+template <typename T, typename Enabled = void>
+struct Serializer {
+ using serialized_type = T;
+
+ static serialized_type Serialize(T value) { return value; }
+ static T Deserialize(serialized_type value) { return value; }
+
+ static base::Optional<serialized_type> Serialize(base::Optional<T> value) {
+ return value;
+ }
+ static base::Optional<T> Deserialize(base::Optional<serialized_type> value) {
+ return value;
+ }
+};
+
+// Specialization of Serializer for StringPool types.
+template <>
+struct Serializer<StringPool::Id> {
+ using serialized_type = StringPool::Id;
+
+ static serialized_type Serialize(StringPool::Id value) { return value; }
+ static StringPool::Id Deserialize(serialized_type value) { return value; }
+
+ static serialized_type Serialize(base::Optional<StringPool::Id> value) {
+ // Since StringPool::Id == 0 is always treated as null, rewrite
+ // base::nullopt -> 0 to remove an extra check at filter time for
+ // base::nullopt. Instead, that code can assume that the SparseVector
+ // layer always returns a valid id and can handle the nullability at the
+ // stringpool level.
+ // TODO(lalitm): remove this special casing if we migrate all tables over
+ // to macro tables and find that we can remove support for null stringids
+ // in the stringpool.
+ return value ? Serialize(*value) : StringPool::Id::Null();
+ }
+ static base::Optional<serialized_type> Deserialize(
+ base::Optional<StringPool::Id>) {
+ PERFETTO_FATAL("Should never be storing optional StringPool ids");
+ }
+};
+
+// TypeHandler (and it's specializations) allow for specialied handling of
+// functions of a TypedColumn based on what is being stored inside.
+// Default implementation of TypeHandler.
+template <typename T, typename Enable = void>
+struct TypeHandler {
+ using non_optional_type = T;
+ using get_type = T;
+ using sql_value_type = T;
+
+ static constexpr bool is_optional = false;
+ static constexpr bool is_string = false;
+
+ static bool Equals(T a, T b) {
+ // We need to use equal_to here as it could be T == double and because we
+ // enable all compile time warnings, we will get complaints if we just use
+ // a == b.
+ return std::equal_to<T>()(a, b);
+ }
+};
+
+// Specialization for Optional types.
+template <typename T>
+struct TypeHandler<base::Optional<T>> {
+ using non_optional_type = T;
+ using get_type = base::Optional<T>;
+ using sql_value_type = T;
+
+ static constexpr bool is_optional = true;
+ static constexpr bool is_string = false;
+
+ static bool Equals(base::Optional<T> a, base::Optional<T> b) {
+ // We need to use equal_to here as it could be T == double and because we
+ // enable all compile time warnings, we will get complaints if we just use
+ // a == b. This is the same reason why we can't also just use equal_to using
+ // a and b directly because the optional implementation of equality uses
+ // == which again causes complaints.
+ return a.has_value() == b.has_value() &&
+ (!a.has_value() || std::equal_to<T>()(*a, *b));
+ }
+};
+
+// Specialization for Optional<StringId> types.
+template <>
+struct TypeHandler<StringPool::Id> {
+ // get_type removes the base::Optional since we convert base::nullopt ->
+ // StringPool::Id::Null (see Serializer<StringPool> above).
+ using non_optional_type = StringPool::Id;
+ using get_type = StringPool::Id;
+ using sql_value_type = NullTermStringView;
+
+ static constexpr bool is_optional = false;
+ static constexpr bool is_string = true;
+
+ static bool Equals(StringPool::Id a, StringPool::Id b) { return a == b; }
+};
+
+// Specialization for Optional<StringId> types.
+template <>
+struct TypeHandler<base::Optional<StringPool::Id>> {
+ // get_type removes the base::Optional since we convert base::nullopt ->
+ // StringPool::Id::Null (see Serializer<StringPool> above).
+ using non_optional_type = StringPool::Id;
+ using get_type = StringPool::Id;
+ using sql_value_type = NullTermStringView;
+
+ // is_optional is false again because we always unwrap
+ // base::Optional<StringPool::Id> into StringPool::Id.
+ static constexpr bool is_optional = false;
+ static constexpr bool is_string = true;
+
+ static bool Equals(base::Optional<StringPool::Id> a,
+ base::Optional<StringPool::Id> b) {
+ // To match our handling of treating base::nullopt ==
+ // StringPool::Id::Null(), ensure that they both compare equal to each
+ // other.
+ return a == b || (!a && b->is_null()) || (!b && a->is_null());
+ }
+};
+
+} // namespace tc_internal
+} // namespace trace_processor
+} // namespace perfetto
+
+#endif // SRC_TRACE_PROCESSOR_DB_TYPED_COLUMN_INTERNAL_H_
diff --git a/src/trace_processor/event_tracker.cc b/src/trace_processor/event_tracker.cc
index 348ac68..cd7c9e4 100644
--- a/src/trace_processor/event_tracker.cc
+++ b/src/trace_processor/event_tracker.cc
@@ -25,7 +25,7 @@
#include "src/trace_processor/stats.h"
#include "src/trace_processor/trace_processor_context.h"
#include "src/trace_processor/track_tracker.h"
-#include "src/trace_processor/variadic.h"
+#include "src/trace_processor/types/variadic.h"
namespace perfetto {
namespace trace_processor {
@@ -91,11 +91,12 @@
}
void EventTracker::FlushPendingEvents() {
+ const auto& thread_table = context_->storage->thread_table();
for (const auto& pending_counter : pending_upid_resolution_counter_) {
- const auto& thread = context_->storage->GetThread(pending_counter.utid);
// TODO(lalitm): having upid == 0 is probably not the correct approach here
// but it's unclear what may be better.
- UniquePid upid = thread.upid.value_or(0);
+ UniqueTid utid = pending_counter.utid;
+ UniquePid upid = thread_table.upid()[utid].value_or(0);
TrackId id = context_->track_tracker->InternProcessCounterTrack(
pending_counter.name_id, upid);
context_->storage->mutable_counter_table()->mutable_track_id()->Set(
@@ -103,10 +104,10 @@
}
for (const auto& pending_instant : pending_upid_resolution_instant_) {
- const auto& thread = context_->storage->GetThread(pending_instant.utid);
+ UniqueTid utid = pending_instant.utid;
// TODO(lalitm): having upid == 0 is probably not the correct approach here
// but it's unclear what may be better.
- UniquePid upid = thread.upid.value_or(0);
+ UniquePid upid = thread_table.upid()[utid].value_or(0);
context_->storage->mutable_instant_table()->mutable_ref()->Set(
pending_instant.row, upid);
}
diff --git a/src/trace_processor/event_tracker.h b/src/trace_processor/event_tracker.h
index 983dad0..bde0588 100644
--- a/src/trace_processor/event_tracker.h
+++ b/src/trace_processor/event_tracker.h
@@ -76,7 +76,7 @@
// Represents a counter event which is currently pending upid resolution.
struct PendingUpidResolutionCounter {
uint32_t row = 0;
- StringId name_id = 0;
+ StringId name_id = kNullStringId;
UniqueTid utid = 0;
};
diff --git a/src/trace_processor/event_tracker_unittest.cc b/src/trace_processor/event_tracker_unittest.cc
index 4fadf41..d8f41ed 100644
--- a/src/trace_processor/event_tracker_unittest.cc
+++ b/src/trace_processor/event_tracker_unittest.cc
@@ -35,6 +35,7 @@
public:
EventTrackerTest() {
context.storage.reset(new TraceStorage());
+ context.global_args_tracker.reset(new GlobalArgsTracker(&context));
context.args_tracker.reset(new ArgsTracker(&context));
context.process_tracker.reset(new ProcessTracker(&context));
context.event_tracker.reset(new EventTracker(&context));
@@ -67,10 +68,11 @@
ASSERT_EQ(timestamps.size(), 2ul);
ASSERT_EQ(timestamps[0], timestamp);
- ASSERT_EQ(context.storage->GetThread(1).start_ns, 0);
- ASSERT_STREQ(
- context.storage->GetString(context.storage->GetThread(1).name_id).c_str(),
- kCommProc1);
+ ASSERT_EQ(context.storage->thread_table().start_ts()[1], base::nullopt);
+
+ auto name =
+ context.storage->GetString(context.storage->thread_table().name()[1]);
+ ASSERT_STREQ(name.c_str(), kCommProc1);
ASSERT_EQ(context.storage->slices().utids().front(), 1u);
ASSERT_EQ(context.storage->slices().durations().front(), 1);
}
@@ -101,7 +103,7 @@
ASSERT_EQ(timestamps.size(), 4ul);
ASSERT_EQ(timestamps[0], timestamp);
- ASSERT_EQ(context.storage->GetThread(1).start_ns, 0);
+ ASSERT_EQ(context.storage->thread_table().start_ts()[1], base::nullopt);
ASSERT_EQ(context.storage->slices().durations().at(0), 1u);
ASSERT_EQ(context.storage->slices().durations().at(1), 11u - 1u);
ASSERT_EQ(context.storage->slices().durations().at(2), 31u - 11u);
@@ -112,7 +114,7 @@
TEST_F(EventTrackerTest, CounterDuration) {
uint32_t cpu = 3;
int64_t timestamp = 100;
- StringId name_id = 0;
+ StringId name_id = kNullStringId;
TrackId track = context.track_tracker->InternCpuCounterTrack(name_id, cpu);
context.event_tracker->PushCounter(timestamp, 1000, track);
diff --git a/src/trace_processor/export_json.cc b/src/trace_processor/export_json.cc
index 4aa62b9..42370f7 100644
--- a/src/trace_processor/export_json.cc
+++ b/src/trace_processor/export_json.cc
@@ -27,11 +27,13 @@
#include <json/writer.h>
#include <stdio.h>
+#include <algorithm>
#include <cstring>
#include <deque>
#include <limits>
#include "perfetto/ext/base/string_splitter.h"
+#include "perfetto/ext/base/string_utils.h"
#include "src/trace_processor/metadata.h"
#include "src/trace_processor/trace_processor_context.h"
#include "src/trace_processor/trace_processor_storage_impl.h"
@@ -46,7 +48,7 @@
using IndexMap = perfetto::trace_processor::TraceStorage::Stats::IndexMap;
const char kLegacyEventArgsKey[] = "legacy_event";
-const char kLegacyEventOriginalTidKey[] = "original_tid";
+const char kLegacyEventPassthroughUtidKey[] = "passthrough_utid";
const char kLegacyEventCategoryKey[] = "category";
const char kLegacyEventNameKey[] = "name";
const char kLegacyEventPhaseKey[] = "phase";
@@ -72,388 +74,12 @@
return id == kNullStringId ? "" : storage->GetString(id).c_str();
}
-class FileWriter : public OutputWriter {
- public:
- FileWriter(FILE* file) : file_(file) {}
- ~FileWriter() override { fflush(file_); }
-
- util::Status AppendString(const std::string& s) override {
- size_t written =
- fwrite(s.data(), sizeof(std::string::value_type), s.size(), file_);
- if (written != s.size())
- return util::ErrStatus("Error writing to file: %d", ferror(file_));
- return util::OkStatus();
- }
-
- private:
- FILE* file_;
-};
-
-class TraceFormatWriter {
- public:
- TraceFormatWriter(OutputWriter* output,
- ArgumentFilterPredicate argument_filter,
- MetadataFilterPredicate metadata_filter,
- LabelFilterPredicate label_filter)
- : output_(output),
- argument_filter_(argument_filter),
- metadata_filter_(metadata_filter),
- label_filter_(label_filter),
- first_event_(true) {
- WriteHeader();
- }
-
- ~TraceFormatWriter() { WriteFooter(); }
-
- void WriteCommonEvent(const Json::Value& event) {
- if (label_filter_ && !label_filter_("traceEvents"))
- return;
-
- // Pop end events with smaller or equal timestamps.
- PopEndEvents(event["ts"].asInt64());
-
- DoWriteEvent(event);
- }
-
- void PushEndEvent(const Json::Value& event) {
- if (label_filter_ && !label_filter_("traceEvents"))
- return;
-
- // Pop any end events that end before the new one.
- PopEndEvents(event["ts"].asInt64() - 1);
-
- // Catapult doesn't handle out-of-order begin/end events well, especially
- // when their timestamps are the same, but their order is incorrect. Since
- // our events are sorted by begin timestamp, we only have to reorder end
- // events. We do this by buffering them into a stack, so that both begin &
- // end events of potential child events have been emitted before we emit the
- // end of a parent event.
- end_events_.push_back(event);
- }
-
- void WriteMetadataEvent(const char* metadata_type,
- const char* metadata_value,
- uint32_t tid,
- uint32_t pid) {
- if (label_filter_ && !label_filter_("traceEvents"))
- return;
-
- if (!first_event_)
- output_->AppendString(",\n");
-
- Json::FastWriter writer;
- writer.omitEndingLineFeed();
- Json::Value value;
- value["ph"] = "M";
- value["cat"] = "__metadata";
- value["ts"] = 0;
- value["name"] = metadata_type;
- value["tid"] = static_cast<int32_t>(tid);
- value["pid"] = static_cast<int32_t>(pid);
-
- Json::Value args;
- args["name"] = metadata_value;
- value["args"] = args;
-
- output_->AppendString(writer.write(value));
- first_event_ = false;
- }
-
- void MergeMetadata(const Json::Value& value) {
- for (const auto& member : value.getMemberNames()) {
- metadata_[member] = value[member];
- }
- }
-
- void AppendTelemetryMetadataString(const char* key, const char* value) {
- metadata_["telemetry"][key].append(value);
- }
-
- void AppendTelemetryMetadataInt(const char* key, int64_t value) {
- metadata_["telemetry"][key].append(Json::Int64(value));
- }
-
- void AppendTelemetryMetadataBool(const char* key, bool value) {
- metadata_["telemetry"][key].append(value);
- }
-
- void SetTelemetryMetadataTimestamp(const char* key, int64_t value) {
- metadata_["telemetry"][key] = value / 1000.0;
- }
-
- void SetStats(const char* key, int64_t value) {
- metadata_["trace_processor_stats"][key] = Json::Int64(value);
- }
-
- void SetStats(const char* key, const IndexMap& indexed_values) {
- constexpr const char* kBufferStatsPrefix = "traced_buf_";
-
- // Stats for the same buffer should be grouped together in the JSON.
- if (strncmp(kBufferStatsPrefix, key, strlen(kBufferStatsPrefix)) == 0) {
- for (const auto& value : indexed_values) {
- metadata_["trace_processor_stats"]["traced_buf"][value.first]
- [key + strlen(kBufferStatsPrefix)] = Json::Int64(value.second);
- }
- return;
- }
-
- // Other indexed value stats are exported as array under their key.
- for (const auto& value : indexed_values) {
- metadata_["trace_processor_stats"][key][value.first] =
- Json::Int64(value.second);
- }
- }
-
- void AddSystemTraceData(const std::string& data) {
- system_trace_data_ += data;
- }
-
- void AddUserTraceData(const std::string& data) {
- if (user_trace_data_.empty())
- user_trace_data_ = "[";
- user_trace_data_ += data;
- }
-
- private:
- void WriteHeader() {
- if (!label_filter_)
- output_->AppendString("{\"traceEvents\":[\n");
- }
-
- void WriteFooter() {
- PopEndEvents(std::numeric_limits<int64_t>::max());
-
- // Filter metadata entries.
- if (metadata_filter_) {
- for (const auto& member : metadata_.getMemberNames()) {
- if (!metadata_filter_(member.c_str()))
- metadata_[member] = kStrippedArgument;
- }
- }
-
- Json::FastWriter writer;
- writer.omitEndingLineFeed();
- if ((!label_filter_ || label_filter_("traceEvents")) &&
- !user_trace_data_.empty()) {
- user_trace_data_ += "]";
- Json::Reader reader;
- Json::Value result;
- if (reader.parse(user_trace_data_, result)) {
- for (const auto& event : result) {
- WriteCommonEvent(event);
- }
- } else {
- PERFETTO_DLOG(
- "can't parse legacy user json trace export, skipping. data: %s",
- user_trace_data_.c_str());
- }
- }
- if (!label_filter_)
- output_->AppendString("]");
- if ((!label_filter_ || label_filter_("systemTraceEvents")) &&
- !system_trace_data_.empty()) {
- output_->AppendString(",\"systemTraceEvents\":\n");
- output_->AppendString(writer.write(Json::Value(system_trace_data_)));
- }
- if ((!label_filter_ || label_filter_("metadata")) && !metadata_.empty()) {
- output_->AppendString(",\"metadata\":\n");
- output_->AppendString(writer.write(metadata_));
- }
- if (!label_filter_)
- output_->AppendString("}");
- }
-
- void DoWriteEvent(const Json::Value& event) {
- if (!first_event_)
- output_->AppendString(",\n");
-
- Json::FastWriter writer;
- writer.omitEndingLineFeed();
-
- ArgumentNameFilterPredicate argument_name_filter;
- bool strip_args =
- argument_filter_ &&
- !argument_filter_(event["cat"].asCString(), event["name"].asCString(),
- &argument_name_filter);
- if ((strip_args || argument_name_filter) && event.isMember("args")) {
- Json::Value event_copy = event;
- if (strip_args) {
- event_copy["args"] = kStrippedArgument;
- } else {
- auto& args = event_copy["args"];
- for (const auto& member : event["args"].getMemberNames()) {
- if (!argument_name_filter(member.c_str()))
- args[member] = kStrippedArgument;
- }
- }
- output_->AppendString(writer.write(event_copy));
- } else {
- output_->AppendString(writer.write(event));
- }
- first_event_ = false;
- }
-
- void PopEndEvents(int64_t max_ts) {
- while (!end_events_.empty()) {
- int64_t ts = end_events_.back()["ts"].asInt64();
- if (ts > max_ts)
- break;
- DoWriteEvent(end_events_.back());
- end_events_.pop_back();
- }
- }
-
- OutputWriter* output_;
- ArgumentFilterPredicate argument_filter_;
- MetadataFilterPredicate metadata_filter_;
- LabelFilterPredicate label_filter_;
-
- bool first_event_;
- Json::Value metadata_;
- std::string system_trace_data_;
- std::string user_trace_data_;
- std::deque<Json::Value> end_events_;
-};
-
std::string PrintUint64(uint64_t x) {
char hex_str[19];
sprintf(hex_str, "0x%" PRIx64, x);
return hex_str;
}
-class ArgsBuilder {
- public:
- explicit ArgsBuilder(const TraceStorage* storage)
- : storage_(storage),
- empty_value_(Json::objectValue),
- nan_value_(Json::StaticString("NaN")),
- inf_value_(Json::StaticString("Infinity")),
- neg_inf_value_(Json::StaticString("-Infinity")) {
- const TraceStorage::Args& args = storage->args();
- if (args.args_count() == 0) {
- args_sets_.resize(1, empty_value_);
- return;
- }
- args_sets_.resize(args.set_ids().back() + 1, empty_value_);
- for (size_t i = 0; i < args.args_count(); ++i) {
- ArgSetId set_id = args.set_ids()[i];
- const char* key = GetNonNullString(storage_, args.keys()[i]);
- Variadic value = args.arg_values()[i];
- AppendArg(set_id, key, VariadicToJson(value));
- }
- PostprocessArgs();
- }
-
- const Json::Value& GetArgs(ArgSetId set_id) const {
- // If |set_id| was empty and added to the storage last, it may not be in
- // args_sets_.
- if (set_id > args_sets_.size())
- return empty_value_;
- return args_sets_[set_id];
- }
-
- private:
- Json::Value VariadicToJson(Variadic variadic) {
- switch (variadic.type) {
- case Variadic::kInt:
- return Json::Int64(variadic.int_value);
- case Variadic::kUint:
- return Json::UInt64(variadic.uint_value);
- case Variadic::kString:
- return GetNonNullString(storage_, variadic.string_value);
- case Variadic::kReal:
- if (std::isnan(variadic.real_value)) {
- return nan_value_;
- } else if (std::isinf(variadic.real_value) && variadic.real_value > 0) {
- return inf_value_;
- } else if (std::isinf(variadic.real_value) && variadic.real_value < 0) {
- return neg_inf_value_;
- } else {
- return variadic.real_value;
- }
- case Variadic::kPointer:
- return PrintUint64(variadic.pointer_value);
- case Variadic::kBool:
- return variadic.bool_value;
- case Variadic::kJson:
- Json::Reader reader;
- Json::Value result;
- reader.parse(GetNonNullString(storage_, variadic.json_value), result);
- return result;
- }
- PERFETTO_FATAL("Not reached"); // For gcc.
- }
-
- void AppendArg(ArgSetId set_id,
- const std::string& key,
- const Json::Value& value) {
- Json::Value* target = &args_sets_[set_id];
- for (base::StringSplitter parts(key, '.'); parts.Next();) {
- if (PERFETTO_UNLIKELY(!target->isNull() && !target->isObject())) {
- PERFETTO_DLOG("Malformed arguments. Can't append %s to %s.",
- key.c_str(), args_sets_[set_id].toStyledString().c_str());
- return;
- }
- std::string key_part = parts.cur_token();
- size_t bracketpos = key_part.find('[');
- if (bracketpos == key_part.npos) { // A single item
- target = &(*target)[key_part];
- } else { // A list item
- target = &(*target)[key_part.substr(0, bracketpos)];
- while (bracketpos != key_part.npos) {
- std::string index = key_part.substr(
- bracketpos + 1, key_part.find(']', bracketpos) - bracketpos - 1);
- if (PERFETTO_UNLIKELY(!target->isNull() && !target->isArray())) {
- PERFETTO_DLOG("Malformed arguments. Can't append %s to %s.",
- key.c_str(),
- args_sets_[set_id].toStyledString().c_str());
- return;
- }
- target = &(*target)[stoi(index)];
- bracketpos = key_part.find('[', bracketpos + 1);
- }
- }
- }
- *target = value;
- }
-
- void PostprocessArgs() {
- for (Json::Value& args : args_sets_) {
- // Move all fields from "debug" key to upper level.
- if (args.isMember("debug")) {
- Json::Value debug = args["debug"];
- args.removeMember("debug");
- for (const auto& member : debug.getMemberNames()) {
- args[member] = debug[member];
- }
- }
-
- // Rename source fields.
- if (args.isMember("task")) {
- if (args["task"].isMember("posted_from")) {
- Json::Value posted_from = args["task"]["posted_from"];
- args["task"].removeMember("posted_from");
- if (posted_from.isMember("function_name")) {
- args["src_func"] = posted_from["function_name"];
- args["src_file"] = posted_from["file_name"];
- } else if (posted_from.isMember("file_name")) {
- args["src"] = posted_from["file_name"];
- }
- }
- if (args["task"].empty())
- args.removeMember("task");
- }
- }
- }
-
- const TraceStorage* storage_;
- std::vector<Json::Value> args_sets_;
- const Json::Value empty_value_;
- const Json::Value nan_value_;
- const Json::Value inf_value_;
- const Json::Value neg_inf_value_;
-};
-
void ConvertLegacyFlowEventArgs(const Json::Value& legacy_args,
Json::Value* event) {
if (legacy_args.isMember(kLegacyEventBindIdKey)) {
@@ -478,564 +104,1223 @@
}
}
-util::Status ExportThreadNames(const TraceStorage* storage,
- TraceFormatWriter* writer) {
- for (UniqueTid i = 1; i < storage->thread_count(); ++i) {
- auto thread = storage->GetThread(i);
- if (!thread.name_id.is_null()) {
- const char* thread_name = GetNonNullString(storage, thread.name_id);
- uint32_t pid = thread.upid ? storage->GetProcess(*thread.upid).pid : 0;
- writer->WriteMetadataEvent("thread_name", thread_name, thread.tid, pid);
- }
+class FileWriter : public OutputWriter {
+ public:
+ FileWriter(FILE* file) : file_(file) {}
+ ~FileWriter() override { fflush(file_); }
+
+ util::Status AppendString(const std::string& s) override {
+ size_t written =
+ fwrite(s.data(), sizeof(std::string::value_type), s.size(), file_);
+ if (written != s.size())
+ return util::ErrStatus("Error writing to file: %d", ferror(file_));
+ return util::OkStatus();
}
- return util::OkStatus();
-}
-util::Status ExportProcessNames(const TraceStorage* storage,
- TraceFormatWriter* writer) {
- for (UniquePid i = 1; i < storage->process_count(); ++i) {
- auto process = storage->GetProcess(i);
- if (!process.name_id.is_null()) {
- const char* process_name = GetNonNullString(storage, process.name_id);
- writer->WriteMetadataEvent("process_name", process_name, 0, process.pid);
- }
+ private:
+ FILE* file_;
+};
+
+class JsonExporter {
+ public:
+ JsonExporter(const TraceStorage* storage,
+ OutputWriter* output,
+ ArgumentFilterPredicate argument_filter,
+ MetadataFilterPredicate metadata_filter,
+ LabelFilterPredicate label_filter)
+ : storage_(storage),
+ args_builder_(storage_),
+ writer_(output, argument_filter, metadata_filter, label_filter) {}
+
+ util::Status Export() {
+ util::Status status = MapUniquePidsAndTids();
+ if (!status.ok())
+ return status;
+
+ status = ExportThreadNames();
+ if (!status.ok())
+ return status;
+
+ status = ExportProcessNames();
+ if (!status.ok())
+ return status;
+
+ status = ExportSlices();
+ if (!status.ok())
+ return status;
+
+ status = ExportRawEvents();
+ if (!status.ok())
+ return status;
+
+ status = ExportCpuProfileSamples();
+ if (!status.ok())
+ return status;
+
+ status = ExportMetadata();
+ if (!status.ok())
+ return status;
+
+ status = ExportStats();
+ if (!status.ok())
+ return status;
+
+ return util::OkStatus();
}
- return util::OkStatus();
-}
-util::Status ExportSlices(const TraceStorage* storage,
- const ArgsBuilder& args_builder,
- TraceFormatWriter* writer) {
- const auto& slices = storage->slice_table();
- for (uint32_t i = 0; i < slices.row_count(); ++i) {
- Json::Value event;
- event["ts"] = Json::Int64(slices.ts()[i] / 1000);
- event["cat"] = GetNonNullString(storage, slices.category()[i]);
- event["name"] = GetNonNullString(storage, slices.name()[i]);
- event["pid"] = 0;
- event["tid"] = 0;
+ private:
+ class TraceFormatWriter {
+ public:
+ TraceFormatWriter(OutputWriter* output,
+ ArgumentFilterPredicate argument_filter,
+ MetadataFilterPredicate metadata_filter,
+ LabelFilterPredicate label_filter)
+ : output_(output),
+ argument_filter_(argument_filter),
+ metadata_filter_(metadata_filter),
+ label_filter_(label_filter),
+ first_event_(true) {
+ WriteHeader();
+ }
- int32_t legacy_tid = 0;
+ ~TraceFormatWriter() { WriteFooter(); }
- event["args"] =
- args_builder.GetArgs(slices.arg_set_id()[i]); // Makes a copy.
- if (event["args"].isMember(kLegacyEventArgsKey)) {
- ConvertLegacyFlowEventArgs(event["args"][kLegacyEventArgsKey], &event);
+ void WriteCommonEvent(const Json::Value& event) {
+ if (label_filter_ && !label_filter_("traceEvents"))
+ return;
- if (event["args"][kLegacyEventArgsKey].isMember(
- kLegacyEventOriginalTidKey)) {
- legacy_tid = static_cast<int32_t>(
- event["args"][kLegacyEventArgsKey][kLegacyEventOriginalTidKey]
- .asInt());
+ DoWriteEvent(event);
+ }
+
+ void AddAsyncBeginEvent(const Json::Value& event) {
+ if (label_filter_ && !label_filter_("traceEvents"))
+ return;
+
+ async_begin_events_.push_back(event);
+ }
+
+ void AddAsyncInstantEvent(const Json::Value& event) {
+ if (label_filter_ && !label_filter_("traceEvents"))
+ return;
+
+ async_instant_events_.push_back(event);
+ }
+
+ void AddAsyncEndEvent(const Json::Value& event) {
+ if (label_filter_ && !label_filter_("traceEvents"))
+ return;
+
+ async_end_events_.push_back(event);
+ }
+
+ void SortAndEmitAsyncEvents() {
+ // Catapult doesn't handle out-of-order begin/end events well, especially
+ // when their timestamps are the same, but their order is incorrect. Since
+ // we process events sorted by begin timestamp, |async_begin_events_| and
+ // |async_instant_events_| are already sorted. We now only have to sort
+ // |async_end_events_| and merge-sort all events into a single sequence.
+
+ // Sort |async_end_events_|. Note that we should order by ascending
+ // timestamp, but in reverse-stable order. This way, a child slices's end
+ // is emitted before its parent's end event, even if both end events have
+ // the same timestamp. To accomplish this, we perform a stable sort in
+ // descending order and later iterate via reverse iterators.
+ struct {
+ bool operator()(const Json::Value& a, const Json::Value& b) const {
+ return a["ts"].asInt64() > b["ts"].asInt64();
+ }
+ } CompareEvents;
+ std::stable_sort(async_end_events_.begin(), async_end_events_.end(),
+ CompareEvents);
+
+ // Merge sort by timestamp. If events share the same timestamp, prefer
+ // instant events, then end events, so that old slices close before new
+ // ones are opened, but instant events remain in their deepest nesting
+ // level.
+ auto instant_event_it = async_instant_events_.begin();
+ auto end_event_it = async_end_events_.rbegin();
+ auto begin_event_it = async_begin_events_.begin();
+
+ auto has_instant_event = instant_event_it != async_instant_events_.end();
+ auto has_end_event = end_event_it != async_end_events_.rend();
+ auto has_begin_event = begin_event_it != async_begin_events_.end();
+
+ auto emit_next_instant = [&instant_event_it, &has_instant_event, this]() {
+ DoWriteEvent(*instant_event_it);
+ instant_event_it++;
+ has_instant_event = instant_event_it != async_instant_events_.end();
+ };
+ auto emit_next_end = [&end_event_it, &has_end_event, this]() {
+ DoWriteEvent(*end_event_it);
+ end_event_it++;
+ has_end_event = end_event_it != async_end_events_.rend();
+ };
+ auto emit_next_begin = [&begin_event_it, &has_begin_event, this]() {
+ DoWriteEvent(*begin_event_it);
+ begin_event_it++;
+ has_begin_event = begin_event_it != async_begin_events_.end();
+ };
+
+ auto emit_next_instant_or_end = [&instant_event_it, &end_event_it,
+ &emit_next_instant, &emit_next_end]() {
+ if ((*instant_event_it)["ts"].asInt64() <=
+ (*end_event_it)["ts"].asInt64()) {
+ emit_next_instant();
+ } else {
+ emit_next_end();
+ }
+ };
+ auto emit_next_instant_or_begin = [&instant_event_it, &begin_event_it,
+ &emit_next_instant,
+ &emit_next_begin]() {
+ if ((*instant_event_it)["ts"].asInt64() <=
+ (*begin_event_it)["ts"].asInt64()) {
+ emit_next_instant();
+ } else {
+ emit_next_begin();
+ }
+ };
+ auto emit_next_end_or_begin = [&end_event_it, &begin_event_it,
+ &emit_next_end, &emit_next_begin]() {
+ if ((*end_event_it)["ts"].asInt64() <=
+ (*begin_event_it)["ts"].asInt64()) {
+ emit_next_end();
+ } else {
+ emit_next_begin();
+ }
+ };
+
+ // While we still have events in all iterators, consider each.
+ while (has_instant_event && has_end_event && has_begin_event) {
+ if ((*instant_event_it)["ts"].asInt64() <=
+ (*end_event_it)["ts"].asInt64()) {
+ emit_next_instant_or_begin();
+ } else {
+ emit_next_end_or_begin();
+ }
}
- event["args"].removeMember(kLegacyEventArgsKey);
+ // Only instant and end events left.
+ while (has_instant_event && has_end_event) {
+ emit_next_instant_or_end();
+ }
+
+ // Only instant and begin events left.
+ while (has_instant_event && has_begin_event) {
+ emit_next_instant_or_begin();
+ }
+
+ // Only end and begin events left.
+ while (has_end_event && has_begin_event) {
+ emit_next_end_or_begin();
+ }
+
+ // Remaining instant events.
+ while (has_instant_event) {
+ emit_next_instant();
+ }
+
+ // Remaining end events.
+ while (has_end_event) {
+ emit_next_end();
+ }
+
+ // Remaining begin events.
+ while (has_begin_event) {
+ emit_next_begin();
+ }
}
- // To prevent duplicate export of slices, only export slices on descriptor
- // or chrome tracks (i.e. TrackEvent slices). Slices on other tracks may
- // also be present as raw events and handled by trace_to_text. Only add more
- // track types here if they are not already covered by trace_to_text.
- uint32_t track_id = slices.track_id()[i];
+ void WriteMetadataEvent(const char* metadata_type,
+ const char* metadata_value,
+ uint32_t pid,
+ uint32_t tid) {
+ if (label_filter_ && !label_filter_("traceEvents"))
+ return;
- const auto& track_table = storage->track_table();
+ if (!first_event_)
+ output_->AppendString(",\n");
- uint32_t track_row = *track_table.id().IndexOf(TrackId{track_id});
- auto track_args_id = track_table.source_arg_set_id()[track_row];
- if (!track_args_id)
- continue;
- const auto& track_args = args_builder.GetArgs(*track_args_id);
- bool legacy_chrome_track = track_args["source"].asString() == "chrome";
- if (!track_args.isMember("source") ||
- (!legacy_chrome_track &&
- track_args["source"].asString() != "descriptor")) {
- continue;
+ Json::FastWriter writer;
+ writer.omitEndingLineFeed();
+ Json::Value value;
+ value["ph"] = "M";
+ value["cat"] = "__metadata";
+ value["ts"] = 0;
+ value["name"] = metadata_type;
+ value["pid"] = Json::Int(pid);
+ value["tid"] = Json::Int(tid);
+
+ Json::Value args;
+ args["name"] = metadata_value;
+ value["args"] = args;
+
+ output_->AppendString(writer.write(value));
+ first_event_ = false;
}
- const auto& thread_track = storage->thread_track_table();
- const auto& process_track = storage->process_track_table();
- const auto& thread_slices = storage->thread_slices();
- const auto& virtual_track_slices = storage->virtual_track_slices();
+ void MergeMetadata(const Json::Value& value) {
+ for (const auto& member : value.getMemberNames()) {
+ metadata_[member] = value[member];
+ }
+ }
- int64_t duration_ns = slices.dur()[i];
- int64_t thread_ts_ns = 0;
- int64_t thread_duration_ns = 0;
- int64_t thread_instruction_count = 0;
- int64_t thread_instruction_delta = 0;
+ void AppendTelemetryMetadataString(const char* key, const char* value) {
+ metadata_["telemetry"][key].append(value);
+ }
- base::Optional<uint32_t> thread_slice_row =
- thread_slices.FindRowForSliceId(i);
- if (thread_slice_row) {
- thread_ts_ns = thread_slices.thread_timestamp_ns()[*thread_slice_row];
- thread_duration_ns =
- thread_slices.thread_duration_ns()[*thread_slice_row];
- thread_instruction_count =
- thread_slices.thread_instruction_counts()[*thread_slice_row];
- thread_instruction_delta =
- thread_slices.thread_instruction_deltas()[*thread_slice_row];
- } else {
- base::Optional<uint32_t> vtrack_slice_row =
- virtual_track_slices.FindRowForSliceId(i);
- if (vtrack_slice_row) {
- thread_ts_ns =
- virtual_track_slices.thread_timestamp_ns()[*vtrack_slice_row];
+ void AppendTelemetryMetadataInt(const char* key, int64_t value) {
+ metadata_["telemetry"][key].append(Json::Int64(value));
+ }
+
+ void AppendTelemetryMetadataBool(const char* key, bool value) {
+ metadata_["telemetry"][key].append(value);
+ }
+
+ void SetTelemetryMetadataTimestamp(const char* key, int64_t value) {
+ metadata_["telemetry"][key] = value / 1000.0;
+ }
+
+ void SetStats(const char* key, int64_t value) {
+ metadata_["trace_processor_stats"][key] = Json::Int64(value);
+ }
+
+ void SetStats(const char* key, const IndexMap& indexed_values) {
+ constexpr const char* kBufferStatsPrefix = "traced_buf_";
+
+ // Stats for the same buffer should be grouped together in the JSON.
+ if (strncmp(kBufferStatsPrefix, key, strlen(kBufferStatsPrefix)) == 0) {
+ for (const auto& value : indexed_values) {
+ metadata_["trace_processor_stats"]["traced_buf"][value.first]
+ [key + strlen(kBufferStatsPrefix)] =
+ Json::Int64(value.second);
+ }
+ return;
+ }
+
+ // Other indexed value stats are exported as array under their key.
+ for (const auto& value : indexed_values) {
+ metadata_["trace_processor_stats"][key][value.first] =
+ Json::Int64(value.second);
+ }
+ }
+
+ void AddSystemTraceData(const std::string& data) {
+ system_trace_data_ += data;
+ }
+
+ void AddUserTraceData(const std::string& data) {
+ if (user_trace_data_.empty())
+ user_trace_data_ = "[";
+ user_trace_data_ += data;
+ }
+
+ private:
+ void WriteHeader() {
+ if (!label_filter_)
+ output_->AppendString("{\"traceEvents\":[\n");
+ }
+
+ void WriteFooter() {
+ SortAndEmitAsyncEvents();
+
+ // Filter metadata entries.
+ if (metadata_filter_) {
+ for (const auto& member : metadata_.getMemberNames()) {
+ if (!metadata_filter_(member.c_str()))
+ metadata_[member] = kStrippedArgument;
+ }
+ }
+
+ Json::FastWriter writer;
+ writer.omitEndingLineFeed();
+ if ((!label_filter_ || label_filter_("traceEvents")) &&
+ !user_trace_data_.empty()) {
+ user_trace_data_ += "]";
+ Json::Reader reader;
+ Json::Value result;
+ if (reader.parse(user_trace_data_, result)) {
+ for (const auto& event : result) {
+ WriteCommonEvent(event);
+ }
+ } else {
+ PERFETTO_DLOG(
+ "can't parse legacy user json trace export, skipping. data: %s",
+ user_trace_data_.c_str());
+ }
+ }
+ if (!label_filter_)
+ output_->AppendString("]");
+ if ((!label_filter_ || label_filter_("systemTraceEvents")) &&
+ !system_trace_data_.empty()) {
+ output_->AppendString(",\"systemTraceEvents\":\n");
+ output_->AppendString(writer.write(Json::Value(system_trace_data_)));
+ }
+ if ((!label_filter_ || label_filter_("metadata")) && !metadata_.empty()) {
+ output_->AppendString(",\"metadata\":\n");
+ output_->AppendString(writer.write(metadata_));
+ }
+ if (!label_filter_)
+ output_->AppendString("}");
+ }
+
+ void DoWriteEvent(const Json::Value& event) {
+ if (!first_event_)
+ output_->AppendString(",\n");
+
+ Json::FastWriter writer;
+ writer.omitEndingLineFeed();
+
+ ArgumentNameFilterPredicate argument_name_filter;
+ bool strip_args =
+ argument_filter_ &&
+ !argument_filter_(event["cat"].asCString(), event["name"].asCString(),
+ &argument_name_filter);
+ if ((strip_args || argument_name_filter) && event.isMember("args")) {
+ Json::Value event_copy = event;
+ if (strip_args) {
+ event_copy["args"] = kStrippedArgument;
+ } else {
+ auto& args = event_copy["args"];
+ for (const auto& member : event["args"].getMemberNames()) {
+ if (!argument_name_filter(member.c_str()))
+ args[member] = kStrippedArgument;
+ }
+ }
+ output_->AppendString(writer.write(event_copy));
+ } else {
+ output_->AppendString(writer.write(event));
+ }
+ first_event_ = false;
+ }
+
+ OutputWriter* output_;
+ ArgumentFilterPredicate argument_filter_;
+ MetadataFilterPredicate metadata_filter_;
+ LabelFilterPredicate label_filter_;
+
+ bool first_event_;
+ Json::Value metadata_;
+ std::string system_trace_data_;
+ std::string user_trace_data_;
+ std::vector<Json::Value> async_begin_events_;
+ std::vector<Json::Value> async_instant_events_;
+ std::vector<Json::Value> async_end_events_;
+ };
+
+ class ArgsBuilder {
+ public:
+ explicit ArgsBuilder(const TraceStorage* storage)
+ : storage_(storage),
+ empty_value_(Json::objectValue),
+ nan_value_(Json::StaticString("NaN")),
+ inf_value_(Json::StaticString("Infinity")),
+ neg_inf_value_(Json::StaticString("-Infinity")) {
+ const auto& arg_table = storage_->arg_table();
+ uint32_t count = arg_table.row_count();
+ if (count == 0) {
+ args_sets_.resize(1, empty_value_);
+ return;
+ }
+ args_sets_.resize(arg_table.arg_set_id()[count - 1] + 1, empty_value_);
+
+ for (uint32_t i = 0; i < count; ++i) {
+ ArgSetId set_id = arg_table.arg_set_id()[i];
+ const char* key = GetNonNullString(storage_, arg_table.key()[i]);
+ Variadic value = storage_->GetArgValue(i);
+ AppendArg(set_id, key, VariadicToJson(value));
+ }
+ PostprocessArgs();
+ }
+
+ const Json::Value& GetArgs(ArgSetId set_id) const {
+ // If |set_id| was empty and added to the storage last, it may not be in
+ // args_sets_.
+ if (set_id > args_sets_.size())
+ return empty_value_;
+ return args_sets_[set_id];
+ }
+
+ private:
+ Json::Value VariadicToJson(Variadic variadic) {
+ switch (variadic.type) {
+ case Variadic::kInt:
+ return Json::Int64(variadic.int_value);
+ case Variadic::kUint:
+ return Json::UInt64(variadic.uint_value);
+ case Variadic::kString:
+ return GetNonNullString(storage_, variadic.string_value);
+ case Variadic::kReal:
+ if (std::isnan(variadic.real_value)) {
+ return nan_value_;
+ } else if (std::isinf(variadic.real_value) &&
+ variadic.real_value > 0) {
+ return inf_value_;
+ } else if (std::isinf(variadic.real_value) &&
+ variadic.real_value < 0) {
+ return neg_inf_value_;
+ } else {
+ return variadic.real_value;
+ }
+ case Variadic::kPointer:
+ return PrintUint64(variadic.pointer_value);
+ case Variadic::kBool:
+ return variadic.bool_value;
+ case Variadic::kJson:
+ Json::Reader reader;
+ Json::Value result;
+ reader.parse(GetNonNullString(storage_, variadic.json_value), result);
+ return result;
+ }
+ PERFETTO_FATAL("Not reached"); // For gcc.
+ }
+
+ void AppendArg(ArgSetId set_id,
+ const std::string& key,
+ const Json::Value& value) {
+ Json::Value* target = &args_sets_[set_id];
+ for (base::StringSplitter parts(key, '.'); parts.Next();) {
+ if (PERFETTO_UNLIKELY(!target->isNull() && !target->isObject())) {
+ PERFETTO_DLOG("Malformed arguments. Can't append %s to %s.",
+ key.c_str(),
+ args_sets_[set_id].toStyledString().c_str());
+ return;
+ }
+ std::string key_part = parts.cur_token();
+ size_t bracketpos = key_part.find('[');
+ if (bracketpos == key_part.npos) { // A single item
+ target = &(*target)[key_part];
+ } else { // A list item
+ target = &(*target)[key_part.substr(0, bracketpos)];
+ while (bracketpos != key_part.npos) {
+ // We constructed this string from an int earlier in trace_processor
+ // so it shouldn't be possible for this (or the StringToUInt32
+ // below) to fail.
+ std::string s =
+ key_part.substr(bracketpos + 1, key_part.find(']', bracketpos) -
+ bracketpos - 1);
+ if (PERFETTO_UNLIKELY(!target->isNull() && !target->isArray())) {
+ PERFETTO_DLOG("Malformed arguments. Can't append %s to %s.",
+ key.c_str(),
+ args_sets_[set_id].toStyledString().c_str());
+ return;
+ }
+ base::Optional<uint32_t> index = base::StringToUInt32(s);
+ if (PERFETTO_UNLIKELY(!index)) {
+ PERFETTO_ELOG("Expected to be able to extract index from %s",
+ key_part.c_str());
+ return;
+ }
+ target = &(*target)[index.value()];
+ bracketpos = key_part.find('[', bracketpos + 1);
+ }
+ }
+ }
+ *target = value;
+ }
+
+ void PostprocessArgs() {
+ for (Json::Value& args : args_sets_) {
+ // Move all fields from "debug" key to upper level.
+ if (args.isMember("debug")) {
+ Json::Value debug = args["debug"];
+ args.removeMember("debug");
+ for (const auto& member : debug.getMemberNames()) {
+ args[member] = debug[member];
+ }
+ }
+
+ // Rename source fields.
+ if (args.isMember("task")) {
+ if (args["task"].isMember("posted_from")) {
+ Json::Value posted_from = args["task"]["posted_from"];
+ args["task"].removeMember("posted_from");
+ if (posted_from.isMember("function_name")) {
+ args["src_func"] = posted_from["function_name"];
+ args["src_file"] = posted_from["file_name"];
+ } else if (posted_from.isMember("file_name")) {
+ args["src"] = posted_from["file_name"];
+ }
+ }
+ if (args["task"].empty())
+ args.removeMember("task");
+ }
+ }
+ }
+
+ const TraceStorage* storage_;
+ std::vector<Json::Value> args_sets_;
+ const Json::Value empty_value_;
+ const Json::Value nan_value_;
+ const Json::Value inf_value_;
+ const Json::Value neg_inf_value_;
+ };
+
+ util::Status MapUniquePidsAndTids() {
+ const auto& process_table = storage_->process_table();
+ for (UniquePid upid = 0; upid < process_table.row_count(); upid++) {
+ uint32_t exported_pid = process_table.pid()[upid];
+ auto it_and_inserted =
+ exported_pids_to_upids_.emplace(exported_pid, upid);
+ if (!it_and_inserted.second) {
+ exported_pid = NextExportedPidOrTidForDuplicates();
+ it_and_inserted = exported_pids_to_upids_.emplace(exported_pid, upid);
+ }
+ upids_to_exported_pids_.emplace(upid, exported_pid);
+ }
+
+ const auto& thread_table = storage_->thread_table();
+ for (UniqueTid utid = 0; utid < thread_table.row_count(); utid++) {
+ uint32_t exported_pid = 0;
+ base::Optional<UniquePid> upid = thread_table.upid()[utid];
+ if (upid) {
+ auto exported_pid_it = upids_to_exported_pids_.find(*upid);
+ PERFETTO_DCHECK(exported_pid_it != upids_to_exported_pids_.end());
+ exported_pid = exported_pid_it->second;
+ }
+
+ uint32_t exported_tid = thread_table.tid()[utid];
+ auto it_and_inserted = exported_pids_and_tids_to_utids_.emplace(
+ std::make_pair(exported_pid, exported_tid), utid);
+ if (!it_and_inserted.second) {
+ exported_tid = NextExportedPidOrTidForDuplicates();
+ it_and_inserted = exported_pids_and_tids_to_utids_.emplace(
+ std::make_pair(exported_pid, exported_tid), utid);
+ }
+ utids_to_exported_pids_and_tids_.emplace(
+ utid, std::make_pair(exported_pid, exported_tid));
+ }
+
+ return util::OkStatus();
+ }
+
+ util::Status ExportThreadNames() {
+ const auto& thread_table = storage_->thread_table();
+ for (UniqueTid utid = 0; utid < thread_table.row_count(); ++utid) {
+ auto opt_name = thread_table.name()[utid];
+ if (!opt_name.is_null()) {
+ const char* thread_name = GetNonNullString(storage_, opt_name);
+ auto pid_and_tid = UtidToPidAndTid(utid);
+ writer_.WriteMetadataEvent("thread_name", thread_name,
+ pid_and_tid.first, pid_and_tid.second);
+ }
+ }
+ return util::OkStatus();
+ }
+
+ util::Status ExportProcessNames() {
+ const auto& process_table = storage_->process_table();
+ for (UniquePid upid = 0; upid < process_table.row_count(); ++upid) {
+ auto opt_name = process_table.name()[upid];
+ if (!opt_name.is_null()) {
+ const char* process_name = GetNonNullString(storage_, opt_name);
+ writer_.WriteMetadataEvent("process_name", process_name,
+ UpidToPid(upid), /*tid=*/0);
+ }
+ }
+ return util::OkStatus();
+ }
+
+ util::Status ExportSlices() {
+ const auto& slices = storage_->slice_table();
+ for (uint32_t i = 0; i < slices.row_count(); ++i) {
+ // Skip slices with empty category - these are ftrace/system slices that
+ // were also imported into the raw table and will be exported from there
+ // by trace_to_text.
+ if (slices.category()[i] == kNullStringId)
+ continue;
+
+ Json::Value event;
+ event["ts"] = Json::Int64(slices.ts()[i] / 1000);
+ event["cat"] = GetNonNullString(storage_, slices.category()[i]);
+ event["name"] = GetNonNullString(storage_, slices.name()[i]);
+ event["pid"] = 0;
+ event["tid"] = 0;
+
+ base::Optional<UniqueTid> legacy_utid;
+
+ event["args"] =
+ args_builder_.GetArgs(slices.arg_set_id()[i]); // Makes a copy.
+ if (event["args"].isMember(kLegacyEventArgsKey)) {
+ ConvertLegacyFlowEventArgs(event["args"][kLegacyEventArgsKey], &event);
+
+ if (event["args"][kLegacyEventArgsKey].isMember(
+ kLegacyEventPassthroughUtidKey)) {
+ legacy_utid =
+ event["args"][kLegacyEventArgsKey][kLegacyEventPassthroughUtidKey]
+ .asUInt();
+ }
+
+ event["args"].removeMember(kLegacyEventArgsKey);
+ }
+
+ // To prevent duplicate export of slices, only export slices on descriptor
+ // or chrome tracks (i.e. TrackEvent slices). Slices on other tracks may
+ // also be present as raw events and handled by trace_to_text. Only add
+ // more track types here if they are not already covered by trace_to_text.
+ uint32_t track_id = slices.track_id()[i];
+
+ const auto& track_table = storage_->track_table();
+
+ uint32_t track_row = *track_table.id().IndexOf(TrackId{track_id});
+ auto track_args_id = track_table.source_arg_set_id()[track_row];
+ const Json::Value* track_args = nullptr;
+ bool legacy_chrome_track = false;
+ bool is_child_track = false;
+ if (track_args_id) {
+ track_args = &args_builder_.GetArgs(*track_args_id);
+ legacy_chrome_track = (*track_args)["source"].asString() == "chrome";
+ is_child_track = track_args->isMember("parent_track_id");
+ }
+
+ const auto& thread_track = storage_->thread_track_table();
+ const auto& process_track = storage_->process_track_table();
+ const auto& thread_slices = storage_->thread_slices();
+ const auto& virtual_track_slices = storage_->virtual_track_slices();
+
+ int64_t duration_ns = slices.dur()[i];
+ int64_t thread_ts_ns = 0;
+ int64_t thread_duration_ns = 0;
+ int64_t thread_instruction_count = 0;
+ int64_t thread_instruction_delta = 0;
+
+ base::Optional<uint32_t> thread_slice_row =
+ thread_slices.FindRowForSliceId(i);
+ if (thread_slice_row) {
+ thread_ts_ns = thread_slices.thread_timestamp_ns()[*thread_slice_row];
thread_duration_ns =
- virtual_track_slices.thread_duration_ns()[*vtrack_slice_row];
+ thread_slices.thread_duration_ns()[*thread_slice_row];
thread_instruction_count =
- virtual_track_slices.thread_instruction_counts()[*vtrack_slice_row];
+ thread_slices.thread_instruction_counts()[*thread_slice_row];
thread_instruction_delta =
- virtual_track_slices.thread_instruction_deltas()[*vtrack_slice_row];
- }
- }
-
- auto opt_thread_track_row = thread_track.id().IndexOf(TrackId{track_id});
-
- if (opt_thread_track_row) {
- // Synchronous (thread) slice or instant event.
- UniqueTid utid = thread_track.utid()[*opt_thread_track_row];
- auto thread = storage->GetThread(utid);
- event["tid"] = static_cast<int32_t>(thread.tid);
- if (thread.upid) {
- event["pid"] =
- static_cast<int32_t>(storage->GetProcess(*thread.upid).pid);
- }
-
- if (duration_ns == 0) {
- // Use "I" instead of "i" phase for backwards-compat with old consumers.
- event["ph"] = "I";
- if (thread_ts_ns > 0) {
- event["tts"] = Json::Int64(thread_ts_ns / 1000);
- }
- if (thread_instruction_count > 0) {
- event["ticount"] = Json::Int64(thread_instruction_count);
- }
- event["s"] = "t";
+ thread_slices.thread_instruction_deltas()[*thread_slice_row];
} else {
- if (duration_ns > 0) {
- event["ph"] = "X";
- event["dur"] = Json::Int64(duration_ns / 1000);
- } else {
- // If the slice didn't finish, the duration may be negative. Only
- // write a begin event without end event in this case.
- event["ph"] = "B";
- }
- if (thread_ts_ns > 0) {
- event["tts"] = Json::Int64(thread_ts_ns / 1000);
- // Only write thread duration for completed events.
- if (duration_ns > 0)
- event["tdur"] = Json::Int64(thread_duration_ns / 1000);
- }
- if (thread_instruction_count > 0) {
- event["ticount"] = Json::Int64(thread_instruction_count);
- // Only write thread instruction delta for completed events.
- if (duration_ns > 0)
- event["tidelta"] = Json::Int64(thread_instruction_delta);
- }
- }
- writer->WriteCommonEvent(event);
- } else if (!legacy_chrome_track ||
- (legacy_chrome_track && track_args.isMember("source_id"))) {
- // Async event slice.
- auto opt_process_row = process_track.id().IndexOf(TrackId{track_id});
- if (legacy_chrome_track) {
- // Legacy async tracks are always process-associated.
- PERFETTO_DCHECK(opt_process_row);
- uint32_t upid = process_track.upid()[*opt_process_row];
- event["pid"] = static_cast<int32_t>(storage->GetProcess(upid).pid);
- event["tid"] =
- legacy_tid ? legacy_tid
- : static_cast<int32_t>(storage->GetProcess(upid).pid);
-
- // Preserve original event IDs for legacy tracks. This is so that e.g.
- // memory dump IDs show up correctly in the JSON trace.
- PERFETTO_DCHECK(track_args.isMember("source_id"));
- PERFETTO_DCHECK(track_args.isMember("source_id_is_process_scoped"));
- PERFETTO_DCHECK(track_args.isMember("source_scope"));
- uint64_t source_id =
- static_cast<uint64_t>(track_args["source_id"].asInt64());
- std::string source_scope = track_args["source_scope"].asString();
- if (!source_scope.empty())
- event["scope"] = source_scope;
- bool source_id_is_process_scoped =
- track_args["source_id_is_process_scoped"].asBool();
- if (source_id_is_process_scoped) {
- event["id2"]["local"] = PrintUint64(source_id);
- } else {
- // Some legacy importers don't understand "id2" fields, so we use the
- // "usually" global "id" field instead. This works as long as the
- // event phase is not in {'N', 'D', 'O', '(', ')'}, see
- // "LOCAL_ID_PHASES" in catapult.
- event["id"] = PrintUint64(source_id);
- }
- } else {
- if (opt_process_row) {
- uint32_t upid = process_track.upid()[*opt_process_row];
- event["id2"]["local"] = PrintUint64(track_id);
- event["pid"] = static_cast<int32_t>(storage->GetProcess(upid).pid);
- event["tid"] =
- legacy_tid ? legacy_tid
- : static_cast<int32_t>(storage->GetProcess(upid).pid);
- } else {
- // Some legacy importers don't understand "id2" fields, so we use the
- // "usually" global "id" field instead. This works as long as the
- // event phase is not in {'N', 'D', 'O', '(', ')'}, see
- // "LOCAL_ID_PHASES" in catapult.
- event["id"] = PrintUint64(track_id);
+ base::Optional<uint32_t> vtrack_slice_row =
+ virtual_track_slices.FindRowForSliceId(i);
+ if (vtrack_slice_row) {
+ thread_ts_ns =
+ virtual_track_slices.thread_timestamp_ns()[*vtrack_slice_row];
+ thread_duration_ns =
+ virtual_track_slices.thread_duration_ns()[*vtrack_slice_row];
+ thread_instruction_count =
+ virtual_track_slices
+ .thread_instruction_counts()[*vtrack_slice_row];
+ thread_instruction_delta =
+ virtual_track_slices
+ .thread_instruction_deltas()[*vtrack_slice_row];
}
}
- if (thread_ts_ns > 0) {
- event["tts"] = Json::Int64(thread_ts_ns / 1000);
- event["use_async_tts"] = Json::Int(1);
- }
- if (thread_instruction_count > 0) {
- event["ticount"] = Json::Int64(thread_instruction_count);
- event["use_async_tts"] = Json::Int(1);
- }
+ auto opt_thread_track_row = thread_track.id().IndexOf(TrackId{track_id});
- if (duration_ns == 0) { // Instant async event.
- event["ph"] = "n";
- writer->WriteCommonEvent(event);
- } else { // Async start and end.
- event["ph"] = "b";
- writer->WriteCommonEvent(event);
- // If the slice didn't finish, the duration may be negative. Don't
- // write the end event in this case.
- if (duration_ns > 0) {
- event["ph"] = "e";
- event["ts"] = Json::Int64((slices.ts()[i] + duration_ns) / 1000);
+ if (opt_thread_track_row && !is_child_track) {
+ // Synchronous (thread) slice or instant event.
+ UniqueTid utid = thread_track.utid()[*opt_thread_track_row];
+ auto pid_and_tid = UtidToPidAndTid(utid);
+ event["pid"] = Json::Int(pid_and_tid.first);
+ event["tid"] = Json::Int(pid_and_tid.second);
+
+ if (duration_ns == 0) {
+ // Use "I" instead of "i" phase for backwards-compat with old
+ // consumers.
+ event["ph"] = "I";
if (thread_ts_ns > 0) {
- event["tts"] =
- Json::Int64((thread_ts_ns + thread_duration_ns) / 1000);
+ event["tts"] = Json::Int64(thread_ts_ns / 1000);
}
if (thread_instruction_count > 0) {
- event["ticount"] = Json::Int64(
- (thread_instruction_count + thread_instruction_delta));
+ event["ticount"] = Json::Int64(thread_instruction_count);
}
- event["args"].clear();
- writer->PushEndEvent(event);
+ event["s"] = "t";
+ } else {
+ if (duration_ns > 0) {
+ event["ph"] = "X";
+ event["dur"] = Json::Int64(duration_ns / 1000);
+ } else {
+ // If the slice didn't finish, the duration may be negative. Only
+ // write a begin event without end event in this case.
+ event["ph"] = "B";
+ }
+ if (thread_ts_ns > 0) {
+ event["tts"] = Json::Int64(thread_ts_ns / 1000);
+ // Only write thread duration for completed events.
+ if (duration_ns > 0)
+ event["tdur"] = Json::Int64(thread_duration_ns / 1000);
+ }
+ if (thread_instruction_count > 0) {
+ event["ticount"] = Json::Int64(thread_instruction_count);
+ // Only write thread instruction delta for completed events.
+ if (duration_ns > 0)
+ event["tidelta"] = Json::Int64(thread_instruction_delta);
+ }
+ }
+ writer_.WriteCommonEvent(event);
+ } else if (is_child_track ||
+ (legacy_chrome_track && track_args->isMember("source_id"))) {
+ // Async event slice.
+ auto opt_process_row = process_track.id().IndexOf(TrackId{track_id});
+ if (legacy_chrome_track) {
+ // Legacy async tracks are always process-associated and have args.
+ PERFETTO_DCHECK(opt_process_row);
+ PERFETTO_DCHECK(track_args);
+ uint32_t upid = process_track.upid()[*opt_process_row];
+ uint32_t exported_pid = UpidToPid(upid);
+ event["pid"] = Json::Int(exported_pid);
+ event["tid"] =
+ Json::Int(legacy_utid ? UtidToPidAndTid(*legacy_utid).second
+ : exported_pid);
+
+ // Preserve original event IDs for legacy tracks. This is so that e.g.
+ // memory dump IDs show up correctly in the JSON trace.
+ PERFETTO_DCHECK(track_args->isMember("source_id"));
+ PERFETTO_DCHECK(track_args->isMember("source_id_is_process_scoped"));
+ PERFETTO_DCHECK(track_args->isMember("source_scope"));
+ uint64_t source_id =
+ static_cast<uint64_t>((*track_args)["source_id"].asInt64());
+ std::string source_scope = (*track_args)["source_scope"].asString();
+ if (!source_scope.empty())
+ event["scope"] = source_scope;
+ bool source_id_is_process_scoped =
+ (*track_args)["source_id_is_process_scoped"].asBool();
+ if (source_id_is_process_scoped) {
+ event["id2"]["local"] = PrintUint64(source_id);
+ } else {
+ // Some legacy importers don't understand "id2" fields, so we use
+ // the "usually" global "id" field instead. This works as long as
+ // the event phase is not in {'N', 'D', 'O', '(', ')'}, see
+ // "LOCAL_ID_PHASES" in catapult.
+ event["id"] = PrintUint64(source_id);
+ }
+ } else {
+ if (opt_thread_track_row) {
+ UniqueTid utid = thread_track.utid()[*opt_thread_track_row];
+ auto pid_and_tid = UtidToPidAndTid(utid);
+ event["pid"] = Json::Int(pid_and_tid.first);
+ event["tid"] = Json::Int(pid_and_tid.second);
+ event["id2"]["local"] = PrintUint64(track_id);
+ } else if (opt_process_row) {
+ uint32_t upid = process_track.upid()[*opt_process_row];
+ uint32_t exported_pid = UpidToPid(upid);
+ event["pid"] = Json::Int(exported_pid);
+ event["tid"] =
+ Json::Int(legacy_utid ? UtidToPidAndTid(*legacy_utid).second
+ : exported_pid);
+ event["id2"]["local"] = PrintUint64(track_id);
+ } else {
+ // Some legacy importers don't understand "id2" fields, so we use
+ // the "usually" global "id" field instead. This works as long as
+ // the event phase is not in {'N', 'D', 'O', '(', ')'}, see
+ // "LOCAL_ID_PHASES" in catapult.
+ event["id"] = PrintUint64(track_id);
+ }
+ }
+
+ if (thread_ts_ns > 0) {
+ event["tts"] = Json::Int64(thread_ts_ns / 1000);
+ event["use_async_tts"] = Json::Int(1);
+ }
+ if (thread_instruction_count > 0) {
+ event["ticount"] = Json::Int64(thread_instruction_count);
+ event["use_async_tts"] = Json::Int(1);
+ }
+
+ if (duration_ns == 0) { // Instant async event.
+ event["ph"] = "n";
+ writer_.AddAsyncInstantEvent(event);
+ } else { // Async start and end.
+ event["ph"] = "b";
+ writer_.AddAsyncBeginEvent(event);
+ // If the slice didn't finish, the duration may be negative. Don't
+ // write the end event in this case.
+ if (duration_ns > 0) {
+ event["ph"] = "e";
+ event["ts"] = Json::Int64((slices.ts()[i] + duration_ns) / 1000);
+ if (thread_ts_ns > 0) {
+ event["tts"] =
+ Json::Int64((thread_ts_ns + thread_duration_ns) / 1000);
+ }
+ if (thread_instruction_count > 0) {
+ event["ticount"] = Json::Int64(
+ (thread_instruction_count + thread_instruction_delta));
+ }
+ event["args"].clear();
+ writer_.AddAsyncEndEvent(event);
+ }
+ }
+ } else {
+ // Global or process-scoped instant event.
+ PERFETTO_DCHECK(legacy_chrome_track || !is_child_track);
+ if (duration_ns != 0) {
+ // We don't support exporting slices on the default global or process
+ // track to JSON (JSON only supports instant events on these tracks).
+ PERFETTO_DLOG(
+ "skipping non-instant slice on global or process track");
+ } else {
+ // Use "I" instead of "i" phase for backwards-compat with old
+ // consumers.
+ event["ph"] = "I";
+
+ auto opt_process_row = process_track.id().IndexOf(TrackId{track_id});
+ if (opt_process_row.has_value()) {
+ uint32_t upid = process_track.upid()[*opt_process_row];
+ uint32_t exported_pid = UpidToPid(upid);
+ event["pid"] = Json::Int(exported_pid);
+ event["tid"] =
+ Json::Int(legacy_utid ? UtidToPidAndTid(*legacy_utid).second
+ : exported_pid);
+ event["s"] = "p";
+ } else {
+ event["s"] = "g";
+ }
+ writer_.WriteCommonEvent(event);
}
}
- } else {
- // Global or process-scoped instant event.
- PERFETTO_DCHECK(duration_ns == 0);
- // Use "I" instead of "i" phase for backwards-compat with old consumers.
- event["ph"] = "I";
-
- auto opt_process_row = process_track.id().IndexOf(TrackId{track_id});
- if (opt_process_row.has_value()) {
- uint32_t upid = process_track.upid()[*opt_process_row];
- event["pid"] = static_cast<int32_t>(storage->GetProcess(upid).pid);
- event["tid"] =
- legacy_tid ? legacy_tid
- : static_cast<int32_t>(storage->GetProcess(upid).pid);
- event["s"] = "p";
- } else {
- event["s"] = "g";
- }
- writer->WriteCommonEvent(event);
}
- }
- return util::OkStatus();
-}
-
-Json::Value ConvertLegacyRawEventToJson(const TraceStorage* storage,
- const ArgsBuilder& args_builder,
- uint32_t index) {
- const auto& events = storage->raw_events();
-
- Json::Value event;
- event["ts"] = Json::Int64(events.timestamps()[index] / 1000);
-
- UniqueTid utid = static_cast<UniqueTid>(events.utids()[index]);
- auto thread = storage->GetThread(utid);
- event["tid"] = static_cast<int32_t>(thread.tid);
- event["pid"] = 0;
- if (thread.upid)
- event["pid"] = static_cast<int32_t>(storage->GetProcess(*thread.upid).pid);
-
- // Raw legacy events store all other params in the arg set. Make a copy of
- // the converted args here, parse, and then remove the legacy params.
- event["args"] = args_builder.GetArgs(events.arg_set_ids()[index]);
- const Json::Value& legacy_args = event["args"][kLegacyEventArgsKey];
-
- PERFETTO_DCHECK(legacy_args.isMember(kLegacyEventCategoryKey));
- event["cat"] = legacy_args[kLegacyEventCategoryKey];
-
- PERFETTO_DCHECK(legacy_args.isMember(kLegacyEventNameKey));
- event["name"] = legacy_args[kLegacyEventNameKey];
-
- PERFETTO_DCHECK(legacy_args.isMember(kLegacyEventPhaseKey));
- event["ph"] = legacy_args[kLegacyEventPhaseKey];
-
- // Object snapshot events are supposed to have a mandatory "snapshot" arg,
- // which may be removed in trace processor if it is empty.
- if (legacy_args[kLegacyEventPhaseKey] == "O" &&
- !event["args"].isMember("snapshot")) {
- event["args"]["snapshot"] = Json::Value(Json::objectValue);
+ return util::OkStatus();
}
- if (legacy_args.isMember(kLegacyEventDurationNsKey))
- event["dur"] = legacy_args[kLegacyEventDurationNsKey].asInt64() / 1000;
+ Json::Value ConvertLegacyRawEventToJson(uint32_t index) {
+ const auto& events = storage_->raw_table();
- if (legacy_args.isMember(kLegacyEventThreadTimestampNsKey)) {
- event["tts"] =
- legacy_args[kLegacyEventThreadTimestampNsKey].asInt64() / 1000;
- }
-
- if (legacy_args.isMember(kLegacyEventThreadDurationNsKey)) {
- event["tdur"] =
- legacy_args[kLegacyEventThreadDurationNsKey].asInt64() / 1000;
- }
-
- if (legacy_args.isMember(kLegacyEventThreadInstructionCountKey))
- event["ticount"] = legacy_args[kLegacyEventThreadInstructionCountKey];
-
- if (legacy_args.isMember(kLegacyEventThreadInstructionDeltaKey))
- event["tidelta"] = legacy_args[kLegacyEventThreadInstructionDeltaKey];
-
- if (legacy_args.isMember(kLegacyEventUseAsyncTtsKey))
- event["use_async_tts"] = legacy_args[kLegacyEventUseAsyncTtsKey];
-
- if (legacy_args.isMember(kLegacyEventUnscopedIdKey)) {
- event["id"] =
- PrintUint64(legacy_args[kLegacyEventUnscopedIdKey].asUInt64());
- }
-
- if (legacy_args.isMember(kLegacyEventGlobalIdKey)) {
- event["id2"]["global"] =
- PrintUint64(legacy_args[kLegacyEventGlobalIdKey].asUInt64());
- }
-
- if (legacy_args.isMember(kLegacyEventLocalIdKey)) {
- event["id2"]["local"] =
- PrintUint64(legacy_args[kLegacyEventLocalIdKey].asUInt64());
- }
-
- if (legacy_args.isMember(kLegacyEventIdScopeKey))
- event["scope"] = legacy_args[kLegacyEventIdScopeKey];
-
- ConvertLegacyFlowEventArgs(legacy_args, &event);
-
- event["args"].removeMember(kLegacyEventArgsKey);
-
- return event;
-}
-
-util::Status ExportRawEvents(const TraceStorage* storage,
- const ArgsBuilder& args_builder,
- TraceFormatWriter* writer) {
- base::Optional<StringId> raw_legacy_event_key_id =
- storage->string_pool().GetId("track_event.legacy_event");
- base::Optional<StringId> raw_legacy_system_trace_event_id =
- storage->string_pool().GetId("chrome_event.legacy_system_trace");
- base::Optional<StringId> raw_legacy_user_trace_event_id =
- storage->string_pool().GetId("chrome_event.legacy_user_trace");
- base::Optional<StringId> raw_chrome_metadata_event_id =
- storage->string_pool().GetId("chrome_event.metadata");
-
- const auto& events = storage->raw_events();
- for (uint32_t i = 0; i < events.raw_event_count(); ++i) {
- if (raw_legacy_event_key_id &&
- events.name_ids()[i] == *raw_legacy_event_key_id) {
- Json::Value event = ConvertLegacyRawEventToJson(storage, args_builder, i);
- writer->WriteCommonEvent(event);
- } else if (raw_legacy_system_trace_event_id &&
- events.name_ids()[i] == *raw_legacy_system_trace_event_id) {
- Json::Value args = args_builder.GetArgs(events.arg_set_ids()[i]);
- PERFETTO_DCHECK(args.isMember("data"));
- writer->AddSystemTraceData(args["data"].asString());
- } else if (raw_legacy_user_trace_event_id &&
- events.name_ids()[i] == *raw_legacy_user_trace_event_id) {
- Json::Value args = args_builder.GetArgs(events.arg_set_ids()[i]);
- PERFETTO_DCHECK(args.isMember("data"));
- writer->AddUserTraceData(args["data"].asString());
- } else if (raw_chrome_metadata_event_id &&
- events.name_ids()[i] == *raw_chrome_metadata_event_id) {
- Json::Value args = args_builder.GetArgs(events.arg_set_ids()[i]);
- writer->MergeMetadata(args);
- }
- }
- return util::OkStatus();
-}
-
-util::Status ExportCpuProfileSamples(const TraceStorage* storage,
- TraceFormatWriter* writer) {
- const tables::CpuProfileStackSampleTable& samples =
- storage->cpu_profile_stack_sample_table();
- for (uint32_t i = 0; i < samples.row_count(); ++i) {
Json::Value event;
- event["ts"] = Json::Int64(samples.ts()[i] / 1000);
+ event["ts"] = Json::Int64(events.ts()[index] / 1000);
- UniqueTid utid = static_cast<UniqueTid>(samples.utid()[i]);
- auto thread = storage->GetThread(utid);
- event["tid"] = static_cast<int32_t>(thread.tid);
- if (thread.upid) {
- event["pid"] =
- static_cast<int32_t>(storage->GetProcess(*thread.upid).pid);
+ UniqueTid utid = static_cast<UniqueTid>(events.utid()[index]);
+ auto pid_and_tid = UtidToPidAndTid(utid);
+ event["pid"] = Json::Int(pid_and_tid.first);
+ event["tid"] = Json::Int(pid_and_tid.second);
+
+ // Raw legacy events store all other params in the arg set. Make a copy of
+ // the converted args here, parse, and then remove the legacy params.
+ event["args"] = args_builder_.GetArgs(events.arg_set_id()[index]);
+ const Json::Value& legacy_args = event["args"][kLegacyEventArgsKey];
+
+ PERFETTO_DCHECK(legacy_args.isMember(kLegacyEventCategoryKey));
+ event["cat"] = legacy_args[kLegacyEventCategoryKey];
+
+ PERFETTO_DCHECK(legacy_args.isMember(kLegacyEventNameKey));
+ event["name"] = legacy_args[kLegacyEventNameKey];
+
+ PERFETTO_DCHECK(legacy_args.isMember(kLegacyEventPhaseKey));
+ event["ph"] = legacy_args[kLegacyEventPhaseKey];
+
+ // Object snapshot events are supposed to have a mandatory "snapshot" arg,
+ // which may be removed in trace processor if it is empty.
+ if (legacy_args[kLegacyEventPhaseKey] == "O" &&
+ !event["args"].isMember("snapshot")) {
+ event["args"]["snapshot"] = Json::Value(Json::objectValue);
}
- event["ph"] = "n";
- event["cat"] = "disabled_by_default-cpu_profiler";
- event["name"] = "StackCpuSampling";
- event["s"] = "t";
+ if (legacy_args.isMember(kLegacyEventDurationNsKey))
+ event["dur"] = legacy_args[kLegacyEventDurationNsKey].asInt64() / 1000;
- // Add a dummy thread timestamp to this event to match the format of instant
- // events. Useful in the UI to view args of a selected group of samples.
- event["tts"] = Json::Int64(1);
+ if (legacy_args.isMember(kLegacyEventThreadTimestampNsKey)) {
+ event["tts"] =
+ legacy_args[kLegacyEventThreadTimestampNsKey].asInt64() / 1000;
+ }
- // "n"-phase events are nestable async events which get tied together with
- // their id, so we need to give each one a unique ID as we only
- // want the samples to show up on their own track in the trace-viewer but
- // not nested together.
- static size_t g_id_counter = 0;
- event["id"] = PrintUint64(++g_id_counter);
+ if (legacy_args.isMember(kLegacyEventThreadDurationNsKey)) {
+ event["tdur"] =
+ legacy_args[kLegacyEventThreadDurationNsKey].asInt64() / 1000;
+ }
- std::vector<std::string> callstack;
- const auto& callsites = storage->stack_profile_callsite_table();
- int64_t maybe_callsite_id = samples.callsite_id()[i];
- PERFETTO_DCHECK(maybe_callsite_id >= 0 &&
- maybe_callsite_id < callsites.row_count());
- while (maybe_callsite_id >= 0) {
- uint32_t callsite_id = static_cast<uint32_t>(maybe_callsite_id);
+ if (legacy_args.isMember(kLegacyEventThreadInstructionCountKey))
+ event["ticount"] = legacy_args[kLegacyEventThreadInstructionCountKey];
- const auto& frames = storage->stack_profile_frame_table();
- PERFETTO_DCHECK(callsites.frame_id()[callsite_id] >= 0 &&
- callsites.frame_id()[callsite_id] < frames.row_count());
- uint32_t frame_id =
- static_cast<uint32_t>(callsites.frame_id()[callsite_id]);
+ if (legacy_args.isMember(kLegacyEventThreadInstructionDeltaKey))
+ event["tidelta"] = legacy_args[kLegacyEventThreadInstructionDeltaKey];
- const auto& mappings = storage->stack_profile_mapping_table();
- PERFETTO_DCHECK(frames.mapping()[frame_id] >= 0 &&
- frames.mapping()[frame_id] < mappings.row_count());
- uint32_t mapping_id = static_cast<uint32_t>(frames.mapping()[frame_id]);
+ if (legacy_args.isMember(kLegacyEventUseAsyncTtsKey))
+ event["use_async_tts"] = legacy_args[kLegacyEventUseAsyncTtsKey];
- NullTermStringView symbol_name;
- auto opt_symbol_set_id = frames.symbol_set_id()[frame_id];
- if (opt_symbol_set_id) {
- symbol_name = storage->GetString(
- storage->symbol_table().name()[*opt_symbol_set_id]);
+ if (legacy_args.isMember(kLegacyEventUnscopedIdKey)) {
+ event["id"] =
+ PrintUint64(legacy_args[kLegacyEventUnscopedIdKey].asUInt64());
+ }
+
+ if (legacy_args.isMember(kLegacyEventGlobalIdKey)) {
+ event["id2"]["global"] =
+ PrintUint64(legacy_args[kLegacyEventGlobalIdKey].asUInt64());
+ }
+
+ if (legacy_args.isMember(kLegacyEventLocalIdKey)) {
+ event["id2"]["local"] =
+ PrintUint64(legacy_args[kLegacyEventLocalIdKey].asUInt64());
+ }
+
+ if (legacy_args.isMember(kLegacyEventIdScopeKey))
+ event["scope"] = legacy_args[kLegacyEventIdScopeKey];
+
+ ConvertLegacyFlowEventArgs(legacy_args, &event);
+
+ event["args"].removeMember(kLegacyEventArgsKey);
+
+ return event;
+ }
+
+ util::Status ExportRawEvents() {
+ base::Optional<StringId> raw_legacy_event_key_id =
+ storage_->string_pool().GetId("track_event.legacy_event");
+ base::Optional<StringId> raw_legacy_system_trace_event_id =
+ storage_->string_pool().GetId("chrome_event.legacy_system_trace");
+ base::Optional<StringId> raw_legacy_user_trace_event_id =
+ storage_->string_pool().GetId("chrome_event.legacy_user_trace");
+ base::Optional<StringId> raw_chrome_metadata_event_id =
+ storage_->string_pool().GetId("chrome_event.metadata");
+
+ const auto& events = storage_->raw_table();
+ for (uint32_t i = 0; i < events.row_count(); ++i) {
+ if (raw_legacy_event_key_id &&
+ events.name()[i] == *raw_legacy_event_key_id) {
+ Json::Value event = ConvertLegacyRawEventToJson(i);
+ writer_.WriteCommonEvent(event);
+ } else if (raw_legacy_system_trace_event_id &&
+ events.name()[i] == *raw_legacy_system_trace_event_id) {
+ Json::Value args = args_builder_.GetArgs(events.arg_set_id()[i]);
+ PERFETTO_DCHECK(args.isMember("data"));
+ writer_.AddSystemTraceData(args["data"].asString());
+ } else if (raw_legacy_user_trace_event_id &&
+ events.name()[i] == *raw_legacy_user_trace_event_id) {
+ Json::Value args = args_builder_.GetArgs(events.arg_set_id()[i]);
+ PERFETTO_DCHECK(args.isMember("data"));
+ writer_.AddUserTraceData(args["data"].asString());
+ } else if (raw_chrome_metadata_event_id &&
+ events.name()[i] == *raw_chrome_metadata_event_id) {
+ Json::Value args = args_builder_.GetArgs(events.arg_set_id()[i]);
+ writer_.MergeMetadata(args);
+ }
+ }
+ return util::OkStatus();
+ }
+
+ util::Status ExportCpuProfileSamples() {
+ const tables::CpuProfileStackSampleTable& samples =
+ storage_->cpu_profile_stack_sample_table();
+ for (uint32_t i = 0; i < samples.row_count(); ++i) {
+ Json::Value event;
+ event["ts"] = Json::Int64(samples.ts()[i] / 1000);
+
+ UniqueTid utid = static_cast<UniqueTid>(samples.utid()[i]);
+ auto pid_and_tid = UtidToPidAndTid(utid);
+ event["pid"] = Json::Int(pid_and_tid.first);
+ event["tid"] = Json::Int(pid_and_tid.second);
+
+ event["ph"] = "n";
+ event["cat"] = "disabled_by_default-cpu_profiler";
+ event["name"] = "StackCpuSampling";
+ event["s"] = "t";
+
+ // Add a dummy thread timestamp to this event to match the format of
+ // instant events. Useful in the UI to view args of a selected group of
+ // samples.
+ event["tts"] = Json::Int64(1);
+
+ // "n"-phase events are nestable async events which get tied together with
+ // their id, so we need to give each one a unique ID as we only
+ // want the samples to show up on their own track in the trace-viewer but
+ // not nested together.
+ static size_t g_id_counter = 0;
+ event["id"] = PrintUint64(++g_id_counter);
+
+ std::vector<std::string> callstack;
+ const auto& callsites = storage_->stack_profile_callsite_table();
+ int64_t maybe_callsite_id = samples.callsite_id()[i];
+ PERFETTO_DCHECK(maybe_callsite_id >= 0 &&
+ maybe_callsite_id < callsites.row_count());
+ while (maybe_callsite_id >= 0) {
+ uint32_t callsite_id = static_cast<uint32_t>(maybe_callsite_id);
+
+ const auto& frames = storage_->stack_profile_frame_table();
+ PERFETTO_DCHECK(callsites.frame_id()[callsite_id] >= 0 &&
+ callsites.frame_id()[callsite_id] < frames.row_count());
+ uint32_t frame_id =
+ static_cast<uint32_t>(callsites.frame_id()[callsite_id]);
+
+ const auto& mappings = storage_->stack_profile_mapping_table();
+ PERFETTO_DCHECK(frames.mapping()[frame_id] >= 0 &&
+ frames.mapping()[frame_id] < mappings.row_count());
+ uint32_t mapping_id = static_cast<uint32_t>(frames.mapping()[frame_id]);
+
+ NullTermStringView symbol_name;
+ auto opt_symbol_set_id = frames.symbol_set_id()[frame_id];
+ if (opt_symbol_set_id) {
+ symbol_name = storage_->GetString(
+ storage_->symbol_table().name()[*opt_symbol_set_id]);
+ }
+
+ char frame_entry[1024];
+ snprintf(
+ frame_entry, sizeof(frame_entry), "%s - %s [%s]\n",
+ (symbol_name.empty()
+ ? PrintUint64(static_cast<uint64_t>(frames.rel_pc()[frame_id]))
+ .c_str()
+ : symbol_name.c_str()),
+ GetNonNullString(storage_, mappings.name()[mapping_id]),
+ GetNonNullString(storage_, mappings.build_id()[mapping_id]));
+
+ callstack.emplace_back(frame_entry);
+
+ maybe_callsite_id = callsites.parent_id()[callsite_id];
}
- char frame_entry[1024];
- snprintf(
- frame_entry, sizeof(frame_entry), "%s - %s [%s]\n",
- (symbol_name.empty()
- ? PrintUint64(static_cast<uint64_t>(frames.rel_pc()[frame_id]))
- .c_str()
- : symbol_name.c_str()),
- GetNonNullString(storage, mappings.name()[mapping_id]),
- GetNonNullString(storage, mappings.build_id()[mapping_id]));
+ std::string merged_callstack;
+ for (auto entry = callstack.rbegin(); entry != callstack.rend();
+ ++entry) {
+ merged_callstack += *entry;
+ }
- callstack.emplace_back(frame_entry);
+ event["args"]["frames"] = merged_callstack;
- maybe_callsite_id = callsites.parent_id()[callsite_id];
+ // TODO(oysteine): Used for backwards compatibility with the memlog
+ // pipeline, should remove once we've switched to looking directly at the
+ // tid.
+ event["args"]["thread_id"] = Json::Int(pid_and_tid.second);
+
+ writer_.WriteCommonEvent(event);
}
- std::string merged_callstack;
- for (auto entry = callstack.rbegin(); entry != callstack.rend(); ++entry) {
- merged_callstack += *entry;
+ return util::OkStatus();
+ }
+
+ util::Status ExportMetadata() {
+ const auto& trace_metadata = storage_->metadata_table();
+ const auto& keys = trace_metadata.name();
+ const auto& int_values = trace_metadata.int_value();
+ const auto& str_values = trace_metadata.str_value();
+
+ // Create a mapping from key string ids to keys.
+ std::unordered_map<StringId, metadata::KeyIDs> key_map;
+ for (uint32_t i = 0; i < metadata::kNumKeys; ++i) {
+ auto id = *storage_->string_pool().GetId(metadata::kNames[i]);
+ key_map[id] = static_cast<metadata::KeyIDs>(i);
}
- event["args"]["frames"] = merged_callstack;
+ for (uint32_t pos = 0; pos < trace_metadata.row_count(); pos++) {
+ // Cast away from enum type, as otherwise -Wswitch-enum will demand an
+ // exhaustive list of cases, even if there's a default case.
+ metadata::KeyIDs key = key_map[keys[pos]];
+ switch (static_cast<size_t>(key)) {
+ case metadata::benchmark_description:
+ writer_.AppendTelemetryMetadataString(
+ "benchmarkDescriptions",
+ GetNonNullString(storage_, str_values[pos]));
+ break;
- // TODO(oysteine): Used for backwards compatibility with the memlog
- // pipeline, should remove once we've switched to looking directly at the
- // tid.
- event["args"]["thread_id"] = thread.tid;
+ case metadata::benchmark_name:
+ writer_.AppendTelemetryMetadataString(
+ "benchmarks", GetNonNullString(storage_, str_values[pos]));
+ break;
- writer->WriteCommonEvent(event);
- }
+ case metadata::benchmark_start_time_us:
- return util::OkStatus();
-}
+ writer_.SetTelemetryMetadataTimestamp("benchmarkStart",
+ *int_values[pos]);
+ break;
-util::Status ExportMetadata(const TraceStorage* storage,
- TraceFormatWriter* writer) {
- const auto& trace_metadata = storage->metadata_table();
- const auto& keys = trace_metadata.name();
- const auto& int_values = trace_metadata.int_value();
- const auto& str_values = trace_metadata.str_value();
+ case metadata::benchmark_had_failures:
+ writer_.AppendTelemetryMetadataBool("hadFailures", *int_values[pos]);
+ break;
- // Create a mapping from key string ids to keys.
- std::unordered_map<StringId, metadata::KeyIDs> key_map;
- for (uint32_t i = 0; i < metadata::kNumKeys; ++i) {
- auto id = *storage->string_pool().GetId(metadata::kNames[i]);
- key_map[id] = static_cast<metadata::KeyIDs>(i);
- }
+ case metadata::benchmark_label:
+ writer_.AppendTelemetryMetadataString(
+ "labels", GetNonNullString(storage_, str_values[pos]));
+ break;
- for (uint32_t pos = 0; pos < trace_metadata.row_count(); pos++) {
- // Cast away from enum type, as otherwise -Wswitch-enum will demand an
- // exhaustive list of cases, even if there's a default case.
- metadata::KeyIDs key = key_map[keys[pos]];
- switch (static_cast<size_t>(key)) {
- case metadata::benchmark_description:
- writer->AppendTelemetryMetadataString(
- "benchmarkDescriptions",
- GetNonNullString(storage, str_values[pos]));
- break;
+ case metadata::benchmark_story_name:
+ writer_.AppendTelemetryMetadataString(
+ "stories", GetNonNullString(storage_, str_values[pos]));
+ break;
- case metadata::benchmark_name:
- writer->AppendTelemetryMetadataString(
- "benchmarks", GetNonNullString(storage, str_values[pos]));
- break;
+ case metadata::benchmark_story_run_index:
+ writer_.AppendTelemetryMetadataInt("storysetRepeats",
+ *int_values[pos]);
+ break;
- case metadata::benchmark_start_time_us:
+ case metadata::benchmark_story_run_time_us:
+ writer_.SetTelemetryMetadataTimestamp("traceStart", *int_values[pos]);
+ break;
- writer->SetTelemetryMetadataTimestamp("benchmarkStart",
- *int_values[pos]);
- break;
+ case metadata::benchmark_story_tags: // repeated
+ writer_.AppendTelemetryMetadataString(
+ "storyTags", GetNonNullString(storage_, str_values[pos]));
+ break;
- case metadata::benchmark_had_failures:
- writer->AppendTelemetryMetadataBool("hadFailures", *int_values[pos]);
- break;
-
- case metadata::benchmark_label:
- writer->AppendTelemetryMetadataString(
- "labels", GetNonNullString(storage, str_values[pos]));
- break;
-
- case metadata::benchmark_story_name:
- writer->AppendTelemetryMetadataString(
- "stories", GetNonNullString(storage, str_values[pos]));
- break;
-
- case metadata::benchmark_story_run_index:
- writer->AppendTelemetryMetadataInt("storysetRepeats", *int_values[pos]);
- break;
-
- case metadata::benchmark_story_run_time_us:
- writer->SetTelemetryMetadataTimestamp("traceStart", *int_values[pos]);
- break;
-
- case metadata::benchmark_story_tags: // repeated
- writer->AppendTelemetryMetadataString(
- "storyTags", GetNonNullString(storage, str_values[pos]));
- break;
-
- default:
- PERFETTO_DLOG("Ignoring metadata key %zu", static_cast<size_t>(key));
- break;
+ default:
+ PERFETTO_DLOG("Ignoring metadata key %zu", static_cast<size_t>(key));
+ break;
+ }
}
+ return util::OkStatus();
}
- return util::OkStatus();
-}
-util::Status ExportStats(const TraceStorage* storage,
- TraceFormatWriter* writer) {
- const auto& stats = storage->stats();
+ util::Status ExportStats() {
+ const auto& stats = storage_->stats();
- for (size_t idx = 0; idx < stats::kNumKeys; idx++) {
- if (stats::kTypes[idx] == stats::kSingle) {
- writer->SetStats(stats::kNames[idx], stats[idx].value);
- } else {
- PERFETTO_DCHECK(stats::kTypes[idx] == stats::kIndexed);
- writer->SetStats(stats::kNames[idx], stats[idx].indexed_values);
+ for (size_t idx = 0; idx < stats::kNumKeys; idx++) {
+ if (stats::kTypes[idx] == stats::kSingle) {
+ writer_.SetStats(stats::kNames[idx], stats[idx].value);
+ } else {
+ PERFETTO_DCHECK(stats::kTypes[idx] == stats::kIndexed);
+ writer_.SetStats(stats::kNames[idx], stats[idx].indexed_values);
+ }
}
+
+ return util::OkStatus();
}
- return util::OkStatus();
-}
+ uint32_t UpidToPid(UniquePid upid) {
+ auto pid_it = upids_to_exported_pids_.find(upid);
+ PERFETTO_DCHECK(pid_it != upids_to_exported_pids_.end());
+ return pid_it->second;
+ }
+
+ std::pair<uint32_t, uint32_t> UtidToPidAndTid(UniqueTid utid) {
+ auto pid_and_tid_it = utids_to_exported_pids_and_tids_.find(utid);
+ PERFETTO_DCHECK(pid_and_tid_it != utids_to_exported_pids_and_tids_.end());
+ return pid_and_tid_it->second;
+ }
+
+ uint32_t NextExportedPidOrTidForDuplicates() {
+ // Ensure that the exported substitute value does not represent a valid
+ // pid/tid. This would be very unlikely in practice.
+ while (IsValidPidOrTid(next_exported_pid_or_tid_for_duplicates_))
+ next_exported_pid_or_tid_for_duplicates_--;
+ return next_exported_pid_or_tid_for_duplicates_--;
+ }
+
+ bool IsValidPidOrTid(uint32_t pid_or_tid) {
+ const auto& process_table = storage_->process_table();
+ for (UniquePid upid = 0; upid < process_table.row_count(); upid++) {
+ if (process_table.pid()[upid] == pid_or_tid)
+ return true;
+ }
+
+ const auto& thread_table = storage_->thread_table();
+ for (UniqueTid utid = 0; utid < thread_table.row_count(); utid++) {
+ if (thread_table.tid()[utid] == pid_or_tid)
+ return true;
+ }
+
+ return false;
+ }
+
+ const TraceStorage* storage_;
+ ArgsBuilder args_builder_;
+ TraceFormatWriter writer_;
+
+ // If a pid/tid is duplicated between two or more different processes/threads
+ // (pid/tid reuse), we export the subsequent occurrences with different
+ // pids/tids that is visibly different from regular pids/tids - counting down
+ // from uint32_t max.
+ uint32_t next_exported_pid_or_tid_for_duplicates_ =
+ std::numeric_limits<uint32_t>::max();
+
+ std::map<UniquePid, uint32_t> upids_to_exported_pids_;
+ std::map<uint32_t, UniquePid> exported_pids_to_upids_;
+ std::map<UniqueTid, std::pair<uint32_t, uint32_t>>
+ utids_to_exported_pids_and_tids_;
+ std::map<std::pair<uint32_t, uint32_t>, UniqueTid>
+ exported_pids_and_tids_to_utids_;
+};
} // namespace
@@ -1047,40 +1332,9 @@
ArgumentFilterPredicate argument_filter,
MetadataFilterPredicate metadata_filter,
LabelFilterPredicate label_filter) {
- // TODO(eseckler): Implement argument/metadata/label filtering.
- TraceFormatWriter writer(output, argument_filter, metadata_filter,
- label_filter);
- ArgsBuilder args_builder(storage);
-
- util::Status status = ExportThreadNames(storage, &writer);
- if (!status.ok())
- return status;
-
- status = ExportProcessNames(storage, &writer);
- if (!status.ok())
- return status;
-
- status = ExportSlices(storage, args_builder, &writer);
- if (!status.ok())
- return status;
-
- status = ExportRawEvents(storage, args_builder, &writer);
- if (!status.ok())
- return status;
-
- status = ExportCpuProfileSamples(storage, &writer);
- if (!status.ok())
- return status;
-
- status = ExportMetadata(storage, &writer);
- if (!status.ok())
- return status;
-
- status = ExportStats(storage, &writer);
- if (!status.ok())
- return status;
-
- return util::OkStatus();
+ JsonExporter exporter(storage, output, std::move(argument_filter),
+ std::move(metadata_filter), std::move(label_filter));
+ return exporter.Export();
}
util::Status ExportJson(TraceProcessorStorage* tp,
diff --git a/src/trace_processor/export_json_unittest.cc b/src/trace_processor/export_json_unittest.cc
index 7cac7cd..14ca221 100644
--- a/src/trace_processor/export_json_unittest.cc
+++ b/src/trace_processor/export_json_unittest.cc
@@ -27,6 +27,7 @@
#include "perfetto/ext/base/temp_file.h"
#include "src/trace_processor/args_tracker.h"
#include "src/trace_processor/metadata_tracker.h"
+#include "src/trace_processor/process_tracker.h"
#include "src/trace_processor/trace_processor_context.h"
#include "src/trace_processor/track_tracker.h"
@@ -65,10 +66,12 @@
class ExportJsonTest : public ::testing::Test {
public:
ExportJsonTest() {
+ context_.global_args_tracker.reset(new GlobalArgsTracker(&context_));
context_.args_tracker.reset(new ArgsTracker(&context_));
context_.storage.reset(new TraceStorage());
context_.track_tracker.reset(new TrackTracker(&context_));
context_.metadata_tracker.reset(new MetadataTracker(&context_));
+ context_.process_tracker.reset(new ProcessTracker(&context_));
}
std::string ToJson(ArgumentFilterPredicate argument_filter = nullptr,
@@ -111,13 +114,12 @@
const int64_t kThreadDuration = 20000;
const int64_t kThreadInstructionCount = 30000000;
const int64_t kThreadInstructionDelta = 30000;
- const int64_t kThreadID = 100;
+ const uint32_t kThreadID = 100;
const char* kCategory = "cat";
const char* kName = "name";
- UniqueTid utid = context_.storage->AddEmptyThread(kThreadID);
- TrackId track =
- context_.track_tracker->GetOrCreateDescriptorTrackForThread(utid);
+ UniqueTid utid = context_.process_tracker->GetOrCreateThread(kThreadID);
+ TrackId track = context_.track_tracker->InternThreadTrack(utid);
context_.args_tracker->Flush(); // Flush track args.
StringId cat_id = context_.storage->InternString(base::StringView(kCategory));
StringId name_id = context_.storage->InternString(base::StringView(kName));
@@ -144,7 +146,7 @@
EXPECT_EQ(event["tdur"].asInt64(), kThreadDuration / 1000);
EXPECT_EQ(event["ticount"].asInt64(), kThreadInstructionCount);
EXPECT_EQ(event["tidelta"].asInt64(), kThreadInstructionDelta);
- EXPECT_EQ(event["tid"].asUInt(), kThreadID);
+ EXPECT_EQ(event["tid"].asInt(), static_cast<int>(kThreadID));
EXPECT_EQ(event["cat"].asString(), kCategory);
EXPECT_EQ(event["name"].asString(), kName);
EXPECT_TRUE(event["args"].isObject());
@@ -158,13 +160,12 @@
const int64_t kThreadDuration = -1;
const int64_t kThreadInstructionCount = 30000000;
const int64_t kThreadInstructionDelta = -1;
- const int64_t kThreadID = 100;
+ const uint32_t kThreadID = 100;
const char* kCategory = "cat";
const char* kName = "name";
- UniqueTid utid = context_.storage->AddEmptyThread(kThreadID);
- TrackId track =
- context_.track_tracker->GetOrCreateDescriptorTrackForThread(utid);
+ UniqueTid utid = context_.process_tracker->GetOrCreateThread(kThreadID);
+ TrackId track = context_.track_tracker->InternThreadTrack(utid);
context_.args_tracker->Flush(); // Flush track args.
StringId cat_id = context_.storage->InternString(base::StringView(kCategory));
StringId name_id = context_.storage->InternString(base::StringView(kName));
@@ -191,7 +192,7 @@
EXPECT_FALSE(event.isMember("tdur"));
EXPECT_EQ(event["ticount"].asInt64(), kThreadInstructionCount);
EXPECT_FALSE(event.isMember("tidelta"));
- EXPECT_EQ(event["tid"].asUInt(), kThreadID);
+ EXPECT_EQ(event["tid"].asInt(), static_cast<int>(kThreadID));
EXPECT_EQ(event["cat"].asString(), kCategory);
EXPECT_EQ(event["name"].asString(), kName);
EXPECT_TRUE(event["args"].isObject());
@@ -199,12 +200,12 @@
}
TEST_F(ExportJsonTest, StorageWithThreadName) {
- const int64_t kThreadID = 100;
+ const uint32_t kThreadID = 100;
const char* kName = "thread";
- UniqueTid utid = context_.storage->AddEmptyThread(kThreadID);
- StringId name_id = context_.storage->InternString(base::StringView(kName));
- context_.storage->GetMutableThread(utid)->name_id = name_id;
+ tables::ThreadTable::Row row(kThreadID);
+ row.name = context_.storage->InternString(base::StringView(kName));
+ context_.storage->mutable_thread_table()->Insert(row);
base::TempFile temp_file = base::TempFile::Create();
FILE* output = fopen(temp_file.path().c_str(), "w+");
@@ -217,18 +218,19 @@
Json::Value event = result["traceEvents"][0];
EXPECT_EQ(event["ph"].asString(), "M");
- EXPECT_EQ(event["tid"].asUInt(), kThreadID);
+ EXPECT_EQ(event["tid"].asInt(), static_cast<int>(kThreadID));
EXPECT_EQ(event["name"].asString(), "thread_name");
EXPECT_EQ(event["args"]["name"].asString(), kName);
}
-TEST_F(ExportJsonTest, WrongTrackTypeIgnored) {
+TEST_F(ExportJsonTest, SystemEventsIgnored) {
constexpr int64_t kCookie = 22;
TrackId track = context_.track_tracker->InternAndroidAsyncTrack(
- /*name=*/0, /*upid=*/0, kCookie);
+ /*name=*/kNullStringId, /*upid=*/0, kCookie);
context_.args_tracker->Flush(); // Flush track args.
- StringId cat_id = context_.storage->InternString("cat");
+ // System events have no category.
+ StringId cat_id = kNullStringId;
StringId name_id = context_.storage->InternString("name");
context_.storage->mutable_slice_table()->Insert(
{0, 0, track.value, cat_id, name_id, 0, 0, 0});
@@ -371,16 +373,16 @@
TraceStorage* storage = context_.storage.get();
- uint32_t row = storage->mutable_raw_events()->AddRawEvent(
- 0, storage->InternString("chrome_event.metadata"), 0, 0);
+ RawId id = storage->mutable_raw_table()->Insert(
+ {0, storage->InternString("chrome_event.metadata"), 0, 0});
StringId name1_id = storage->InternString(base::StringView(kName1));
StringId name2_id = storage->InternString(base::StringView(kName2));
StringId value1_id = storage->InternString(base::StringView(kValue1));
- context_.args_tracker->AddArg(TableId::kRawEvents, row, name1_id, name1_id,
- Variadic::String(value1_id));
- context_.args_tracker->AddArg(TableId::kRawEvents, row, name2_id, name2_id,
- Variadic::Integer(kValue2));
+
+ context_.args_tracker->AddArgsTo(id)
+ .AddArg(name1_id, Variadic::String(value1_id))
+ .AddArg(name2_id, Variadic::Integer(kValue2));
context_.args_tracker->Flush();
base::TempFile temp_file = base::TempFile::Create();
@@ -402,9 +404,8 @@
const char* kName = "name";
const char* kSrc = "source_file.cc";
- UniqueTid utid = context_.storage->AddEmptyThread(0);
- TrackId track =
- context_.track_tracker->GetOrCreateDescriptorTrackForThread(utid);
+ UniqueTid utid = context_.process_tracker->GetOrCreateThread(0);
+ TrackId track = context_.track_tracker->InternThreadTrack(utid);
context_.args_tracker->Flush(); // Flush track args.
StringId cat_id = context_.storage->InternString(base::StringView(kCategory));
StringId name_id = context_.storage->InternString(base::StringView(kName));
@@ -415,11 +416,11 @@
base::StringView("task.posted_from.file_name"));
StringId arg_value_id =
context_.storage->InternString(base::StringView(kSrc));
- TraceStorage::Args::Arg arg;
+ GlobalArgsTracker::Arg arg;
arg.flat_key = arg_key_id;
arg.key = arg_key_id;
arg.value = Variadic::String(arg_value_id);
- ArgSetId args = context_.storage->mutable_args()->AddArgSet({arg}, 0, 1);
+ ArgSetId args = context_.global_args_tracker->AddArgSet({arg}, 0, 1);
context_.storage->mutable_slice_table()->mutable_arg_set_id()->Set(0, args);
base::TempFile temp_file = base::TempFile::Create();
@@ -447,20 +448,17 @@
TraceStorage* storage = context_.storage.get();
- UniqueTid utid = storage->AddEmptyThread(0);
- TrackId track =
- context_.track_tracker->GetOrCreateDescriptorTrackForThread(utid);
+ UniqueTid utid = context_.process_tracker->GetOrCreateThread(0);
+ TrackId track = context_.track_tracker->InternThreadTrack(utid);
context_.args_tracker->Flush(); // Flush track args.
StringId cat_id = storage->InternString(base::StringView(kCategory));
StringId name_id = storage->InternString(base::StringView(kName));
SliceId id = storage->mutable_slice_table()->Insert(
{0, 0, track.value, cat_id, name_id, 0, 0, 0});
- uint32_t row = *storage->slice_table().id().IndexOf(id);
+ auto inserter = context_.args_tracker->AddArgsTo(id);
auto add_arg = [&](const char* key, Variadic value) {
- StringId key_id = storage->InternString(key);
- context_.args_tracker->AddArg(TableId::kNestableSlices, row, key_id, key_id,
- value);
+ inserter.AddArg(storage->InternString(key), value);
};
add_arg("legacy_event.bind_id", Variadic::UnsignedInteger(kBindId));
@@ -497,9 +495,8 @@
const char* kName = "name";
double kValues[] = {1.234, 2.345};
- UniqueTid utid = context_.storage->AddEmptyThread(0);
- TrackId track =
- context_.track_tracker->GetOrCreateDescriptorTrackForThread(utid);
+ UniqueTid utid = context_.process_tracker->GetOrCreateThread(0);
+ TrackId track = context_.track_tracker->InternThreadTrack(utid);
context_.args_tracker->Flush(); // Flush track args.
StringId cat_id = context_.storage->InternString(base::StringView(kCategory));
StringId name_id = context_.storage->InternString(base::StringView(kName));
@@ -512,16 +509,15 @@
base::StringView("debug.draw_duration_ms[0]"));
StringId arg_key1_id = context_.storage->InternString(
base::StringView("debug.draw_duration_ms[1]"));
- TraceStorage::Args::Arg arg0;
+ GlobalArgsTracker::Arg arg0;
arg0.flat_key = arg_flat_key_id;
arg0.key = arg_key0_id;
arg0.value = Variadic::Real(kValues[0]);
- TraceStorage::Args::Arg arg1;
+ GlobalArgsTracker::Arg arg1;
arg1.flat_key = arg_flat_key_id;
arg1.key = arg_key1_id;
arg1.value = Variadic::Real(kValues[1]);
- ArgSetId args =
- context_.storage->mutable_args()->AddArgSet({arg0, arg1}, 0, 2);
+ ArgSetId args = context_.global_args_tracker->AddArgSet({arg0, arg1}, 0, 2);
context_.storage->mutable_slice_table()->mutable_arg_set_id()->Set(0, args);
base::TempFile temp_file = base::TempFile::Create();
@@ -547,9 +543,8 @@
uint64_t kValue0 = 1;
uint64_t kValue1 = std::numeric_limits<uint64_t>::max();
- UniqueTid utid = context_.storage->AddEmptyThread(0);
- TrackId track =
- context_.track_tracker->GetOrCreateDescriptorTrackForThread(utid);
+ UniqueTid utid = context_.process_tracker->GetOrCreateThread(0);
+ TrackId track = context_.track_tracker->InternThreadTrack(utid);
context_.args_tracker->Flush(); // Flush track args.
StringId cat_id = context_.storage->InternString(base::StringView(kCategory));
StringId name_id = context_.storage->InternString(base::StringView(kName));
@@ -560,16 +555,15 @@
context_.storage->InternString(base::StringView("arg0"));
StringId arg_key1_id =
context_.storage->InternString(base::StringView("arg1"));
- TraceStorage::Args::Arg arg0;
+ GlobalArgsTracker::Arg arg0;
arg0.flat_key = arg_key0_id;
arg0.key = arg_key0_id;
arg0.value = Variadic::Pointer(kValue0);
- TraceStorage::Args::Arg arg1;
+ GlobalArgsTracker::Arg arg1;
arg1.flat_key = arg_key1_id;
arg1.key = arg_key1_id;
arg1.value = Variadic::Pointer(kValue1);
- ArgSetId args =
- context_.storage->mutable_args()->AddArgSet({arg0, arg1}, 0, 2);
+ ArgSetId args = context_.global_args_tracker->AddArgSet({arg0, arg1}, 0, 2);
context_.storage->mutable_slice_table()->mutable_arg_set_id()->Set(0, args);
base::TempFile temp_file = base::TempFile::Create();
@@ -593,9 +587,8 @@
const char* kName = "name";
int kValues[] = {123, 234};
- UniqueTid utid = context_.storage->AddEmptyThread(0);
- TrackId track =
- context_.track_tracker->GetOrCreateDescriptorTrackForThread(utid);
+ UniqueTid utid = context_.process_tracker->GetOrCreateThread(0);
+ TrackId track = context_.track_tracker->InternThreadTrack(utid);
context_.args_tracker->Flush(); // Flush track args.
StringId cat_id = context_.storage->InternString(base::StringView(kCategory));
StringId name_id = context_.storage->InternString(base::StringView(kName));
@@ -608,16 +601,15 @@
context_.storage->InternString(base::StringView("a[0].b"));
StringId arg_key1_id =
context_.storage->InternString(base::StringView("a[1].b"));
- TraceStorage::Args::Arg arg0;
+ GlobalArgsTracker::Arg arg0;
arg0.flat_key = arg_flat_key_id;
arg0.key = arg_key0_id;
arg0.value = Variadic::Integer(kValues[0]);
- TraceStorage::Args::Arg arg1;
+ GlobalArgsTracker::Arg arg1;
arg1.flat_key = arg_flat_key_id;
arg1.key = arg_key1_id;
arg1.value = Variadic::Integer(kValues[1]);
- ArgSetId args =
- context_.storage->mutable_args()->AddArgSet({arg0, arg1}, 0, 2);
+ ArgSetId args = context_.global_args_tracker->AddArgSet({arg0, arg1}, 0, 2);
context_.storage->mutable_slice_table()->mutable_arg_set_id()->Set(0, args);
base::TempFile temp_file = base::TempFile::Create();
@@ -642,9 +634,8 @@
const char* kName = "name";
int kValues[] = {123, 234};
- UniqueTid utid = context_.storage->AddEmptyThread(0);
- TrackId track =
- context_.track_tracker->GetOrCreateDescriptorTrackForThread(utid);
+ UniqueTid utid = context_.process_tracker->GetOrCreateThread(0);
+ TrackId track = context_.track_tracker->InternThreadTrack(utid);
context_.args_tracker->Flush(); // Flush track args.
StringId cat_id = context_.storage->InternString(base::StringView(kCategory));
StringId name_id = context_.storage->InternString(base::StringView(kName));
@@ -657,16 +648,15 @@
context_.storage->InternString(base::StringView("a[0][0]"));
StringId arg_key1_id =
context_.storage->InternString(base::StringView("a[0][1]"));
- TraceStorage::Args::Arg arg0;
+ GlobalArgsTracker::Arg arg0;
arg0.flat_key = arg_flat_key_id;
arg0.key = arg_key0_id;
arg0.value = Variadic::Integer(kValues[0]);
- TraceStorage::Args::Arg arg1;
+ GlobalArgsTracker::Arg arg1;
arg1.flat_key = arg_flat_key_id;
arg1.key = arg_key1_id;
arg1.value = Variadic::Integer(kValues[1]);
- ArgSetId args =
- context_.storage->mutable_args()->AddArgSet({arg0, arg1}, 0, 2);
+ ArgSetId args = context_.global_args_tracker->AddArgSet({arg0, arg1}, 0, 2);
context_.storage->mutable_slice_table()->mutable_arg_set_id()->Set(0, args);
base::TempFile temp_file = base::TempFile::Create();
@@ -691,9 +681,8 @@
const char* kCategory = "cat";
const char* kName = "name";
- UniqueTid utid = context_.storage->AddEmptyThread(0);
- TrackId track =
- context_.track_tracker->GetOrCreateDescriptorTrackForThread(utid);
+ UniqueTid utid = context_.process_tracker->GetOrCreateThread(0);
+ TrackId track = context_.track_tracker->InternThreadTrack(utid);
context_.args_tracker->Flush(); // Flush track args.
StringId cat_id = context_.storage->InternString(base::StringView(kCategory));
StringId name_id = context_.storage->InternString(base::StringView(kName));
@@ -703,11 +692,11 @@
StringId arg_key_id = context_.storage->InternString(base::StringView("a"));
StringId arg_value_id =
context_.storage->InternString(base::StringView("{\"b\":123}"));
- TraceStorage::Args::Arg arg;
+ GlobalArgsTracker::Arg arg;
arg.flat_key = arg_key_id;
arg.key = arg_key_id;
arg.value = Variadic::Json(arg_value_id);
- ArgSetId args = context_.storage->mutable_args()->AddArgSet({arg}, 0, 1);
+ ArgSetId args = context_.global_args_tracker->AddArgSet({arg}, 0, 1);
context_.storage->mutable_slice_table()->mutable_arg_set_id()->Set(0, args);
base::TempFile temp_file = base::TempFile::Create();
@@ -727,9 +716,12 @@
TEST_F(ExportJsonTest, InstantEvent) {
const int64_t kTimestamp = 10000000;
+ const int64_t kTimestamp2 = 10001000;
+ const int64_t kTimestamp3 = 10002000;
const char* kCategory = "cat";
const char* kName = "name";
+ // Global legacy track.
TrackId track =
context_.track_tracker->GetOrCreateLegacyChromeGlobalInstantTrack();
context_.args_tracker->Flush(); // Flush track args.
@@ -738,6 +730,19 @@
context_.storage->mutable_slice_table()->Insert(
{kTimestamp, 0, track.value, cat_id, name_id, 0, 0, 0});
+ // Global track.
+ TrackId track2 = context_.track_tracker->GetOrCreateDefaultDescriptorTrack();
+ context_.args_tracker->Flush(); // Flush track args.
+ context_.storage->mutable_slice_table()->Insert(
+ {kTimestamp2, 0, track2.value, cat_id, name_id, 0, 0, 0});
+
+ // Async event track.
+ context_.track_tracker->ReserveDescriptorChildTrack(1234, 0);
+ TrackId track3 = *context_.track_tracker->GetDescriptorTrack(1234);
+ context_.args_tracker->Flush(); // Flush track args.
+ context_.storage->mutable_slice_table()->Insert(
+ {kTimestamp3, 0, track3.value, cat_id, name_id, 0, 0, 0});
+
base::TempFile temp_file = base::TempFile::Create();
FILE* output = fopen(temp_file.path().c_str(), "w+");
util::Status status = ExportJson(context_.storage.get(), output);
@@ -745,7 +750,7 @@
EXPECT_TRUE(status.ok());
Json::Value result = ToJsonValue(ReadFile(output));
- EXPECT_EQ(result["traceEvents"].size(), 1u);
+ EXPECT_EQ(result["traceEvents"].size(), 3u);
Json::Value event = result["traceEvents"][0];
EXPECT_EQ(event["ph"].asString(), "I");
@@ -753,17 +758,30 @@
EXPECT_EQ(event["s"].asString(), "g");
EXPECT_EQ(event["cat"].asString(), kCategory);
EXPECT_EQ(event["name"].asString(), kName);
+
+ Json::Value event2 = result["traceEvents"][1];
+ EXPECT_EQ(event2["ph"].asString(), "I");
+ EXPECT_EQ(event2["ts"].asInt64(), kTimestamp2 / 1000);
+ EXPECT_EQ(event2["s"].asString(), "g");
+ EXPECT_EQ(event2["cat"].asString(), kCategory);
+ EXPECT_EQ(event2["name"].asString(), kName);
+
+ Json::Value event3 = result["traceEvents"][2];
+ EXPECT_EQ(event3["ph"].asString(), "n");
+ EXPECT_EQ(event3["ts"].asInt64(), kTimestamp3 / 1000);
+ EXPECT_EQ(event3["id"].asString(), "0x2");
+ EXPECT_EQ(event3["cat"].asString(), kCategory);
+ EXPECT_EQ(event3["name"].asString(), kName);
}
TEST_F(ExportJsonTest, InstantEventOnThread) {
const int64_t kTimestamp = 10000000;
- const int64_t kThreadID = 100;
+ const uint32_t kThreadID = 100;
const char* kCategory = "cat";
const char* kName = "name";
- UniqueTid utid = context_.storage->AddEmptyThread(kThreadID);
- TrackId track =
- context_.track_tracker->GetOrCreateDescriptorTrackForThread(utid);
+ UniqueTid utid = context_.process_tracker->GetOrCreateThread(kThreadID);
+ TrackId track = context_.track_tracker->InternThreadTrack(utid);
context_.args_tracker->Flush(); // Flush track args.
StringId cat_id = context_.storage->InternString(base::StringView(kCategory));
StringId name_id = context_.storage->InternString(base::StringView(kName));
@@ -780,7 +798,7 @@
EXPECT_EQ(result["traceEvents"].size(), 1u);
Json::Value event = result["traceEvents"][0];
- EXPECT_EQ(event["tid"].asUInt(), kThreadID);
+ EXPECT_EQ(event["tid"].asInt(), static_cast<int>(kThreadID));
EXPECT_EQ(event["ph"].asString(), "I");
EXPECT_EQ(event["ts"].asInt64(), kTimestamp / 1000);
EXPECT_EQ(event["s"].asString(), "t");
@@ -788,41 +806,62 @@
EXPECT_EQ(event["name"].asString(), kName);
}
-TEST_F(ExportJsonTest, AsyncEvents) {
- const int64_t kTimestamp = 10000000;
- const int64_t kDuration = 100000;
- const int64_t kProcessID = 100;
- const char* kCategory = "cat";
- const char* kName = "name";
- const char* kName2 = "name2";
- const char* kArgName = "arg_name";
- const int kArgValue = 123;
+TEST_F(ExportJsonTest, DuplicatePidAndTid) {
+ UniqueTid upid1 = context_.process_tracker->StartNewProcess(
+ base::nullopt, base::nullopt, 1, kNullStringId);
+ UniqueTid utid1a = context_.process_tracker->UpdateThread(1, 1);
+ UniqueTid utid1b = context_.process_tracker->UpdateThread(2, 1);
+ UniqueTid utid1c =
+ context_.process_tracker->StartNewThread(base::nullopt, 2, kNullStringId);
+ // Associate the new thread with its process.
+ ASSERT_EQ(utid1c, context_.process_tracker->UpdateThread(2, 1));
- UniquePid upid = context_.storage->AddEmptyProcess(kProcessID);
- StringId cat_id = context_.storage->InternString(base::StringView(kCategory));
- StringId name_id = context_.storage->InternString(base::StringView(kName));
- StringId name2_id = context_.storage->InternString(base::StringView(kName2));
+ UniqueTid upid2 = context_.process_tracker->StartNewProcess(
+ base::nullopt, base::nullopt, 1, kNullStringId);
+ UniqueTid utid2a = context_.process_tracker->UpdateThread(1, 1);
+ UniqueTid utid2b = context_.process_tracker->UpdateThread(2, 1);
- constexpr int64_t kSourceId = 235;
- TrackId track = context_.track_tracker->InternLegacyChromeAsyncTrack(
- name_id, upid, kSourceId, /*source_id_is_process_scoped=*/true,
- /*source_scope=*/0);
+ ASSERT_NE(upid1, upid2);
+ ASSERT_NE(utid1b, utid1c);
+ ASSERT_NE(utid1a, utid2a);
+ ASSERT_NE(utid1b, utid2b);
+ ASSERT_NE(utid1c, utid2b);
+
+ ASSERT_EQ(upid1, *context_.storage->thread_table().upid()[utid1a]);
+ ASSERT_EQ(upid1, *context_.storage->thread_table().upid()[utid1b]);
+ ASSERT_EQ(upid1, *context_.storage->thread_table().upid()[utid1c]);
+ ASSERT_EQ(upid2, *context_.storage->thread_table().upid()[utid2a]);
+ ASSERT_EQ(upid2, *context_.storage->thread_table().upid()[utid2b]);
+
+ TrackId track1a = context_.track_tracker->InternThreadTrack(utid1a);
+ TrackId track1b = context_.track_tracker->InternThreadTrack(utid1b);
+ TrackId track1c = context_.track_tracker->InternThreadTrack(utid1c);
+ TrackId track2a = context_.track_tracker->InternThreadTrack(utid2a);
+ TrackId track2b = context_.track_tracker->InternThreadTrack(utid2b);
context_.args_tracker->Flush(); // Flush track args.
- context_.storage->mutable_slice_table()->Insert(
- {kTimestamp, kDuration, track.value, cat_id, name_id, 0, 0, 0});
- StringId arg_key_id =
- context_.storage->InternString(base::StringView(kArgName));
- TraceStorage::Args::Arg arg;
- arg.flat_key = arg_key_id;
- arg.key = arg_key_id;
- arg.value = Variadic::Integer(kArgValue);
- ArgSetId args = context_.storage->mutable_args()->AddArgSet({arg}, 0, 1);
- context_.storage->mutable_slice_table()->mutable_arg_set_id()->Set(0, args);
+ StringId cat_id = context_.storage->InternString(base::StringView("cat"));
+ StringId name1a_id =
+ context_.storage->InternString(base::StringView("name1a"));
+ StringId name1b_id =
+ context_.storage->InternString(base::StringView("name1b"));
+ StringId name1c_id =
+ context_.storage->InternString(base::StringView("name1c"));
+ StringId name2a_id =
+ context_.storage->InternString(base::StringView("name2a"));
+ StringId name2b_id =
+ context_.storage->InternString(base::StringView("name2b"));
- // Child event with same timestamps as first one.
context_.storage->mutable_slice_table()->Insert(
- {kTimestamp, kDuration, track.value, cat_id, name2_id, 0, 0, 0});
+ {10000, 0, track1a.value, cat_id, name1a_id, 0, 0, 0});
+ context_.storage->mutable_slice_table()->Insert(
+ {20000, 1000, track1b.value, cat_id, name1b_id, 0, 0, 0});
+ context_.storage->mutable_slice_table()->Insert(
+ {30000, 0, track1c.value, cat_id, name1c_id, 0, 0, 0});
+ context_.storage->mutable_slice_table()->Insert(
+ {40000, 0, track2a.value, cat_id, name2a_id, 0, 0, 0});
+ context_.storage->mutable_slice_table()->Insert(
+ {50000, 1000, track2b.value, cat_id, name2b_id, 0, 0, 0});
base::TempFile temp_file = base::TempFile::Create();
FILE* output = fopen(temp_file.path().c_str(), "w+");
@@ -831,12 +870,113 @@
EXPECT_TRUE(status.ok());
Json::Value result = ToJsonValue(ReadFile(output));
- EXPECT_EQ(result["traceEvents"].size(), 4u);
+ EXPECT_EQ(result["traceEvents"].size(), 5u);
+
+ EXPECT_EQ(result["traceEvents"][0]["pid"].asInt(), 1);
+ EXPECT_EQ(result["traceEvents"][0]["tid"].asInt(), 1);
+ EXPECT_EQ(result["traceEvents"][0]["ph"].asString(), "I");
+ EXPECT_EQ(result["traceEvents"][0]["ts"].asInt64(), 10);
+ EXPECT_EQ(result["traceEvents"][0]["cat"].asString(), "cat");
+ EXPECT_EQ(result["traceEvents"][0]["name"].asString(), "name1a");
+
+ EXPECT_EQ(result["traceEvents"][1]["pid"].asInt(), 1);
+ EXPECT_EQ(result["traceEvents"][1]["tid"].asInt(), 2);
+ EXPECT_EQ(result["traceEvents"][1]["ph"].asString(), "X");
+ EXPECT_EQ(result["traceEvents"][1]["ts"].asInt64(), 20);
+ EXPECT_EQ(result["traceEvents"][1]["dur"].asInt64(), 1);
+ EXPECT_EQ(result["traceEvents"][1]["cat"].asString(), "cat");
+ EXPECT_EQ(result["traceEvents"][1]["name"].asString(), "name1b");
+
+ EXPECT_EQ(result["traceEvents"][2]["pid"].asInt(), 1);
+ EXPECT_EQ(result["traceEvents"][2]["tid"].asInt(),
+ static_cast<int>(std::numeric_limits<uint32_t>::max() - 1u));
+ EXPECT_EQ(result["traceEvents"][2]["ph"].asString(), "I");
+ EXPECT_EQ(result["traceEvents"][2]["ts"].asInt64(), 30);
+ EXPECT_EQ(result["traceEvents"][2]["cat"].asString(), "cat");
+ EXPECT_EQ(result["traceEvents"][2]["name"].asString(), "name1c");
+
+ EXPECT_EQ(result["traceEvents"][3]["pid"].asInt(),
+ static_cast<int>(std::numeric_limits<uint32_t>::max()));
+ EXPECT_EQ(result["traceEvents"][3]["tid"].asInt(), 1);
+ EXPECT_EQ(result["traceEvents"][3]["ph"].asString(), "I");
+ EXPECT_EQ(result["traceEvents"][3]["ts"].asInt64(), 40);
+ EXPECT_EQ(result["traceEvents"][3]["cat"].asString(), "cat");
+ EXPECT_EQ(result["traceEvents"][3]["name"].asString(), "name2a");
+
+ EXPECT_EQ(result["traceEvents"][4]["pid"].asInt(),
+ static_cast<int>(std::numeric_limits<uint32_t>::max()));
+ EXPECT_EQ(result["traceEvents"][4]["tid"].asInt(), 2);
+ EXPECT_EQ(result["traceEvents"][4]["ph"].asString(), "X");
+ EXPECT_EQ(result["traceEvents"][4]["ts"].asInt64(), 50);
+ EXPECT_EQ(result["traceEvents"][1]["dur"].asInt64(), 1);
+ EXPECT_EQ(result["traceEvents"][4]["cat"].asString(), "cat");
+ EXPECT_EQ(result["traceEvents"][4]["name"].asString(), "name2b");
+}
+
+TEST_F(ExportJsonTest, AsyncEvents) {
+ const int64_t kTimestamp = 10000000;
+ const int64_t kDuration = 100000;
+ const int64_t kTimestamp3 = 10005000;
+ const int64_t kDuration3 = 100000;
+ const uint32_t kProcessID = 100;
+ const char* kCategory = "cat";
+ const char* kName = "name";
+ const char* kName2 = "name2";
+ const char* kName3 = "name3";
+ const char* kArgName = "arg_name";
+ const int kArgValue = 123;
+
+ UniquePid upid = context_.process_tracker->GetOrCreateProcess(kProcessID);
+ StringId cat_id = context_.storage->InternString(base::StringView(kCategory));
+ StringId name_id = context_.storage->InternString(base::StringView(kName));
+ StringId name2_id = context_.storage->InternString(base::StringView(kName2));
+ StringId name3_id = context_.storage->InternString(base::StringView(kName3));
+
+ constexpr int64_t kSourceId = 235;
+ TrackId track = context_.track_tracker->InternLegacyChromeAsyncTrack(
+ name_id, upid, kSourceId, /*source_id_is_process_scoped=*/true,
+ /*source_scope=*/kNullStringId);
+ constexpr int64_t kSourceId2 = 236;
+ TrackId track2 = context_.track_tracker->InternLegacyChromeAsyncTrack(
+ name3_id, upid, kSourceId2, /*source_id_is_process_scoped=*/true,
+ /*source_scope=*/kNullStringId);
+ context_.args_tracker->Flush(); // Flush track args.
+
+ context_.storage->mutable_slice_table()->Insert(
+ {kTimestamp, kDuration, track.value, cat_id, name_id, 0, 0, 0});
+ StringId arg_key_id =
+ context_.storage->InternString(base::StringView(kArgName));
+ GlobalArgsTracker::Arg arg;
+ arg.flat_key = arg_key_id;
+ arg.key = arg_key_id;
+ arg.value = Variadic::Integer(kArgValue);
+ ArgSetId args = context_.global_args_tracker->AddArgSet({arg}, 0, 1);
+ context_.storage->mutable_slice_table()->mutable_arg_set_id()->Set(0, args);
+
+ // Child event with same timestamps as first one.
+ context_.storage->mutable_slice_table()->Insert(
+ {kTimestamp, kDuration, track.value, cat_id, name2_id, 0, 0, 0});
+
+ // Another overlapping async event on a different track.
+ context_.storage->mutable_slice_table()->Insert(
+ {kTimestamp3, kDuration3, track2.value, cat_id, name3_id, 0, 0, 0});
+
+ base::TempFile temp_file = base::TempFile::Create();
+ FILE* output = fopen(temp_file.path().c_str(), "w+");
+ util::Status status = ExportJson(context_.storage.get(), output);
+
+ EXPECT_TRUE(status.ok());
+
+ Json::Value result = ToJsonValue(ReadFile(output));
+ EXPECT_EQ(result["traceEvents"].size(), 6u);
+
+ // Events should be sorted by timestamp, with child slice's end before its
+ // parent.
Json::Value begin_event1 = result["traceEvents"][0];
EXPECT_EQ(begin_event1["ph"].asString(), "b");
EXPECT_EQ(begin_event1["ts"].asInt64(), kTimestamp / 1000);
- EXPECT_EQ(begin_event1["pid"].asInt64(), kProcessID);
+ EXPECT_EQ(begin_event1["pid"].asInt(), static_cast<int>(kProcessID));
EXPECT_EQ(begin_event1["id2"]["local"].asString(), "0xeb");
EXPECT_EQ(begin_event1["cat"].asString(), kCategory);
EXPECT_EQ(begin_event1["name"].asString(), kName);
@@ -847,7 +987,7 @@
Json::Value begin_event2 = result["traceEvents"][1];
EXPECT_EQ(begin_event2["ph"].asString(), "b");
EXPECT_EQ(begin_event2["ts"].asInt64(), kTimestamp / 1000);
- EXPECT_EQ(begin_event2["pid"].asInt64(), kProcessID);
+ EXPECT_EQ(begin_event2["pid"].asInt(), static_cast<int>(kProcessID));
EXPECT_EQ(begin_event2["id2"]["local"].asString(), "0xeb");
EXPECT_EQ(begin_event2["cat"].asString(), kCategory);
EXPECT_EQ(begin_event2["name"].asString(), kName2);
@@ -856,22 +996,34 @@
EXPECT_FALSE(begin_event2.isMember("tts"));
EXPECT_FALSE(begin_event2.isMember("use_async_tts"));
+ Json::Value begin_event3 = result["traceEvents"][2];
+ EXPECT_EQ(begin_event3["ph"].asString(), "b");
+ EXPECT_EQ(begin_event3["ts"].asInt64(), kTimestamp3 / 1000);
+ EXPECT_EQ(begin_event3["pid"].asInt(), static_cast<int>(kProcessID));
+ EXPECT_EQ(begin_event3["id2"]["local"].asString(), "0xec");
+ EXPECT_EQ(begin_event3["cat"].asString(), kCategory);
+ EXPECT_EQ(begin_event3["name"].asString(), kName3);
+ EXPECT_TRUE(begin_event3["args"].isObject());
+ EXPECT_EQ(begin_event3["args"].size(), 0u);
+ EXPECT_FALSE(begin_event3.isMember("tts"));
+ EXPECT_FALSE(begin_event3.isMember("use_async_tts"));
+
Json::Value end_event2 = result["traceEvents"][3];
EXPECT_EQ(end_event2["ph"].asString(), "e");
EXPECT_EQ(end_event2["ts"].asInt64(), (kTimestamp + kDuration) / 1000);
- EXPECT_EQ(end_event2["pid"].asInt64(), kProcessID);
+ EXPECT_EQ(end_event2["pid"].asInt(), static_cast<int>(kProcessID));
EXPECT_EQ(end_event2["id2"]["local"].asString(), "0xeb");
EXPECT_EQ(end_event2["cat"].asString(), kCategory);
- EXPECT_EQ(end_event2["name"].asString(), kName);
+ EXPECT_EQ(end_event2["name"].asString(), kName2);
EXPECT_TRUE(end_event2["args"].isObject());
EXPECT_EQ(end_event2["args"].size(), 0u);
EXPECT_FALSE(end_event2.isMember("tts"));
EXPECT_FALSE(end_event2.isMember("use_async_tts"));
- Json::Value end_event1 = result["traceEvents"][3];
+ Json::Value end_event1 = result["traceEvents"][4];
EXPECT_EQ(end_event1["ph"].asString(), "e");
EXPECT_EQ(end_event1["ts"].asInt64(), (kTimestamp + kDuration) / 1000);
- EXPECT_EQ(end_event1["pid"].asInt64(), kProcessID);
+ EXPECT_EQ(end_event1["pid"].asInt(), static_cast<int>(kProcessID));
EXPECT_EQ(end_event1["id2"]["local"].asString(), "0xeb");
EXPECT_EQ(end_event1["cat"].asString(), kCategory);
EXPECT_EQ(end_event1["name"].asString(), kName);
@@ -879,6 +1031,18 @@
EXPECT_EQ(end_event1["args"].size(), 0u);
EXPECT_FALSE(end_event1.isMember("tts"));
EXPECT_FALSE(end_event1.isMember("use_async_tts"));
+
+ Json::Value end_event3 = result["traceEvents"][5];
+ EXPECT_EQ(end_event3["ph"].asString(), "e");
+ EXPECT_EQ(end_event3["ts"].asInt64(), (kTimestamp3 + kDuration3) / 1000);
+ EXPECT_EQ(end_event3["pid"].asInt(), static_cast<int>(kProcessID));
+ EXPECT_EQ(end_event3["id2"]["local"].asString(), "0xec");
+ EXPECT_EQ(end_event3["cat"].asString(), kCategory);
+ EXPECT_EQ(end_event3["name"].asString(), kName3);
+ EXPECT_TRUE(end_event3["args"].isObject());
+ EXPECT_EQ(end_event3["args"].size(), 0u);
+ EXPECT_FALSE(end_event3.isMember("tts"));
+ EXPECT_FALSE(end_event3.isMember("use_async_tts"));
}
TEST_F(ExportJsonTest, AsyncEventWithThreadTimestamp) {
@@ -886,18 +1050,18 @@
const int64_t kDuration = 100000;
const int64_t kThreadTimestamp = 10000001;
const int64_t kThreadDuration = 99998;
- const int64_t kProcessID = 100;
+ const uint32_t kProcessID = 100;
const char* kCategory = "cat";
const char* kName = "name";
- UniquePid upid = context_.storage->AddEmptyProcess(kProcessID);
+ UniquePid upid = context_.process_tracker->GetOrCreateProcess(kProcessID);
StringId cat_id = context_.storage->InternString(base::StringView(kCategory));
StringId name_id = context_.storage->InternString(base::StringView(kName));
constexpr int64_t kSourceId = 235;
TrackId track = context_.track_tracker->InternLegacyChromeAsyncTrack(
name_id, upid, kSourceId, /*source_id_is_process_scoped=*/true,
- /*source_scope=*/0);
+ /*source_scope=*/kNullStringId);
context_.args_tracker->Flush(); // Flush track args.
auto slice_id = context_.storage->mutable_slice_table()->Insert(
@@ -919,7 +1083,7 @@
EXPECT_EQ(begin_event["ts"].asInt64(), kTimestamp / 1000);
EXPECT_EQ(begin_event["tts"].asInt64(), kThreadTimestamp / 1000);
EXPECT_EQ(begin_event["use_async_tts"].asInt(), 1);
- EXPECT_EQ(begin_event["pid"].asInt64(), kProcessID);
+ EXPECT_EQ(begin_event["pid"].asInt(), static_cast<int>(kProcessID));
EXPECT_EQ(begin_event["id2"]["local"].asString(), "0xeb");
EXPECT_EQ(begin_event["cat"].asString(), kCategory);
EXPECT_EQ(begin_event["name"].asString(), kName);
@@ -930,7 +1094,7 @@
EXPECT_EQ(end_event["tts"].asInt64(),
(kThreadTimestamp + kThreadDuration) / 1000);
EXPECT_EQ(end_event["use_async_tts"].asInt(), 1);
- EXPECT_EQ(end_event["pid"].asInt64(), kProcessID);
+ EXPECT_EQ(end_event["pid"].asInt(), static_cast<int>(kProcessID));
EXPECT_EQ(end_event["id2"]["local"].asString(), "0xeb");
EXPECT_EQ(end_event["cat"].asString(), kCategory);
EXPECT_EQ(end_event["name"].asString(), kName);
@@ -941,18 +1105,18 @@
const int64_t kDuration = -1;
const int64_t kThreadTimestamp = 10000001;
const int64_t kThreadDuration = -1;
- const int64_t kProcessID = 100;
+ const uint32_t kProcessID = 100;
const char* kCategory = "cat";
const char* kName = "name";
- UniquePid upid = context_.storage->AddEmptyProcess(kProcessID);
+ UniquePid upid = context_.process_tracker->GetOrCreateProcess(kProcessID);
StringId cat_id = context_.storage->InternString(base::StringView(kCategory));
StringId name_id = context_.storage->InternString(base::StringView(kName));
constexpr int64_t kSourceId = 235;
TrackId track = context_.track_tracker->InternLegacyChromeAsyncTrack(
name_id, upid, kSourceId, /*source_id_is_process_scoped=*/true,
- /*source_scope=*/0);
+ /*source_scope=*/kNullStringId);
context_.args_tracker->Flush(); // Flush track args.
auto slice_id = context_.storage->mutable_slice_table()->Insert(
@@ -974,7 +1138,7 @@
EXPECT_EQ(begin_event["ts"].asInt64(), kTimestamp / 1000);
EXPECT_EQ(begin_event["tts"].asInt64(), kThreadTimestamp / 1000);
EXPECT_EQ(begin_event["use_async_tts"].asInt(), 1);
- EXPECT_EQ(begin_event["pid"].asInt64(), kProcessID);
+ EXPECT_EQ(begin_event["pid"].asInt(), static_cast<int>(kProcessID));
EXPECT_EQ(begin_event["id2"]["local"].asString(), "0xeb");
EXPECT_EQ(begin_event["cat"].asString(), kCategory);
EXPECT_EQ(begin_event["name"].asString(), kName);
@@ -982,31 +1146,31 @@
TEST_F(ExportJsonTest, AsyncInstantEvent) {
const int64_t kTimestamp = 10000000;
- const int64_t kProcessID = 100;
+ const uint32_t kProcessID = 100;
const char* kCategory = "cat";
const char* kName = "name";
const char* kArgName = "arg_name";
const int kArgValue = 123;
- UniquePid upid = context_.storage->AddEmptyProcess(kProcessID);
+ UniquePid upid = context_.process_tracker->GetOrCreateProcess(kProcessID);
StringId cat_id = context_.storage->InternString(base::StringView(kCategory));
StringId name_id = context_.storage->InternString(base::StringView(kName));
constexpr int64_t kSourceId = 235;
TrackId track = context_.track_tracker->InternLegacyChromeAsyncTrack(
name_id, upid, kSourceId, /*source_id_is_process_scoped=*/true,
- /*source_scope=*/0);
+ /*source_scope=*/kNullStringId);
context_.args_tracker->Flush(); // Flush track args.
context_.storage->mutable_slice_table()->Insert(
{kTimestamp, 0, track.value, cat_id, name_id, 0, 0, 0});
StringId arg_key_id =
context_.storage->InternString(base::StringView("arg_name"));
- TraceStorage::Args::Arg arg;
+ GlobalArgsTracker::Arg arg;
arg.flat_key = arg_key_id;
arg.key = arg_key_id;
arg.value = Variadic::Integer(kArgValue);
- ArgSetId args = context_.storage->mutable_args()->AddArgSet({arg}, 0, 1);
+ ArgSetId args = context_.global_args_tracker->AddArgSet({arg}, 0, 1);
context_.storage->mutable_slice_table()->mutable_arg_set_id()->Set(0, args);
base::TempFile temp_file = base::TempFile::Create();
@@ -1021,7 +1185,7 @@
Json::Value event = result["traceEvents"][0];
EXPECT_EQ(event["ph"].asString(), "n");
EXPECT_EQ(event["ts"].asInt64(), kTimestamp / 1000);
- EXPECT_EQ(event["pid"].asInt64(), kProcessID);
+ EXPECT_EQ(event["pid"].asInt(), static_cast<int>(kProcessID));
EXPECT_EQ(event["id2"]["local"].asString(), "0xeb");
EXPECT_EQ(event["cat"].asString(), kCategory);
EXPECT_EQ(event["name"].asString(), kName);
@@ -1035,8 +1199,8 @@
const int64_t kThreadDuration = 20000;
const int64_t kThreadInstructionCount = 30000000;
const int64_t kThreadInstructionDelta = 30000;
- const int64_t kProcessID = 100;
- const int64_t kThreadID = 200;
+ const uint32_t kProcessID = 100;
+ const uint32_t kThreadID = 200;
const char* kCategory = "cat";
const char* kName = "name";
const char* kPhase = "?";
@@ -1049,18 +1213,18 @@
TraceStorage* storage = context_.storage.get();
- UniquePid upid = storage->AddEmptyProcess(kProcessID);
- UniqueTid utid = storage->AddEmptyThread(kThreadID);
- storage->GetMutableThread(utid)->upid = upid;
+ UniqueTid utid = context_.process_tracker->GetOrCreateThread(kThreadID);
+ UniquePid upid = context_.process_tracker->GetOrCreateProcess(kProcessID);
+ context_.storage->mutable_thread_table()->mutable_upid()->Set(utid, upid);
- uint32_t row = storage->mutable_raw_events()->AddRawEvent(
- kTimestamp, storage->InternString("track_event.legacy_event"), /*cpu=*/0,
- utid);
+ RawId id = storage->mutable_raw_table()->Insert(
+ {kTimestamp, storage->InternString("track_event.legacy_event"), /*cpu=*/0,
+ utid});
+ auto inserter = context_.args_tracker->AddArgsTo(id);
auto add_arg = [&](const char* key, Variadic value) {
StringId key_id = storage->InternString(key);
- context_.args_tracker->AddArg(TableId::kRawEvents, row, key_id, key_id,
- value);
+ inserter.AddArg(key_id, value);
};
StringId cat_id = storage->InternString(base::StringView(kCategory));
@@ -1109,7 +1273,7 @@
EXPECT_EQ(event["tdur"].asInt64(), kThreadDuration / 1000);
EXPECT_EQ(event["ticount"].asInt64(), kThreadInstructionCount);
EXPECT_EQ(event["tidelta"].asInt64(), kThreadInstructionDelta);
- EXPECT_EQ(event["tid"].asUInt(), kThreadID);
+ EXPECT_EQ(event["tid"].asInt(), static_cast<int>(kThreadID));
EXPECT_EQ(event["cat"].asString(), kCategory);
EXPECT_EQ(event["name"].asString(), kName);
EXPECT_EQ(event["use_async_tts"].asInt(), 1);
@@ -1129,25 +1293,25 @@
TraceStorage* storage = context_.storage.get();
- uint32_t row = storage->mutable_raw_events()->AddRawEvent(
- 0, storage->InternString("chrome_event.legacy_system_trace"), 0, 0);
+ RawId id = storage->mutable_raw_table()->Insert(
+ {0, storage->InternString("chrome_event.legacy_system_trace"), 0, 0});
+ auto inserter = context_.args_tracker->AddArgsTo(id);
StringId data_id = storage->InternString("data");
StringId ftrace_data_id = storage->InternString(kLegacyFtraceData);
- context_.args_tracker->AddArg(TableId::kRawEvents, row, data_id, data_id,
- Variadic::String(ftrace_data_id));
+ inserter.AddArg(data_id, Variadic::String(ftrace_data_id));
- row = storage->mutable_raw_events()->AddRawEvent(
- 0, storage->InternString("chrome_event.legacy_user_trace"), 0, 0);
+ id = storage->mutable_raw_table()->Insert(
+ {0, storage->InternString("chrome_event.legacy_user_trace"), 0, 0});
+ inserter = context_.args_tracker->AddArgsTo(id);
StringId json_data1_id = storage->InternString(kLegacyJsonData1);
- context_.args_tracker->AddArg(TableId::kRawEvents, row, data_id, data_id,
- Variadic::String(json_data1_id));
+ inserter.AddArg(data_id, Variadic::String(json_data1_id));
- row = storage->mutable_raw_events()->AddRawEvent(
- 0, storage->InternString("chrome_event.legacy_user_trace"), 0, 0);
+ id = storage->mutable_raw_table()->Insert(
+ {0, storage->InternString("chrome_event.legacy_user_trace"), 0, 0});
+ inserter = context_.args_tracker->AddArgsTo(id);
StringId json_data2_id = storage->InternString(kLegacyJsonData2);
- context_.args_tracker->AddArg(TableId::kRawEvents, row, data_id, data_id,
- Variadic::String(json_data2_id));
+ inserter.AddArg(data_id, Variadic::String(json_data2_id));
context_.args_tracker->Flush();
@@ -1166,15 +1330,15 @@
}
TEST_F(ExportJsonTest, CpuProfileEvent) {
- const int64_t kProcessID = 100;
- const int64_t kThreadID = 200;
+ const uint32_t kProcessID = 100;
+ const uint32_t kThreadID = 200;
const int64_t kTimestamp = 10000000;
TraceStorage* storage = context_.storage.get();
- UniquePid upid = storage->AddEmptyProcess(kProcessID);
- UniqueTid utid = storage->AddEmptyThread(kThreadID);
- storage->GetMutableThread(utid)->upid = upid;
+ UniqueTid utid = context_.process_tracker->GetOrCreateThread(kThreadID);
+ UniquePid upid = context_.process_tracker->GetOrCreateProcess(kProcessID);
+ context_.storage->mutable_thread_table()->mutable_upid()->Set(utid, upid);
auto module_id_1 = storage->mutable_stack_profile_mapping_table()->Insert(
{storage->InternString("foo_module_id"), 0, 0, 0, 0, 0,
@@ -1186,10 +1350,11 @@
// TODO(140860736): Once we support null values for
// stack_profile_frame.symbol_set_id remove this hack
- storage->mutable_symbol_table()->Insert({0, 0, 0, 0});
+ storage->mutable_symbol_table()->Insert({0, kNullStringId, kNullStringId, 0});
auto* frames = storage->mutable_stack_profile_frame_table();
- auto frame_id_1 = frames->Insert({/*name_id=*/0, module_id_1.value, 0x42});
+ auto frame_id_1 =
+ frames->Insert({/*name_id=*/kNullStringId, module_id_1.value, 0x42});
uint32_t frame_row_1 = *frames->id().IndexOf(frame_id_1);
uint32_t symbol_set_id = storage->symbol_table().row_count();
@@ -1198,7 +1363,8 @@
storage->InternString("foo_file"), 66});
frames->mutable_symbol_set_id()->Set(frame_row_1, symbol_set_id);
- auto frame_id_2 = frames->Insert({/*name_id=*/0, module_id_2.value, 0x4242});
+ auto frame_id_2 =
+ frames->Insert({/*name_id=*/kNullStringId, module_id_2.value, 0x4242});
uint32_t frame_row_2 = *frames->id().IndexOf(frame_id_2);
symbol_set_id = storage->symbol_table().row_count();
@@ -1231,7 +1397,7 @@
EXPECT_EQ(event["ph"].asString(), "n");
EXPECT_EQ(event["id"].asString(), "0x1");
EXPECT_EQ(event["ts"].asInt64(), kTimestamp / 1000);
- EXPECT_EQ(event["tid"].asUInt(), kThreadID);
+ EXPECT_EQ(event["tid"].asInt(), static_cast<int>(kThreadID));
EXPECT_EQ(event["cat"].asString(), "disabled_by_default-cpu_profiler");
EXPECT_EQ(event["name"].asString(), "StackCpuSampling");
EXPECT_EQ(event["s"].asString(), "t");
@@ -1241,9 +1407,8 @@
}
TEST_F(ExportJsonTest, ArgumentFilter) {
- UniqueTid utid = context_.storage->AddEmptyThread(0);
- TrackId track =
- context_.track_tracker->GetOrCreateDescriptorTrackForThread(utid);
+ UniqueTid utid = context_.process_tracker->GetOrCreateThread(0);
+ TrackId track = context_.track_tracker->InternThreadTrack(utid);
context_.args_tracker->Flush(); // Flush track args.
StringId cat_id = context_.storage->InternString(base::StringView("cat"));
@@ -1255,18 +1420,16 @@
StringId arg2_id = context_.storage->InternString(base::StringView("arg2"));
StringId val_id = context_.storage->InternString(base::StringView("val"));
- std::array<uint32_t, 3> slice_rows;
+ std::vector<ArgsTracker::BoundInserter> slice_inserters;
for (size_t i = 0; i < name_ids.size(); i++) {
auto slice_id = context_.storage->mutable_slice_table()->Insert(
{0, 0, track.value, cat_id, name_ids[i], 0, 0, 0});
- slice_rows[i] = *context_.storage->slice_table().id().IndexOf(slice_id);
+ slice_inserters.emplace_back(context_.args_tracker->AddArgsTo(slice_id));
}
- for (uint32_t row : slice_rows) {
- context_.args_tracker->AddArg(TableId::kNestableSlices, row, arg1_id,
- arg1_id, Variadic::Integer(5));
- context_.args_tracker->AddArg(TableId::kNestableSlices, row, arg2_id,
- arg2_id, Variadic::String(val_id));
+ for (auto& inserter : slice_inserters) {
+ inserter.AddArg(arg1_id, Variadic::Integer(5))
+ .AddArg(arg2_id, Variadic::String(val_id));
}
context_.args_tracker->Flush();
@@ -1320,16 +1483,16 @@
TraceStorage* storage = context_.storage.get();
- uint32_t row = storage->mutable_raw_events()->AddRawEvent(
- 0, storage->InternString("chrome_event.metadata"), 0, 0);
+ RawId id = storage->mutable_raw_table()->Insert(
+ {0, storage->InternString("chrome_event.metadata"), 0, 0});
StringId name1_id = storage->InternString(base::StringView(kName1));
StringId name2_id = storage->InternString(base::StringView(kName2));
StringId value1_id = storage->InternString(base::StringView(kValue1));
- context_.args_tracker->AddArg(TableId::kRawEvents, row, name1_id, name1_id,
- Variadic::String(value1_id));
- context_.args_tracker->AddArg(TableId::kRawEvents, row, name2_id, name2_id,
- Variadic::Integer(kValue2));
+
+ context_.args_tracker->AddArgsTo(id)
+ .AddArg(name1_id, Variadic::String(value1_id))
+ .AddArg(name2_id, Variadic::Integer(kValue2));
context_.args_tracker->Flush();
auto metadata_filter = [](const char* metadata_name) {
@@ -1350,13 +1513,12 @@
const int64_t kTimestamp1 = 10000000;
const int64_t kTimestamp2 = 20000000;
const int64_t kDuration = 10000;
- const int64_t kThreadID = 100;
+ const uint32_t kThreadID = 100;
const char* kCategory = "cat";
const char* kName = "name";
- UniqueTid utid = context_.storage->AddEmptyThread(kThreadID);
- TrackId track =
- context_.track_tracker->GetOrCreateDescriptorTrackForThread(utid);
+ UniqueTid utid = context_.process_tracker->GetOrCreateThread(kThreadID);
+ TrackId track = context_.track_tracker->InternThreadTrack(utid);
context_.args_tracker->Flush(); // Flush track args.
StringId cat_id = context_.storage->InternString(base::StringView(kCategory));
StringId name_id = context_.storage->InternString(base::StringView(kName));
@@ -1379,13 +1541,13 @@
EXPECT_EQ(result[0]["ph"].asString(), "X");
EXPECT_EQ(result[0]["ts"].asInt64(), kTimestamp1 / 1000);
EXPECT_EQ(result[0]["dur"].asInt64(), kDuration / 1000);
- EXPECT_EQ(result[0]["tid"].asUInt(), kThreadID);
+ EXPECT_EQ(result[0]["tid"].asInt(), static_cast<int>(kThreadID));
EXPECT_EQ(result[0]["cat"].asString(), kCategory);
EXPECT_EQ(result[0]["name"].asString(), kName);
EXPECT_EQ(result[1]["ph"].asString(), "X");
EXPECT_EQ(result[1]["ts"].asInt64(), kTimestamp2 / 1000);
EXPECT_EQ(result[1]["dur"].asInt64(), kDuration / 1000);
- EXPECT_EQ(result[1]["tid"].asUInt(), kThreadID);
+ EXPECT_EQ(result[1]["tid"].asInt(), static_cast<int>(kThreadID));
EXPECT_EQ(result[1]["cat"].asString(), kCategory);
EXPECT_EQ(result[1]["name"].asString(), kName);
}
diff --git a/src/trace_processor/filtered_row_index.cc b/src/trace_processor/filtered_row_index.cc
index 48c5d3c..376c021 100644
--- a/src/trace_processor/filtered_row_index.cc
+++ b/src/trace_processor/filtered_row_index.cc
@@ -16,6 +16,7 @@
#include "src/trace_processor/filtered_row_index.h"
+#include <iterator>
#include <stddef.h>
#include <numeric>
diff --git a/src/trace_processor/forwarding_trace_parser.cc b/src/trace_processor/forwarding_trace_parser.cc
index b28b89b..89798f2 100644
--- a/src/trace_processor/forwarding_trace_parser.cc
+++ b/src/trace_processor/forwarding_trace_parser.cc
@@ -39,9 +39,18 @@
namespace trace_processor {
namespace {
+#if !PERFETTO_BUILDFLAG(PERFETTO_ZLIB)
+const char kNoZlibErr[] =
+ "Cannot open compressed trace. zlib not enabled in the build config";
+#endif
+
+inline bool isspace(unsigned char c) {
+ return ::isspace(c);
+}
+
std::string RemoveWhitespace(const std::string& input) {
std::string str(input);
- str.erase(std::remove_if(str.begin(), str.end(), ::isspace), str.end());
+ str.erase(std::remove_if(str.begin(), str.end(), isspace), str.end());
return str;
}
@@ -115,12 +124,20 @@
}
case kGzipTraceType:
PERFETTO_DLOG("gzip trace detected");
+#if PERFETTO_BUILDFLAG(PERFETTO_ZLIB)
reader_.reset(new GzipTraceParser(context_));
break;
+#else
+ return util::ErrStatus(kNoZlibErr);
+#endif
case kCtraceTraceType:
PERFETTO_DLOG("ctrace trace detected");
+#if PERFETTO_BUILDFLAG(PERFETTO_ZLIB)
reader_.reset(new GzipTraceParser(context_));
break;
+#else
+ return util::ErrStatus(kNoZlibErr);
+#endif
case kUnknownTraceType:
return util::ErrStatus("Unknown trace type provided");
}
diff --git a/test/task_runner_thread_delegates.cc b/src/trace_processor/global_args_tracker.cc
similarity index 75%
rename from test/task_runner_thread_delegates.cc
rename to src/trace_processor/global_args_tracker.cc
index 291482f..9966108 100644
--- a/test/task_runner_thread_delegates.cc
+++ b/src/trace_processor/global_args_tracker.cc
@@ -14,12 +14,13 @@
* limitations under the License.
*/
-#include "test/task_runner_thread_delegates.h"
+#include "src/trace_processor/global_args_tracker.h"
namespace perfetto {
+namespace trace_processor {
-ServiceDelegate::~ServiceDelegate() = default;
-ProbesProducerDelegate::~ProbesProducerDelegate() = default;
-FakeProducerDelegate::~FakeProducerDelegate() = default;
+GlobalArgsTracker::GlobalArgsTracker(TraceProcessorContext* context)
+ : context_(context) {}
+} // namespace trace_processor
} // namespace perfetto
diff --git a/src/trace_processor/global_args_tracker.h b/src/trace_processor/global_args_tracker.h
new file mode 100644
index 0000000..74c5152
--- /dev/null
+++ b/src/trace_processor/global_args_tracker.h
@@ -0,0 +1,141 @@
+/*
+ * Copyright (C) 2019 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.
+ */
+
+#ifndef SRC_TRACE_PROCESSOR_GLOBAL_ARGS_TRACKER_H_
+#define SRC_TRACE_PROCESSOR_GLOBAL_ARGS_TRACKER_H_
+
+#include "src/trace_processor/trace_processor_context.h"
+#include "src/trace_processor/trace_storage.h"
+#include "src/trace_processor/types/variadic.h"
+
+namespace perfetto {
+namespace trace_processor {
+
+// Interns args into the storage from all ArgsTrackers across trace processor.
+// Note: most users will want to use ArgsTracker to push args to the strorage
+// and not this class. This class is really intended for ArgsTracker to use for
+// that purpose.
+class GlobalArgsTracker {
+ public:
+ struct Arg {
+ StringId flat_key = kNullStringId;
+ StringId key = kNullStringId;
+ Variadic value = Variadic::Integer(0);
+
+ Column* column;
+ uint32_t row;
+ };
+
+ struct ArgHasher {
+ uint64_t operator()(const Arg& arg) const noexcept {
+ base::Hash hash;
+ hash.Update(arg.key);
+ // We don't hash arg.flat_key because it's a subsequence of arg.key.
+ switch (arg.value.type) {
+ case Variadic::Type::kInt:
+ hash.Update(arg.value.int_value);
+ break;
+ case Variadic::Type::kUint:
+ hash.Update(arg.value.uint_value);
+ break;
+ case Variadic::Type::kString:
+ hash.Update(arg.value.string_value);
+ break;
+ case Variadic::Type::kReal:
+ hash.Update(arg.value.real_value);
+ break;
+ case Variadic::Type::kPointer:
+ hash.Update(arg.value.pointer_value);
+ break;
+ case Variadic::Type::kBool:
+ hash.Update(arg.value.bool_value);
+ break;
+ case Variadic::Type::kJson:
+ hash.Update(arg.value.json_value);
+ break;
+ }
+ return hash.digest();
+ }
+ };
+
+ GlobalArgsTracker(TraceProcessorContext* context);
+
+ ArgSetId AddArgSet(const std::vector<Arg>& args,
+ uint32_t begin,
+ uint32_t end) {
+ base::Hash hash;
+ for (uint32_t i = begin; i < end; i++) {
+ hash.Update(ArgHasher()(args[i]));
+ }
+
+ auto* arg_table = context_->storage->mutable_arg_table();
+
+ ArgSetHash digest = hash.digest();
+ auto it = arg_row_for_hash_.find(digest);
+ if (it != arg_row_for_hash_.end())
+ return arg_table->arg_set_id()[it->second];
+
+ // The +1 ensures that nothing has an id == kInvalidArgSetId == 0.
+ ArgSetId id = static_cast<uint32_t>(arg_row_for_hash_.size()) + 1;
+ arg_row_for_hash_.emplace(digest, arg_table->row_count());
+ for (uint32_t i = begin; i < end; i++) {
+ const auto& arg = args[i];
+
+ tables::ArgTable::Row row;
+ row.arg_set_id = id;
+ row.flat_key = arg.flat_key;
+ row.key = arg.key;
+ switch (arg.value.type) {
+ case Variadic::Type::kInt:
+ row.int_value = arg.value.int_value;
+ break;
+ case Variadic::Type::kUint:
+ row.int_value = static_cast<int64_t>(arg.value.uint_value);
+ break;
+ case Variadic::Type::kString:
+ row.string_value = arg.value.string_value;
+ break;
+ case Variadic::Type::kReal:
+ row.real_value = arg.value.real_value;
+ break;
+ case Variadic::Type::kPointer:
+ row.int_value = static_cast<int64_t>(arg.value.pointer_value);
+ break;
+ case Variadic::Type::kBool:
+ row.int_value = arg.value.bool_value;
+ break;
+ case Variadic::Type::kJson:
+ row.string_value = arg.value.json_value;
+ break;
+ }
+ row.value_type = context_->storage->GetIdForVariadicType(arg.value.type);
+ arg_table->Insert(row);
+ }
+ return id;
+ }
+
+ private:
+ using ArgSetHash = uint64_t;
+
+ std::unordered_map<ArgSetHash, uint32_t> arg_row_for_hash_;
+
+ TraceProcessorContext* context_;
+};
+
+} // namespace trace_processor
+} // namespace perfetto
+
+#endif // SRC_TRACE_PROCESSOR_GLOBAL_ARGS_TRACKER_H_
diff --git a/src/trace_processor/heap_profile_tracker.cc b/src/trace_processor/heap_profile_tracker.cc
index a666dad..67883fc 100644
--- a/src/trace_processor/heap_profile_tracker.cc
+++ b/src/trace_processor/heap_profile_tracker.cc
@@ -24,6 +24,201 @@
namespace perfetto {
namespace trace_processor {
+namespace {
+struct MergedCallsite {
+ StringId frame_name;
+ StringId mapping_name;
+ base::Optional<uint32_t> parent_idx;
+ bool operator<(const MergedCallsite& o) const {
+ return std::tie(frame_name, mapping_name, parent_idx) <
+ std::tie(o.frame_name, o.mapping_name, o.parent_idx);
+ }
+};
+
+std::vector<MergedCallsite> GetMergedCallsites(TraceStorage* storage,
+ uint32_t callstack_row) {
+ const tables::StackProfileCallsiteTable& callsites_tbl =
+ storage->stack_profile_callsite_table();
+ const tables::StackProfileFrameTable& frames_tbl =
+ storage->stack_profile_frame_table();
+ const tables::SymbolTable& symbols_tbl = storage->symbol_table();
+ const tables::StackProfileMappingTable& mapping_tbl =
+ storage->stack_profile_mapping_table();
+
+ // TODO(fmayer): Clean up types and remove the static_cast.
+ uint32_t frame_idx = *frames_tbl.id().IndexOf(
+ FrameId(static_cast<uint32_t>(callsites_tbl.frame_id()[callstack_row])));
+
+ // TODO(fmayer): Clean up types and remove the static_cast.
+ uint32_t mapping_idx = *mapping_tbl.id().IndexOf(
+ MappingId(static_cast<uint32_t>(frames_tbl.mapping()[frame_idx])));
+ StringId mapping_name = mapping_tbl.name()[mapping_idx];
+
+ base::Optional<uint32_t> symbol_set_id =
+ frames_tbl.symbol_set_id()[frame_idx];
+
+ if (!symbol_set_id) {
+ StringId frame_name = frames_tbl.name()[frame_idx];
+ return {{frame_name, mapping_name, base::nullopt}};
+ }
+
+ std::vector<MergedCallsite> result;
+ // id == symbol_set_id for the bottommost frame.
+ // TODO(lalitm): Encode this optimization in the table and remove this
+ // custom optimization.
+ uint32_t symbol_set_idx = *symbols_tbl.id().IndexOf(SymbolId(*symbol_set_id));
+ for (uint32_t i = symbol_set_idx;
+ i < symbols_tbl.row_count() &&
+ symbols_tbl.symbol_set_id()[i] == *symbol_set_id;
+ ++i) {
+ result.emplace_back(
+ MergedCallsite{symbols_tbl.name()[i], mapping_name, base::nullopt});
+ }
+ return result;
+}
+} // namespace
+
+std::unique_ptr<tables::ExperimentalFlamegraphNodesTable> BuildNativeFlamegraph(
+ TraceStorage* storage,
+ UniquePid upid,
+ int64_t timestamp) {
+ const tables::HeapProfileAllocationTable& allocation_tbl =
+ storage->heap_profile_allocation_table();
+ const tables::StackProfileCallsiteTable& callsites_tbl =
+ storage->stack_profile_callsite_table();
+
+ StringId profile_type = storage->InternString("native");
+
+ std::vector<uint32_t> callsite_to_merged_callsite(callsites_tbl.row_count(),
+ 0);
+ std::map<MergedCallsite, uint32_t> merged_callsites_to_table_idx;
+
+ std::unique_ptr<tables::ExperimentalFlamegraphNodesTable> tbl(
+ new tables::ExperimentalFlamegraphNodesTable(
+ storage->mutable_string_pool(), nullptr));
+
+ // FORWARD PASS:
+ // Aggregate callstacks by frame name / mapping name. Use symbolization data.
+ for (uint32_t i = 0; i < callsites_tbl.row_count(); ++i) {
+ base::Optional<uint32_t> parent_idx;
+ // TODO(fmayer): Clean up types and remove the conditional and static_cast.
+ if (callsites_tbl.parent_id()[i] != -1) {
+ auto parent_id = static_cast<uint32_t>(callsites_tbl.parent_id()[i]);
+ parent_idx = callsites_tbl.id().IndexOf(CallsiteId(parent_id));
+ parent_idx = callsite_to_merged_callsite[*parent_idx];
+ PERFETTO_CHECK(*parent_idx < i);
+ }
+
+ auto callsites = GetMergedCallsites(storage, i);
+ for (MergedCallsite& merged_callsite : callsites) {
+ merged_callsite.parent_idx = parent_idx;
+ auto it = merged_callsites_to_table_idx.find(merged_callsite);
+ if (it == merged_callsites_to_table_idx.end()) {
+ std::tie(it, std::ignore) = merged_callsites_to_table_idx.emplace(
+ merged_callsite, merged_callsites_to_table_idx.size());
+ tables::ExperimentalFlamegraphNodesTable::Row row{};
+ if (parent_idx) {
+ row.depth = tbl->depth()[*parent_idx] + 1;
+ } else {
+ row.depth = 0;
+ }
+ row.ts = timestamp;
+ row.upid = upid;
+ row.profile_type = profile_type;
+ row.name = merged_callsite.frame_name;
+ row.map_name = merged_callsite.mapping_name;
+ if (parent_idx)
+ row.parent_id = tbl->id()[*parent_idx].value;
+
+ parent_idx = *tbl->id().IndexOf(tbl->Insert(std::move(row)));
+ PERFETTO_CHECK(merged_callsites_to_table_idx.size() ==
+ tbl->row_count());
+ }
+ parent_idx = it->second;
+ }
+ PERFETTO_CHECK(parent_idx);
+ callsite_to_merged_callsite[i] = *parent_idx;
+ }
+
+ // PASS OVER ALLOCATIONS:
+ // Aggregate allocations into the newly built tree.
+ auto filtered = allocation_tbl.Filter(
+ {allocation_tbl.ts().eq(timestamp), allocation_tbl.upid().eq(upid)});
+
+ if (filtered.row_count() == 0) {
+ return nullptr;
+ }
+
+ for (auto it = filtered.IterateRows(); it; it.Next()) {
+ int64_t size =
+ it.Get(static_cast<uint32_t>(
+ tables::HeapProfileAllocationTable::ColumnIndex::size))
+ .long_value;
+ int64_t count =
+ it.Get(static_cast<uint32_t>(
+ tables::HeapProfileAllocationTable::ColumnIndex::count))
+ .long_value;
+ int64_t callsite_id =
+ it
+ .Get(static_cast<uint32_t>(
+ tables::HeapProfileAllocationTable::ColumnIndex::callsite_id))
+ .long_value;
+
+ PERFETTO_CHECK((size <= 0 && count <= 0) || (size >= 0 && count >= 0));
+ uint32_t merged_idx =
+ callsite_to_merged_callsite[*callsites_tbl.id().IndexOf(
+ CallsiteId(static_cast<uint32_t>(callsite_id)))];
+ if (count > 0) {
+ // TODO(fmayer): Clean up types and remove the static_cast.
+ tbl->mutable_alloc_size()->Set(merged_idx,
+ tbl->alloc_size()[merged_idx] + size);
+ tbl->mutable_alloc_count()->Set(merged_idx,
+ tbl->alloc_count()[merged_idx] + count);
+ }
+
+ // TODO(fmayer): Clean up types and remove the static_cast.
+ tbl->mutable_size()->Set(merged_idx, tbl->size()[merged_idx] + size);
+ tbl->mutable_count()->Set(merged_idx, tbl->count()[merged_idx] + count);
+ }
+
+ // BACKWARD PASS:
+ // Propagate sizes to parents.
+ for (int64_t i = tbl->row_count() - 1; i >= 0; --i) {
+ uint32_t idx = static_cast<uint32_t>(i);
+
+ tbl->mutable_cumulative_size()->Set(
+ idx, tbl->cumulative_size()[idx] + tbl->size()[idx]);
+ tbl->mutable_cumulative_count()->Set(
+ idx, tbl->cumulative_count()[idx] + tbl->count()[idx]);
+
+ tbl->mutable_cumulative_alloc_size()->Set(
+ idx, tbl->cumulative_alloc_size()[idx] + tbl->alloc_size()[idx]);
+ tbl->mutable_cumulative_alloc_count()->Set(
+ idx, tbl->cumulative_alloc_count()[idx] + tbl->alloc_count()[idx]);
+
+ auto parent = tbl->parent_id()[idx];
+ if (parent) {
+ uint32_t parent_idx = *tbl->id().IndexOf(
+ tables::ExperimentalFlamegraphNodesTable::Id(*parent));
+ tbl->mutable_cumulative_size()->Set(
+ parent_idx,
+ tbl->cumulative_size()[parent_idx] + tbl->cumulative_size()[idx]);
+ tbl->mutable_cumulative_count()->Set(
+ parent_idx,
+ tbl->cumulative_count()[parent_idx] + tbl->cumulative_count()[idx]);
+
+ tbl->mutable_cumulative_alloc_size()->Set(
+ parent_idx, tbl->cumulative_alloc_size()[parent_idx] +
+ tbl->cumulative_alloc_size()[idx]);
+ tbl->mutable_cumulative_alloc_count()->Set(
+ parent_idx, tbl->cumulative_alloc_count()[parent_idx] +
+ tbl->cumulative_alloc_count()[idx]);
+ }
+ }
+
+ return tbl;
+}
+
HeapProfileTracker::HeapProfileTracker(TraceProcessorContext* context)
: context_(context), empty_(context_->storage->InternString({"", 0})) {}
@@ -32,11 +227,27 @@
void HeapProfileTracker::SetProfilePacketIndex(uint32_t seq_id,
uint64_t index) {
SequenceState& sequence_state = sequence_state_[seq_id];
- if (sequence_state.last_profile_packet_index != 0 &&
- sequence_state.last_profile_packet_index + 1 != index) {
+ bool dropped_packet = false;
+ // heapprofd starts counting at index = 0.
+ if (!sequence_state.prev_index && index != 0) {
+ dropped_packet = true;
+ }
+
+ if (sequence_state.prev_index && *sequence_state.prev_index + 1 != index) {
+ dropped_packet = true;
+ }
+
+ if (dropped_packet) {
+ if (sequence_state.prev_index) {
+ PERFETTO_ELOG("Missing packets between %" PRIu64 " and %" PRIu64,
+ *sequence_state.prev_index, index);
+ } else {
+ PERFETTO_ELOG("Invalid first packet index %" PRIu64 " (!= 0)", index);
+ }
+
context_->storage->IncrementStats(stats::heapprofd_missing_packet);
}
- sequence_state.last_profile_packet_index = index;
+ sequence_state.prev_index = index;
}
void HeapProfileTracker::AddAllocation(
@@ -45,29 +256,27 @@
const SourceAllocation& alloc,
const StackProfileTracker::InternLookup* intern_lookup) {
SequenceState& sequence_state = sequence_state_[seq_id];
- auto maybe_callstack_id =
- stack_profile_tracker->FindCallstack(alloc.callstack_id, intern_lookup);
+
+ auto maybe_callstack_id = stack_profile_tracker->FindOrInsertCallstack(
+ alloc.callstack_id, intern_lookup);
if (!maybe_callstack_id)
return;
- int64_t callstack_id = *maybe_callstack_id;
+ CallsiteId callstack_id = *maybe_callstack_id;
UniquePid upid = context_->process_tracker->GetOrCreateProcess(
static_cast<uint32_t>(alloc.pid));
tables::HeapProfileAllocationTable::Row alloc_row{
- alloc.timestamp, upid, callstack_id,
+ alloc.timestamp, upid, callstack_id.value,
static_cast<int64_t>(alloc.alloc_count),
static_cast<int64_t>(alloc.self_allocated)};
tables::HeapProfileAllocationTable::Row free_row{
- alloc.timestamp, upid, callstack_id,
+ alloc.timestamp, upid, callstack_id.value,
-static_cast<int64_t>(alloc.free_count),
-static_cast<int64_t>(alloc.self_freed)};
- tables::HeapProfileAllocationTable::Row alloc_delta = alloc_row;
- tables::HeapProfileAllocationTable::Row free_delta = free_row;
-
auto prev_alloc_it = sequence_state.prev_alloc.find({upid, callstack_id});
if (prev_alloc_it == sequence_state.prev_alloc.end()) {
std::tie(prev_alloc_it, std::ignore) = sequence_state.prev_alloc.emplace(
@@ -76,8 +285,6 @@
}
tables::HeapProfileAllocationTable::Row& prev_alloc = prev_alloc_it->second;
- alloc_delta.count -= prev_alloc.count;
- alloc_delta.size -= prev_alloc.size;
auto prev_free_it = sequence_state.prev_free.find({upid, callstack_id});
if (prev_free_it == sequence_state.prev_free.end()) {
@@ -87,15 +294,59 @@
}
tables::HeapProfileAllocationTable::Row& prev_free = prev_free_it->second;
+
+ std::set<CallsiteId>& callstacks_for_source_callstack_id =
+ sequence_state.seen_callstacks[std::make_pair(upid, alloc.callstack_id)];
+ bool new_callstack;
+ std::tie(std::ignore, new_callstack) =
+ callstacks_for_source_callstack_id.emplace(callstack_id);
+
+ if (new_callstack) {
+ sequence_state.alloc_correction[alloc.callstack_id] = prev_alloc;
+ sequence_state.free_correction[alloc.callstack_id] = prev_free;
+ }
+
+ auto alloc_correction_it =
+ sequence_state.alloc_correction.find(alloc.callstack_id);
+ if (alloc_correction_it != sequence_state.alloc_correction.end()) {
+ const auto& alloc_correction = alloc_correction_it->second;
+ alloc_row.count += alloc_correction.count;
+ alloc_row.size += alloc_correction.size;
+ }
+
+ auto free_correction_it =
+ sequence_state.free_correction.find(alloc.callstack_id);
+ if (free_correction_it != sequence_state.free_correction.end()) {
+ const auto& free_correction = free_correction_it->second;
+ free_row.count += free_correction.count;
+ free_row.size += free_correction.size;
+ }
+
+ tables::HeapProfileAllocationTable::Row alloc_delta = alloc_row;
+ tables::HeapProfileAllocationTable::Row free_delta = free_row;
+
+ alloc_delta.count -= prev_alloc.count;
+ alloc_delta.size -= prev_alloc.size;
+
free_delta.count -= prev_free.count;
free_delta.size -= prev_free.size;
- if (alloc_delta.count)
+ if (alloc_delta.count < 0 || alloc_delta.size < 0 || free_delta.count > 0 ||
+ free_delta.size > 0) {
+ PERFETTO_DLOG("Non-monotonous allocation.");
+ context_->storage->IncrementIndexedStats(stats::heapprofd_malformed_packet,
+ static_cast<int>(upid));
+ return;
+ }
+
+ if (alloc_delta.count) {
context_->storage->mutable_heap_profile_allocation_table()->Insert(
alloc_delta);
- if (free_delta.count)
+ }
+ if (free_delta.count) {
context_->storage->mutable_heap_profile_allocation_table()->Insert(
free_delta);
+ }
prev_alloc = alloc_row;
prev_free = free_row;
diff --git a/src/trace_processor/heap_profile_tracker.h b/src/trace_processor/heap_profile_tracker.h
index 1d121aa..fe40a84 100644
--- a/src/trace_processor/heap_profile_tracker.h
+++ b/src/trace_processor/heap_profile_tracker.h
@@ -18,6 +18,7 @@
#define SRC_TRACE_PROCESSOR_HEAP_PROFILE_TRACKER_H_
#include <deque>
+#include <set>
#include <unordered_map>
#include "perfetto/ext/base/optional.h"
@@ -30,6 +31,11 @@
namespace perfetto {
namespace trace_processor {
+std::unique_ptr<tables::ExperimentalFlamegraphNodesTable> BuildNativeFlamegraph(
+ TraceStorage* storage,
+ UniquePid upid,
+ int64_t timestamp);
+
class TraceProcessorContext;
class HeapProfileTracker {
@@ -77,14 +83,34 @@
struct SequenceState {
std::vector<SourceAllocation> pending_allocs;
- std::unordered_map<std::pair<UniquePid, int64_t>,
+ std::unordered_map<std::pair<UniquePid, CallsiteId>,
tables::HeapProfileAllocationTable::Row>
prev_alloc;
- std::unordered_map<std::pair<UniquePid, int64_t>,
+ std::unordered_map<std::pair<UniquePid, CallsiteId>,
tables::HeapProfileAllocationTable::Row>
prev_free;
- uint64_t last_profile_packet_index = 0;
+ // For continuous dumps, we only store the delta in the data-base. To do
+ // this, we subtract the previous dump's value. Sometimes, we should not
+ // do that subtraction, because heapprofd garbage collects stacks that
+ // have no unfreed allocations. If the application then allocations again
+ // at that stack, it gets recreated and initialized to zero.
+ //
+ // To correct for this, we add the previous' stacks value to the current
+ // one, and then handle it as normal. If it is the first time we see a
+ // SourceCallstackId for a CallsiteId, we put the previous value into
+ // the correction maps below.
+ std::map<std::pair<UniquePid, StackProfileTracker::SourceCallstackId>,
+ std::set<CallsiteId>>
+ seen_callstacks;
+ std::map<StackProfileTracker::SourceCallstackId,
+ tables::HeapProfileAllocationTable::Row>
+ alloc_correction;
+ std::map<StackProfileTracker::SourceCallstackId,
+ tables::HeapProfileAllocationTable::Row>
+ free_correction;
+
+ base::Optional<uint64_t> prev_index;
};
std::map<uint32_t, SequenceState> sequence_state_;
TraceProcessorContext* const context_;
diff --git a/src/trace_processor/heap_profile_tracker_unittest.cc b/src/trace_processor/heap_profile_tracker_unittest.cc
index 91c3f93..d9d3e1d 100644
--- a/src/trace_processor/heap_profile_tracker_unittest.cc
+++ b/src/trace_processor/heap_profile_tracker_unittest.cc
@@ -181,11 +181,11 @@
int64_t FindCallstack(const TraceStorage& storage,
int64_t depth,
int64_t parent,
- int64_t frame_id) {
+ FrameId frame_id) {
const auto& callsites = storage.stack_profile_callsite_table();
for (uint32_t i = 0; i < callsites.row_count(); ++i) {
if (callsites.depth()[i] == depth && callsites.parent_id()[i] == parent &&
- callsites.frame_id()[i] == frame_id) {
+ callsites.frame_id()[i] == frame_id.value) {
return static_cast<int64_t>(i);
}
}
@@ -327,7 +327,6 @@
const StackProfileTracker::SourceCallstack& callstack = callstacks[i];
for (size_t depth = 0; depth < callstack.size(); ++depth) {
auto frame_id = spt->GetDatabaseFrameIdForTesting(callstack[depth]);
- ASSERT_NE(frame_id, -1);
int64_t self = FindCallstack(
*context.storage, static_cast<int64_t>(depth), parent, frame_id);
ASSERT_NE(self, -1);
diff --git a/src/trace_processor/importers/ftrace/ftrace_parser.cc b/src/trace_processor/importers/ftrace/ftrace_parser.cc
index d61c63c..ac3d374 100644
--- a/src/trace_processor/importers/ftrace/ftrace_parser.cc
+++ b/src/trace_processor/importers/ftrace/ftrace_parser.cc
@@ -74,7 +74,8 @@
signal_deliver_id_(context->storage->InternString("signal_deliver")),
oom_score_adj_id_(context->storage->InternString("oom_score_adj")),
lmk_id_(context->storage->InternString("mem.lmk")),
- comm_name_id_(context->storage->InternString("comm")) {
+ comm_name_id_(context->storage->InternString("comm")),
+ signal_name_id_(context_->storage->InternString("signal.sig")) {
// Build the lookup table for the strings inside ftrace events (e.g. the
// name of ftrace event fields and the names of their args).
for (size_t i = 0; i < GetDescriptorsSize(); i++) {
@@ -357,25 +358,22 @@
protos::pbzero::GenericFtraceEvent::Decoder evt(blob.data, blob.size);
StringId event_id = context_->storage->InternString(evt.event_name());
UniqueTid utid = context_->process_tracker->GetOrCreateThread(tid);
- uint32_t row = context_->storage->mutable_raw_events()->AddRawEvent(
- ts, event_id, cpu, utid);
+ RawId id =
+ context_->storage->mutable_raw_table()->Insert({ts, event_id, cpu, utid});
+ auto inserter = context_->args_tracker->AddArgsTo(id);
for (auto it = evt.field(); it; ++it) {
protos::pbzero::GenericFtraceEvent::Field::Decoder fld(*it);
auto field_name_id = context_->storage->InternString(fld.name());
if (fld.has_int_value()) {
- context_->args_tracker->AddArg(TableId::kRawEvents, row, field_name_id,
- field_name_id,
- Variadic::Integer(fld.int_value()));
+ inserter.AddArg(field_name_id, Variadic::Integer(fld.int_value()));
} else if (fld.has_uint_value()) {
- context_->args_tracker->AddArg(
- TableId::kRawEvents, row, field_name_id, field_name_id,
+ inserter.AddArg(
+ field_name_id,
Variadic::Integer(static_cast<int64_t>(fld.uint_value())));
} else if (fld.has_str_value()) {
StringId str_value = context_->storage->InternString(fld.str_value());
- context_->args_tracker->AddArg(TableId::kRawEvents, row, field_name_id,
- field_name_id,
- Variadic::String(str_value));
+ inserter.AddArg(field_name_id, Variadic::String(str_value));
}
}
}
@@ -385,6 +383,9 @@
uint32_t cpu,
uint32_t tid,
ConstBytes blob) {
+ if (PERFETTO_UNLIKELY(!context_->config.ingest_ftrace_in_raw_table))
+ return;
+
ProtoDecoder decoder(blob.data, blob.size);
if (ftrace_id >= GetDescriptorsSize()) {
PERFETTO_DLOG("Event with id: %d does not exist and cannot be parsed.",
@@ -395,8 +396,10 @@
MessageDescriptor* m = GetMessageDescriptorForId(ftrace_id);
const auto& message_strings = ftrace_message_strings_[ftrace_id];
UniqueTid utid = context_->process_tracker->GetOrCreateThread(tid);
- uint32_t raw_event_row = context_->storage->mutable_raw_events()->AddRawEvent(
- ts, message_strings.message_name_id, cpu, utid);
+ RawId id = context_->storage->mutable_raw_table()->Insert(
+ {ts, message_strings.message_name_id, cpu, utid});
+ auto inserter = context_->args_tracker->AddArgsTo(id);
+
for (auto fld = decoder.ReadField(); fld.valid(); fld = decoder.ReadField()) {
if (PERFETTO_UNLIKELY(fld.id() >= kMaxFtraceEventFields)) {
PERFETTO_DLOG(
@@ -415,9 +418,7 @@
case ProtoSchemaType::kSint64:
case ProtoSchemaType::kBool:
case ProtoSchemaType::kEnum: {
- context_->args_tracker->AddArg(TableId::kRawEvents, raw_event_row,
- name_id, name_id,
- Variadic::Integer(fld.as_int64()));
+ inserter.AddArg(name_id, Variadic::Integer(fld.as_int64()));
break;
}
case ProtoSchemaType::kUint32:
@@ -427,29 +428,22 @@
// Note that SQLite functions will still treat unsigned values
// as a signed 64 bit integers (but the translation back to ftrace
// refers to this storage directly).
- context_->args_tracker->AddArg(
- TableId::kRawEvents, raw_event_row, name_id, name_id,
- Variadic::UnsignedInteger(fld.as_uint64()));
+ inserter.AddArg(name_id, Variadic::UnsignedInteger(fld.as_uint64()));
break;
}
case ProtoSchemaType::kString:
case ProtoSchemaType::kBytes: {
StringId value = context_->storage->InternString(fld.as_string());
- context_->args_tracker->AddArg(TableId::kRawEvents, raw_event_row,
- name_id, name_id,
- Variadic::String(value));
+ inserter.AddArg(name_id, Variadic::String(value));
break;
}
case ProtoSchemaType::kDouble: {
- context_->args_tracker->AddArg(TableId::kRawEvents, raw_event_row,
- name_id, name_id,
- Variadic::Real(fld.as_double()));
+ inserter.AddArg(name_id, Variadic::Real(fld.as_double()));
break;
}
case ProtoSchemaType::kFloat: {
- context_->args_tracker->AddArg(
- TableId::kRawEvents, raw_event_row, name_id, name_id,
- Variadic::Real(static_cast<double>(fld.as_float())));
+ inserter.AddArg(name_id,
+ Variadic::Real(static_cast<double>(fld.as_float())));
break;
}
case ProtoSchemaType::kUnknown:
@@ -614,11 +608,9 @@
static_cast<uint32_t>(sig.pid()));
InstantId id = context_->event_tracker->PushInstant(ts, signal_generate_id_,
utid, RefType::kRefUtid);
- uint32_t row = *context_->storage->instant_table().id().IndexOf(id);
- StringId key = context_->storage->InternString("signal.sig");
- context_->args_tracker->AddArg(TableId::kInstants, row, key, key,
- Variadic::Integer(sig.sig()));
+ context_->args_tracker->AddArgsTo(id).AddArg(signal_name_id_,
+ Variadic::Integer(sig.sig()));
}
void FtraceParser::ParseSignalDeliver(int64_t ts,
@@ -628,11 +620,9 @@
UniqueTid utid = context_->process_tracker->GetOrCreateThread(pid);
InstantId id = context_->event_tracker->PushInstant(ts, signal_deliver_id_,
utid, RefType::kRefUtid);
- uint32_t row = *context_->storage->instant_table().id().IndexOf(id);
- StringId key = context_->storage->InternString("signal.sig");
- context_->args_tracker->AddArg(TableId::kInstants, row, key, key,
- Variadic::Integer(sig.sig()));
+ context_->args_tracker->AddArgsTo(id).AddArg(signal_name_id_,
+ Variadic::Integer(sig.sig()));
}
void FtraceParser::ParseLowmemoryKill(int64_t ts, ConstBytes blob) {
@@ -651,13 +641,12 @@
InstantId id = context_->event_tracker->PushInstant(
ts, lmk_id_, opt_utid.value(), RefType::kRefUtid, true);
- uint32_t row = *context_->storage->instant_table().id().IndexOf(id);
// Store the comm as an arg.
auto comm_id = context_->storage->InternString(
lmk.has_comm() ? lmk.comm() : base::StringView());
- context_->args_tracker->AddArg(TableId::kInstants, row, comm_name_id_,
- comm_name_id_, Variadic::String(comm_id));
+ context_->args_tracker->AddArgsTo(id).AddArg(comm_name_id_,
+ Variadic::String(comm_id));
}
void FtraceParser::ParseOOMScoreAdjUpdate(int64_t ts, ConstBytes blob) {
diff --git a/src/trace_processor/importers/ftrace/ftrace_parser.h b/src/trace_processor/importers/ftrace/ftrace_parser.h
index bd8ff81..10eacfe 100644
--- a/src/trace_processor/importers/ftrace/ftrace_parser.h
+++ b/src/trace_processor/importers/ftrace/ftrace_parser.h
@@ -94,10 +94,11 @@
const StringId oom_score_adj_id_;
const StringId lmk_id_;
const StringId comm_name_id_;
+ const StringId signal_name_id_;
struct FtraceMessageStrings {
// The string id of name of the event field (e.g. sched_switch's id).
- StringId message_name_id = 0;
+ StringId message_name_id = kNullStringId;
std::array<StringId, kMaxFtraceEventFields> field_name_ids;
};
std::vector<FtraceMessageStrings> ftrace_message_strings_;
@@ -107,9 +108,9 @@
MmEventCounterNames(StringId _count, StringId _max_lat, StringId _avg_lat)
: count(_count), max_lat(_max_lat), avg_lat(_avg_lat) {}
- StringId count = 0;
- StringId max_lat = 0;
- StringId avg_lat = 0;
+ StringId count = kNullStringId;
+ StringId max_lat = kNullStringId;
+ StringId avg_lat = kNullStringId;
};
// Keep kMmEventCounterSize equal to mm_event_type::MM_TYPE_NUM in the kernel.
diff --git a/src/trace_processor/importers/ftrace/rss_stat_tracker.cc b/src/trace_processor/importers/ftrace/rss_stat_tracker.cc
index db444a7..f536a02 100644
--- a/src/trace_processor/importers/ftrace/rss_stat_tracker.cc
+++ b/src/trace_processor/importers/ftrace/rss_stat_tracker.cc
@@ -69,24 +69,34 @@
base::Optional<UniqueTid> RssStatTracker::FindUtidForMmId(int64_t mm_id,
bool is_curr,
uint32_t pid) {
- auto it = mm_id_to_utid_.find(mm_id);
- if (!is_curr) {
- return it == mm_id_to_utid_.end() ? base::nullopt
- : base::make_optional(it->second);
+ // If curr is true, we can just overwrite the state in the map and return
+ // the utid correspodning to |pid|.
+ if (is_curr) {
+ UniqueTid utid = context_->process_tracker->GetOrCreateThread(pid);
+ mm_id_to_utid_[mm_id] = utid;
+ return utid;
}
+ // If curr is false, try and lookup the utid we previously saw for this
+ // mm id.
+ auto it = mm_id_to_utid_.find(mm_id);
+ if (it == mm_id_to_utid_.end())
+ return base::nullopt;
+
+ // If the utid in the map is the same as our current utid but curr is false,
+ // that means we are in the middle of a process changing mm structs (i.e. in
+ // the middle of a vfork + exec). Therefore, we should discard the association
+ // of this vm struct with this thread.
UniqueTid utid = context_->process_tracker->GetOrCreateThread(pid);
- if (it != mm_id_to_utid_.end() && it->second != utid) {
- // Since both of these structs have the same mm hash and both say that
- // the mm hash is for the current project, we can assume they belong to
- // the same process so we can associate them together.
- // TODO(lalitm): investigate if it's possible for mm_id to be reused
- // between different processes if we have pid reuse and get unlucky. If
- // so, we'll need to do some more careful tracking here.
- context_->process_tracker->AssociateThreads(it->second, utid);
+ if (it->second == utid) {
+ mm_id_to_utid_.erase(it);
+ return base::nullopt;
}
- mm_id_to_utid_[mm_id] = utid;
- return utid;
+
+ // This case happens when a process is changing the VM of another process and
+ // we know that the utid corresponding to the target process. Just return that
+ // utid.
+ return it->second;
}
} // namespace trace_processor
diff --git a/src/trace_processor/importers/ftrace/sched_event_tracker.cc b/src/trace_processor/importers/ftrace/sched_event_tracker.cc
index df5f575..62fcec4 100644
--- a/src/trace_processor/importers/ftrace/sched_event_tracker.cc
+++ b/src/trace_processor/importers/ftrace/sched_event_tracker.cc
@@ -26,7 +26,7 @@
#include "src/trace_processor/process_tracker.h"
#include "src/trace_processor/stats.h"
#include "src/trace_processor/trace_processor_context.h"
-#include "src/trace_processor/variadic.h"
+#include "src/trace_processor/types/variadic.h"
#include "protos/perfetto/trace/ftrace/ftrace_event.pbzero.h"
#include "protos/perfetto/trace/ftrace/sched.pbzero.h"
@@ -81,7 +81,7 @@
PERFETTO_DCHECK(cpu < kMaxCpus);
StringId next_comm_id = context_->storage->InternString(next_comm);
- auto next_utid =
+ UniqueTid next_utid =
context_->process_tracker->UpdateThreadName(next_pid, next_comm_id);
// First use this data to close the previous slice.
@@ -132,7 +132,7 @@
context_->event_tracker->UpdateMaxTimestamp(ts);
PERFETTO_DCHECK(cpu < kMaxCpus);
- auto next_utid =
+ UniqueTid next_utid =
context_->process_tracker->UpdateThreadName(next_pid, next_comm_id);
auto* pending_sched = &pending_sched_per_cpu_[cpu];
@@ -167,8 +167,7 @@
// Do a fresh task name lookup in case it was updated by a task_rename while
// scheduled.
- const auto& prev_thread = context_->storage->GetThread(prev_utid);
- StringId prev_comm_id = prev_thread.name_id;
+ StringId prev_comm_id = context_->storage->thread_table().name()[prev_utid];
auto new_slice_idx = AddRawEventAndStartSlice(
cpu, ts, prev_utid, prev_pid, prev_comm_id, prev_prio, prev_state,
@@ -193,29 +192,30 @@
uint32_t next_pid,
StringId next_comm_id,
int32_t next_prio) {
- // Push the raw event - this is done as the raw ftrace event codepath does
- // not insert sched_switch.
- uint32_t row = context_->storage->mutable_raw_events()->AddRawEvent(
- ts, sched_switch_id_, cpu, prev_utid);
+ if (PERFETTO_LIKELY(context_->config.ingest_ftrace_in_raw_table)) {
+ // Push the raw event - this is done as the raw ftrace event codepath does
+ // not insert sched_switch.
+ RawId id = context_->storage->mutable_raw_table()->Insert(
+ {ts, sched_switch_id_, cpu, prev_utid});
- // Note: this ordering is important. The events should be pushed in the same
- // order as the order of fields in the proto; this is used by the raw table to
- // index these events using the field ids.
- using SS = protos::pbzero::SchedSwitchFtraceEvent;
+ // Note: this ordering is important. The events should be pushed in the same
+ // order as the order of fields in the proto; this is used by the raw table
+ // to index these events using the field ids.
+ using SS = protos::pbzero::SchedSwitchFtraceEvent;
- ArgsTracker::BoundInserter inserter(context_->args_tracker.get(),
- TableId::kRawEvents, row);
- auto add_raw_arg = [this, &inserter](int field_num, Variadic var) {
- StringId key = sched_switch_field_ids_[static_cast<size_t>(field_num)];
- inserter.AddArg(key, var);
- };
- add_raw_arg(SS::kPrevCommFieldNumber, Variadic::String(prev_comm_id));
- add_raw_arg(SS::kPrevPidFieldNumber, Variadic::Integer(prev_pid));
- add_raw_arg(SS::kPrevPrioFieldNumber, Variadic::Integer(prev_prio));
- add_raw_arg(SS::kPrevStateFieldNumber, Variadic::Integer(prev_state));
- add_raw_arg(SS::kNextCommFieldNumber, Variadic::String(next_comm_id));
- add_raw_arg(SS::kNextPidFieldNumber, Variadic::Integer(next_pid));
- add_raw_arg(SS::kNextPrioFieldNumber, Variadic::Integer(next_prio));
+ auto inserter = context_->args_tracker->AddArgsTo(id);
+ auto add_raw_arg = [this, &inserter](int field_num, Variadic var) {
+ StringId key = sched_switch_field_ids_[static_cast<size_t>(field_num)];
+ inserter.AddArg(key, var);
+ };
+ add_raw_arg(SS::kPrevCommFieldNumber, Variadic::String(prev_comm_id));
+ add_raw_arg(SS::kPrevPidFieldNumber, Variadic::Integer(prev_pid));
+ add_raw_arg(SS::kPrevPrioFieldNumber, Variadic::Integer(prev_prio));
+ add_raw_arg(SS::kPrevStateFieldNumber, Variadic::Integer(prev_state));
+ add_raw_arg(SS::kNextCommFieldNumber, Variadic::String(next_comm_id));
+ add_raw_arg(SS::kNextPidFieldNumber, Variadic::Integer(next_pid));
+ add_raw_arg(SS::kNextPrioFieldNumber, Variadic::Integer(next_prio));
+ }
// Open a new scheduling slice, corresponding to the task that was
// just switched to.
@@ -273,23 +273,27 @@
}
auto curr_utid = pending_sched->last_utid;
- // Add an entry to the raw table.
- uint32_t row = context_->storage->mutable_raw_events()->AddRawEvent(
- ts, sched_waking_id_, cpu, curr_utid);
+ if (PERFETTO_LIKELY(context_->config.ingest_ftrace_in_raw_table)) {
+ // Add an entry to the raw table.
+ RawId id = context_->storage->mutable_raw_table()->Insert(
+ {ts, sched_waking_id_, cpu, curr_utid});
- // "success" is hardcoded as always 1 by the kernel, with a TODO to remove it.
- static constexpr int32_t kHardcodedSuccess = 1;
+ // "success" is hardcoded as always 1 by the kernel, with a TODO to remove
+ // it.
+ static constexpr int32_t kHardcodedSuccess = 1;
- using SW = protos::pbzero::SchedWakingFtraceEvent;
- auto add_raw_arg = [this, row](int field_num, Variadic var) {
- StringId key = sched_waking_field_ids_[static_cast<size_t>(field_num)];
- context_->args_tracker->AddArg(TableId::kRawEvents, row, key, key, var);
- };
- add_raw_arg(SW::kCommFieldNumber, Variadic::String(comm_id));
- add_raw_arg(SW::kPidFieldNumber, Variadic::Integer(wakee_pid));
- add_raw_arg(SW::kPrioFieldNumber, Variadic::Integer(prio));
- add_raw_arg(SW::kSuccessFieldNumber, Variadic::Integer(kHardcodedSuccess));
- add_raw_arg(SW::kTargetCpuFieldNumber, Variadic::Integer(target_cpu));
+ using SW = protos::pbzero::SchedWakingFtraceEvent;
+ auto inserter = context_->args_tracker->AddArgsTo(id);
+ auto add_raw_arg = [this, &inserter](int field_num, Variadic var) {
+ StringId key = sched_waking_field_ids_[static_cast<size_t>(field_num)];
+ inserter.AddArg(key, var);
+ };
+ add_raw_arg(SW::kCommFieldNumber, Variadic::String(comm_id));
+ add_raw_arg(SW::kPidFieldNumber, Variadic::Integer(wakee_pid));
+ add_raw_arg(SW::kPrioFieldNumber, Variadic::Integer(prio));
+ add_raw_arg(SW::kSuccessFieldNumber, Variadic::Integer(kHardcodedSuccess));
+ add_raw_arg(SW::kTargetCpuFieldNumber, Variadic::Integer(target_cpu));
+ }
// Add a waking entry to the instants.
auto wakee_utid = context_->process_tracker->GetOrCreateThread(wakee_pid);
diff --git a/src/trace_processor/importers/fuchsia/fuchsia_trace_parser.cc b/src/trace_processor/importers/fuchsia/fuchsia_trace_parser.cc
index 660c680..46f0815 100644
--- a/src/trace_processor/importers/fuchsia/fuchsia_trace_parser.cc
+++ b/src/trace_processor/importers/fuchsia/fuchsia_trace_parser.cc
@@ -253,11 +253,10 @@
static_cast<uint32_t>(tinfo.pid));
InstantId id = context_->event_tracker->PushInstant(
ts, name, utid, RefType::kRefUtid);
- uint32_t row = *context_->storage->instant_table().id().IndexOf(id);
+ auto inserter = context_->args_tracker->AddArgsTo(id);
for (const Arg& arg : args) {
- context_->args_tracker->AddArg(
- TableId::kInstants, row, arg.name, arg.name,
- arg.value.ToStorageVariadic(context_->storage.get()));
+ inserter.AddArg(
+ arg.name, arg.value.ToStorageVariadic(context_->storage.get()));
}
context_->args_tracker->Flush();
break;
@@ -379,10 +378,10 @@
name, correlation_id);
InstantId id = context_->event_tracker->PushInstant(
ts, name, track_id.value, RefType::kRefTrack);
- uint32_t row = *context_->storage->instant_table().id().IndexOf(id);
+ auto inserter = context_->args_tracker->AddArgsTo(id);
for (const Arg& arg : args) {
- context_->args_tracker->AddArg(
- TableId::kInstants, row, arg.name, arg.name,
+ inserter.AddArg(
+ arg.name, arg.name,
arg.value.ToStorageVariadic(context_->storage.get()));
}
context_->args_tracker->Flush();
diff --git a/src/trace_processor/importers/fuchsia/fuchsia_trace_tokenizer.cc b/src/trace_processor/importers/fuchsia/fuchsia_trace_tokenizer.cc
index ac6b064..badef38 100644
--- a/src/trace_processor/importers/fuchsia/fuchsia_trace_tokenizer.cc
+++ b/src/trace_processor/importers/fuchsia/fuchsia_trace_tokenizer.cc
@@ -443,7 +443,7 @@
UniqueTid utid = procs->UpdateThread(static_cast<uint32_t>(obj_id),
static_cast<uint32_t>(pid));
- storage->GetMutableThread(utid)->name_id = name;
+ storage->mutable_thread_table()->mutable_name()->Set(utid, name);
break;
}
default: {
diff --git a/src/trace_processor/importers/proto/android_probes_parser.cc b/src/trace_processor/importers/proto/android_probes_parser.cc
index 178be15..1952fef 100644
--- a/src/trace_processor/importers/proto/android_probes_parser.cc
+++ b/src/trace_processor/importers/proto/android_probes_parser.cc
@@ -229,11 +229,9 @@
// arg_set_id when the arg tracker is flushed.
auto id = context_->metadata_tracker->AppendMetadata(
metadata::android_packages_list, Variadic::Integer(0));
- uint32_t row = *context_->storage->metadata_table().id().IndexOf(id);
- auto add_arg = [this, row](base::StringView name, Variadic value) {
+ auto add_arg = [this, id](base::StringView name, Variadic value) {
StringId key_id = context_->storage->InternString(name);
- context_->args_tracker->AddArg(TableId::kMetadataTable, row, key_id,
- key_id, value);
+ context_->args_tracker->AddArgsTo(id).AddArg(key_id, value);
};
protos::pbzero::PackagesList_PackageInfo::Decoder pkg(*it);
add_arg("name",
diff --git a/src/trace_processor/importers/proto/args_table_utils_unittest.cc b/src/trace_processor/importers/proto/args_table_utils_unittest.cc
index 4cc03e9..df023b4 100644
--- a/src/trace_processor/importers/proto/args_table_utils_unittest.cc
+++ b/src/trace_processor/importers/proto/args_table_utils_unittest.cc
@@ -44,24 +44,22 @@
ArgsTableUtilsTest() {
context_.storage.reset(new TraceStorage);
storage_ = context_.storage.get();
+ context_.global_args_tracker.reset(new GlobalArgsTracker(&context_));
context_.args_tracker.reset(new ArgsTracker(&context_));
sequence_state_.reset(new PacketSequenceState(&context_));
}
bool HasArg(ArgSetId set_id, const base::StringView& key, Variadic value) {
- const auto& args = storage_->args();
+ const auto& args = storage_->arg_table();
auto key_id = storage_->string_pool().GetId(key);
EXPECT_TRUE(key_id);
- auto rows =
- std::equal_range(args.set_ids().begin(), args.set_ids().end(), set_id);
+
+ RowMap rm = args.FilterToRowMap({args.arg_set_id().eq(set_id)});
bool found = false;
- for (; rows.first != rows.second; rows.first++) {
- size_t index = static_cast<size_t>(
- std::distance(args.set_ids().begin(), rows.first));
- if (args.keys()[index] == key_id) {
- EXPECT_EQ(args.flat_keys()[index], key_id);
- if (args.flat_keys()[index] == key_id &&
- args.arg_values()[index] == value) {
+ for (auto it = rm.IterateRows(); it; it.Next()) {
+ if (args.key()[it.row()] == key_id) {
+ EXPECT_EQ(args.flat_key()[it.row()], key_id);
+ if (storage_->GetArgValue(it.row()) == value) {
found = true;
break;
}
@@ -132,8 +130,7 @@
ASSERT_TRUE(status.ok()) << "Failed to parse kTestMessagesDescriptor: "
<< status.message();
- ArgsTracker::BoundInserter inserter(context_.args_tracker.get(),
- TableId::kTrack, 0);
+ auto inserter = context_.args_tracker->AddArgsTo(TrackId(0));
status = helper.InternProtoIntoArgsTable(
protozero::ConstBytes{binary_proto.data(), binary_proto.size()},
".protozero.test.protos.EveryField", &inserter);
@@ -205,8 +202,7 @@
ASSERT_TRUE(status.ok()) << "Failed to parse kTestMessagesDescriptor: "
<< status.message();
- ArgsTracker::BoundInserter inserter(context_.args_tracker.get(),
- TableId::kTrack, 0);
+ auto inserter = context_.args_tracker->AddArgsTo(TrackId(0));
status = helper.InternProtoIntoArgsTable(
protozero::ConstBytes{binary_proto.data(), binary_proto.size()},
".protozero.test.protos.NestedA", &inserter);
@@ -234,8 +230,7 @@
ASSERT_TRUE(status.ok()) << "Failed to parse kTestMessagesDescriptor: "
<< status.message();
- ArgsTracker::BoundInserter inserter(context_.args_tracker.get(),
- TableId::kTrack, 0);
+ auto inserter = context_.args_tracker->AddArgsTo(TrackId(0));
status = helper.InternProtoIntoArgsTable(
protozero::ConstBytes{binary_proto.data(), binary_proto.size()},
".protozero.test.protos.CamelCaseFields", &inserter);
@@ -278,8 +273,7 @@
return true;
});
- ArgsTracker::BoundInserter inserter(context_.args_tracker.get(),
- TableId::kTrack, 0);
+ auto inserter = context_.args_tracker->AddArgsTo(TrackId(0));
status = helper.InternProtoIntoArgsTable(
protozero::ConstBytes{binary_proto.data(), binary_proto.size()},
".protozero.test.protos.NestedA", &inserter);
@@ -319,8 +313,7 @@
return false;
});
- ArgsTracker::BoundInserter inserter(context_.args_tracker.get(),
- TableId::kTrack, 0);
+ auto inserter = context_.args_tracker->AddArgsTo(TrackId(0));
status = helper.InternProtoIntoArgsTable(
protozero::ConstBytes{binary_proto.data(), binary_proto.size()},
".protozero.test.protos.NestedA", &inserter);
@@ -385,8 +378,7 @@
ASSERT_TRUE(status.ok()) << "Failed to parse kTestMessagesDescriptor: "
<< status.message();
- ArgsTracker::BoundInserter inserter(context_.args_tracker.get(),
- TableId::kTrack, 0);
+ auto inserter = context_.args_tracker->AddArgsTo(TrackId(0));
status = helper.InternProtoIntoArgsTable(
protozero::ConstBytes{binary_proto.data(), binary_proto.size()},
".protozero.test.protos.NestedA", &inserter);
diff --git a/src/trace_processor/importers/proto/chrome_compositor_scheduler_state.descriptor.h b/src/trace_processor/importers/proto/chrome_compositor_scheduler_state.descriptor.h
index f13eaa1..adc3f2d 100644
--- a/src/trace_processor/importers/proto/chrome_compositor_scheduler_state.descriptor.h
+++ b/src/trace_processor/importers/proto/chrome_compositor_scheduler_state.descriptor.h
@@ -25,17 +25,17 @@
// This file was autogenerated by tools/gen_binary_descriptors. Do not edit.
// SHA1(tools/gen_binary_descriptors)
-// f242f1ac484bbe7ba4c45e77b56ab588f8015196
+// d6628b15181dba5287e35b56b966b39ea93d42b1
// SHA1(protos/perfetto/trace/track_event/chrome_compositor_scheduler_state.proto)
-// 360017d4658dfd81fbf16af8cc2abb994958af05
+// b7dab60e553ebda32178373fa290f99afb94e55a
// This is the proto ChromeCompositorSchedulerState encoded as a ProtoFileDescriptor to allow
// for reflection without libprotobuf full/non-lite protos.
namespace perfetto {
-constexpr std::array<uint8_t, 10133> kChromeCompositorSchedulerStateDescriptor{
- {0x0a, 0xd6, 0x01, 0x0a, 0x37, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2f,
+constexpr std::array<uint8_t, 10125> kChromeCompositorSchedulerStateDescriptor{
+ {0x0a, 0xd2, 0x01, 0x0a, 0x37, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2f,
0x70, 0x65, 0x72, 0x66, 0x65, 0x74, 0x74, 0x6f, 0x2f, 0x74, 0x72, 0x61,
0x63, 0x65, 0x2f, 0x74, 0x72, 0x61, 0x63, 0x6b, 0x5f, 0x65, 0x76, 0x65,
0x6e, 0x74, 0x2f, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x5f, 0x6c, 0x6f,
@@ -52,834 +52,833 @@
0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x4e, 0x61, 0x6d, 0x65,
0x12, 0x1f, 0x0a, 0x0b, 0x6c, 0x69, 0x6e, 0x65, 0x5f, 0x6e, 0x75, 0x6d,
0x62, 0x65, 0x72, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x0a, 0x6c,
- 0x69, 0x6e, 0x65, 0x4e, 0x75, 0x6d, 0x62, 0x65, 0x72, 0x42, 0x02, 0x48,
- 0x03, 0x0a, 0xb9, 0x4d, 0x0a, 0x49, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73,
- 0x2f, 0x70, 0x65, 0x72, 0x66, 0x65, 0x74, 0x74, 0x6f, 0x2f, 0x74, 0x72,
- 0x61, 0x63, 0x65, 0x2f, 0x74, 0x72, 0x61, 0x63, 0x6b, 0x5f, 0x65, 0x76,
- 0x65, 0x6e, 0x74, 0x2f, 0x63, 0x68, 0x72, 0x6f, 0x6d, 0x65, 0x5f, 0x63,
- 0x6f, 0x6d, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x6f, 0x72, 0x5f, 0x73, 0x63,
- 0x68, 0x65, 0x64, 0x75, 0x6c, 0x65, 0x72, 0x5f, 0x73, 0x74, 0x61, 0x74,
- 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x0f, 0x70, 0x65, 0x72,
- 0x66, 0x65, 0x74, 0x74, 0x6f, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73,
- 0x1a, 0x37, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2f, 0x70, 0x65, 0x72,
+ 0x69, 0x6e, 0x65, 0x4e, 0x75, 0x6d, 0x62, 0x65, 0x72, 0x0a, 0xb5, 0x4d,
+ 0x0a, 0x49, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2f, 0x70, 0x65, 0x72,
0x66, 0x65, 0x74, 0x74, 0x6f, 0x2f, 0x74, 0x72, 0x61, 0x63, 0x65, 0x2f,
0x74, 0x72, 0x61, 0x63, 0x6b, 0x5f, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x2f,
- 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x5f, 0x6c, 0x6f, 0x63, 0x61, 0x74,
- 0x69, 0x6f, 0x6e, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x22, 0xe6, 0x0b,
- 0x0a, 0x1e, 0x43, 0x68, 0x72, 0x6f, 0x6d, 0x65, 0x43, 0x6f, 0x6d, 0x70,
- 0x6f, 0x73, 0x69, 0x74, 0x6f, 0x72, 0x53, 0x63, 0x68, 0x65, 0x64, 0x75,
- 0x6c, 0x65, 0x72, 0x53, 0x74, 0x61, 0x74, 0x65, 0x12, 0x52, 0x0a, 0x0d,
- 0x73, 0x74, 0x61, 0x74, 0x65, 0x5f, 0x6d, 0x61, 0x63, 0x68, 0x69, 0x6e,
- 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2d, 0x2e, 0x70, 0x65,
+ 0x63, 0x68, 0x72, 0x6f, 0x6d, 0x65, 0x5f, 0x63, 0x6f, 0x6d, 0x70, 0x6f,
+ 0x73, 0x69, 0x74, 0x6f, 0x72, 0x5f, 0x73, 0x63, 0x68, 0x65, 0x64, 0x75,
+ 0x6c, 0x65, 0x72, 0x5f, 0x73, 0x74, 0x61, 0x74, 0x65, 0x2e, 0x70, 0x72,
+ 0x6f, 0x74, 0x6f, 0x12, 0x0f, 0x70, 0x65, 0x72, 0x66, 0x65, 0x74, 0x74,
+ 0x6f, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x1a, 0x37, 0x70, 0x72,
+ 0x6f, 0x74, 0x6f, 0x73, 0x2f, 0x70, 0x65, 0x72, 0x66, 0x65, 0x74, 0x74,
+ 0x6f, 0x2f, 0x74, 0x72, 0x61, 0x63, 0x65, 0x2f, 0x74, 0x72, 0x61, 0x63,
+ 0x6b, 0x5f, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x2f, 0x73, 0x6f, 0x75, 0x72,
+ 0x63, 0x65, 0x5f, 0x6c, 0x6f, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2e,
+ 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x22, 0xe6, 0x0b, 0x0a, 0x1e, 0x43, 0x68,
+ 0x72, 0x6f, 0x6d, 0x65, 0x43, 0x6f, 0x6d, 0x70, 0x6f, 0x73, 0x69, 0x74,
+ 0x6f, 0x72, 0x53, 0x63, 0x68, 0x65, 0x64, 0x75, 0x6c, 0x65, 0x72, 0x53,
+ 0x74, 0x61, 0x74, 0x65, 0x12, 0x52, 0x0a, 0x0d, 0x73, 0x74, 0x61, 0x74,
+ 0x65, 0x5f, 0x6d, 0x61, 0x63, 0x68, 0x69, 0x6e, 0x65, 0x18, 0x01, 0x20,
+ 0x01, 0x28, 0x0b, 0x32, 0x2d, 0x2e, 0x70, 0x65, 0x72, 0x66, 0x65, 0x74,
+ 0x74, 0x6f, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2e, 0x43, 0x68,
+ 0x72, 0x6f, 0x6d, 0x65, 0x43, 0x6f, 0x6d, 0x70, 0x6f, 0x73, 0x69, 0x74,
+ 0x6f, 0x72, 0x53, 0x74, 0x61, 0x74, 0x65, 0x4d, 0x61, 0x63, 0x68, 0x69,
+ 0x6e, 0x65, 0x52, 0x0c, 0x73, 0x74, 0x61, 0x74, 0x65, 0x4d, 0x61, 0x63,
+ 0x68, 0x69, 0x6e, 0x65, 0x12, 0x3f, 0x0a, 0x1c, 0x6f, 0x62, 0x73, 0x65,
+ 0x72, 0x76, 0x69, 0x6e, 0x67, 0x5f, 0x62, 0x65, 0x67, 0x69, 0x6e, 0x5f,
+ 0x66, 0x72, 0x61, 0x6d, 0x65, 0x5f, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65,
+ 0x18, 0x02, 0x20, 0x01, 0x28, 0x08, 0x52, 0x19, 0x6f, 0x62, 0x73, 0x65,
+ 0x72, 0x76, 0x69, 0x6e, 0x67, 0x42, 0x65, 0x67, 0x69, 0x6e, 0x46, 0x72,
+ 0x61, 0x6d, 0x65, 0x53, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x12, 0x42, 0x0a,
+ 0x1e, 0x62, 0x65, 0x67, 0x69, 0x6e, 0x5f, 0x69, 0x6d, 0x70, 0x6c, 0x5f,
+ 0x66, 0x72, 0x61, 0x6d, 0x65, 0x5f, 0x64, 0x65, 0x61, 0x64, 0x6c, 0x69,
+ 0x6e, 0x65, 0x5f, 0x74, 0x61, 0x73, 0x6b, 0x18, 0x03, 0x20, 0x01, 0x28,
+ 0x08, 0x52, 0x1a, 0x62, 0x65, 0x67, 0x69, 0x6e, 0x49, 0x6d, 0x70, 0x6c,
+ 0x46, 0x72, 0x61, 0x6d, 0x65, 0x44, 0x65, 0x61, 0x64, 0x6c, 0x69, 0x6e,
+ 0x65, 0x54, 0x61, 0x73, 0x6b, 0x12, 0x37, 0x0a, 0x18, 0x70, 0x65, 0x6e,
+ 0x64, 0x69, 0x6e, 0x67, 0x5f, 0x62, 0x65, 0x67, 0x69, 0x6e, 0x5f, 0x66,
+ 0x72, 0x61, 0x6d, 0x65, 0x5f, 0x74, 0x61, 0x73, 0x6b, 0x18, 0x04, 0x20,
+ 0x01, 0x28, 0x08, 0x52, 0x15, 0x70, 0x65, 0x6e, 0x64, 0x69, 0x6e, 0x67,
+ 0x42, 0x65, 0x67, 0x69, 0x6e, 0x46, 0x72, 0x61, 0x6d, 0x65, 0x54, 0x61,
+ 0x73, 0x6b, 0x12, 0x5b, 0x0a, 0x2b, 0x73, 0x6b, 0x69, 0x70, 0x70, 0x65,
+ 0x64, 0x5f, 0x6c, 0x61, 0x73, 0x74, 0x5f, 0x66, 0x72, 0x61, 0x6d, 0x65,
+ 0x5f, 0x6d, 0x69, 0x73, 0x73, 0x65, 0x64, 0x5f, 0x65, 0x78, 0x63, 0x65,
+ 0x65, 0x64, 0x65, 0x64, 0x5f, 0x64, 0x65, 0x61, 0x64, 0x6c, 0x69, 0x6e,
+ 0x65, 0x18, 0x05, 0x20, 0x01, 0x28, 0x08, 0x52, 0x26, 0x73, 0x6b, 0x69,
+ 0x70, 0x70, 0x65, 0x64, 0x4c, 0x61, 0x73, 0x74, 0x46, 0x72, 0x61, 0x6d,
+ 0x65, 0x4d, 0x69, 0x73, 0x73, 0x65, 0x64, 0x45, 0x78, 0x63, 0x65, 0x65,
+ 0x64, 0x65, 0x64, 0x44, 0x65, 0x61, 0x64, 0x6c, 0x69, 0x6e, 0x65, 0x12,
+ 0x4d, 0x0a, 0x24, 0x73, 0x6b, 0x69, 0x70, 0x70, 0x65, 0x64, 0x5f, 0x6c,
+ 0x61, 0x73, 0x74, 0x5f, 0x66, 0x72, 0x61, 0x6d, 0x65, 0x5f, 0x74, 0x6f,
+ 0x5f, 0x72, 0x65, 0x64, 0x75, 0x63, 0x65, 0x5f, 0x6c, 0x61, 0x74, 0x65,
+ 0x6e, 0x63, 0x79, 0x18, 0x06, 0x20, 0x01, 0x28, 0x08, 0x52, 0x1f, 0x73,
+ 0x6b, 0x69, 0x70, 0x70, 0x65, 0x64, 0x4c, 0x61, 0x73, 0x74, 0x46, 0x72,
+ 0x61, 0x6d, 0x65, 0x54, 0x6f, 0x52, 0x65, 0x64, 0x75, 0x63, 0x65, 0x4c,
+ 0x61, 0x74, 0x65, 0x6e, 0x63, 0x79, 0x12, 0x55, 0x0a, 0x0d, 0x69, 0x6e,
+ 0x73, 0x69, 0x64, 0x65, 0x5f, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x18,
+ 0x07, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x30, 0x2e, 0x70, 0x65, 0x72, 0x66,
+ 0x65, 0x74, 0x74, 0x6f, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2e,
+ 0x43, 0x68, 0x72, 0x6f, 0x6d, 0x65, 0x43, 0x6f, 0x6d, 0x70, 0x6f, 0x73,
+ 0x69, 0x74, 0x6f, 0x72, 0x53, 0x63, 0x68, 0x65, 0x64, 0x75, 0x6c, 0x65,
+ 0x72, 0x41, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x0c, 0x69, 0x6e, 0x73,
+ 0x69, 0x64, 0x65, 0x41, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x6f, 0x0a,
+ 0x0d, 0x64, 0x65, 0x61, 0x64, 0x6c, 0x69, 0x6e, 0x65, 0x5f, 0x6d, 0x6f,
+ 0x64, 0x65, 0x18, 0x08, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x4a, 0x2e, 0x70,
+ 0x65, 0x72, 0x66, 0x65, 0x74, 0x74, 0x6f, 0x2e, 0x70, 0x72, 0x6f, 0x74,
+ 0x6f, 0x73, 0x2e, 0x43, 0x68, 0x72, 0x6f, 0x6d, 0x65, 0x43, 0x6f, 0x6d,
+ 0x70, 0x6f, 0x73, 0x69, 0x74, 0x6f, 0x72, 0x53, 0x63, 0x68, 0x65, 0x64,
+ 0x75, 0x6c, 0x65, 0x72, 0x53, 0x74, 0x61, 0x74, 0x65, 0x2e, 0x42, 0x65,
+ 0x67, 0x69, 0x6e, 0x49, 0x6d, 0x70, 0x6c, 0x46, 0x72, 0x61, 0x6d, 0x65,
+ 0x44, 0x65, 0x61, 0x64, 0x6c, 0x69, 0x6e, 0x65, 0x4d, 0x6f, 0x64, 0x65,
+ 0x52, 0x0c, 0x64, 0x65, 0x61, 0x64, 0x6c, 0x69, 0x6e, 0x65, 0x4d, 0x6f,
+ 0x64, 0x65, 0x12, 0x1f, 0x0a, 0x0b, 0x64, 0x65, 0x61, 0x64, 0x6c, 0x69,
+ 0x6e, 0x65, 0x5f, 0x75, 0x73, 0x18, 0x09, 0x20, 0x01, 0x28, 0x03, 0x52,
+ 0x0a, 0x64, 0x65, 0x61, 0x64, 0x6c, 0x69, 0x6e, 0x65, 0x55, 0x73, 0x12,
+ 0x37, 0x0a, 0x18, 0x64, 0x65, 0x61, 0x64, 0x6c, 0x69, 0x6e, 0x65, 0x5f,
+ 0x73, 0x63, 0x68, 0x65, 0x64, 0x75, 0x6c, 0x65, 0x64, 0x5f, 0x61, 0x74,
+ 0x5f, 0x75, 0x73, 0x18, 0x0a, 0x20, 0x01, 0x28, 0x03, 0x52, 0x15, 0x64,
+ 0x65, 0x61, 0x64, 0x6c, 0x69, 0x6e, 0x65, 0x53, 0x63, 0x68, 0x65, 0x64,
+ 0x75, 0x6c, 0x65, 0x64, 0x41, 0x74, 0x55, 0x73, 0x12, 0x15, 0x0a, 0x06,
+ 0x6e, 0x6f, 0x77, 0x5f, 0x75, 0x73, 0x18, 0x0b, 0x20, 0x01, 0x28, 0x03,
+ 0x52, 0x05, 0x6e, 0x6f, 0x77, 0x55, 0x73, 0x12, 0x36, 0x0a, 0x18, 0x6e,
+ 0x6f, 0x77, 0x5f, 0x74, 0x6f, 0x5f, 0x64, 0x65, 0x61, 0x64, 0x6c, 0x69,
+ 0x6e, 0x65, 0x5f, 0x64, 0x65, 0x6c, 0x74, 0x61, 0x5f, 0x75, 0x73, 0x18,
+ 0x0c, 0x20, 0x01, 0x28, 0x03, 0x52, 0x14, 0x6e, 0x6f, 0x77, 0x54, 0x6f,
+ 0x44, 0x65, 0x61, 0x64, 0x6c, 0x69, 0x6e, 0x65, 0x44, 0x65, 0x6c, 0x74,
+ 0x61, 0x55, 0x73, 0x12, 0x4e, 0x0a, 0x25, 0x6e, 0x6f, 0x77, 0x5f, 0x74,
+ 0x6f, 0x5f, 0x64, 0x65, 0x61, 0x64, 0x6c, 0x69, 0x6e, 0x65, 0x5f, 0x73,
+ 0x63, 0x68, 0x65, 0x64, 0x75, 0x6c, 0x65, 0x64, 0x5f, 0x61, 0x74, 0x5f,
+ 0x64, 0x65, 0x6c, 0x74, 0x61, 0x5f, 0x75, 0x73, 0x18, 0x0d, 0x20, 0x01,
+ 0x28, 0x03, 0x52, 0x1f, 0x6e, 0x6f, 0x77, 0x54, 0x6f, 0x44, 0x65, 0x61,
+ 0x64, 0x6c, 0x69, 0x6e, 0x65, 0x53, 0x63, 0x68, 0x65, 0x64, 0x75, 0x6c,
+ 0x65, 0x64, 0x41, 0x74, 0x44, 0x65, 0x6c, 0x74, 0x61, 0x55, 0x73, 0x12,
+ 0x56, 0x0a, 0x15, 0x62, 0x65, 0x67, 0x69, 0x6e, 0x5f, 0x69, 0x6d, 0x70,
+ 0x6c, 0x5f, 0x66, 0x72, 0x61, 0x6d, 0x65, 0x5f, 0x61, 0x72, 0x67, 0x73,
+ 0x18, 0x0e, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x23, 0x2e, 0x70, 0x65, 0x72,
+ 0x66, 0x65, 0x74, 0x74, 0x6f, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73,
+ 0x2e, 0x42, 0x65, 0x67, 0x69, 0x6e, 0x49, 0x6d, 0x70, 0x6c, 0x46, 0x72,
+ 0x61, 0x6d, 0x65, 0x41, 0x72, 0x67, 0x73, 0x52, 0x12, 0x62, 0x65, 0x67,
+ 0x69, 0x6e, 0x49, 0x6d, 0x70, 0x6c, 0x46, 0x72, 0x61, 0x6d, 0x65, 0x41,
+ 0x72, 0x67, 0x73, 0x12, 0x65, 0x0a, 0x1a, 0x62, 0x65, 0x67, 0x69, 0x6e,
+ 0x5f, 0x66, 0x72, 0x61, 0x6d, 0x65, 0x5f, 0x6f, 0x62, 0x73, 0x65, 0x72,
+ 0x76, 0x65, 0x72, 0x5f, 0x73, 0x74, 0x61, 0x74, 0x65, 0x18, 0x0f, 0x20,
+ 0x01, 0x28, 0x0b, 0x32, 0x28, 0x2e, 0x70, 0x65, 0x72, 0x66, 0x65, 0x74,
+ 0x74, 0x6f, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2e, 0x42, 0x65,
+ 0x67, 0x69, 0x6e, 0x46, 0x72, 0x61, 0x6d, 0x65, 0x4f, 0x62, 0x73, 0x65,
+ 0x72, 0x76, 0x65, 0x72, 0x53, 0x74, 0x61, 0x74, 0x65, 0x52, 0x17, 0x62,
+ 0x65, 0x67, 0x69, 0x6e, 0x46, 0x72, 0x61, 0x6d, 0x65, 0x4f, 0x62, 0x73,
+ 0x65, 0x72, 0x76, 0x65, 0x72, 0x53, 0x74, 0x61, 0x74, 0x65, 0x12, 0x5f,
+ 0x0a, 0x18, 0x62, 0x65, 0x67, 0x69, 0x6e, 0x5f, 0x66, 0x72, 0x61, 0x6d,
+ 0x65, 0x5f, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x5f, 0x73, 0x74, 0x61,
+ 0x74, 0x65, 0x18, 0x10, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x26, 0x2e, 0x70,
+ 0x65, 0x72, 0x66, 0x65, 0x74, 0x74, 0x6f, 0x2e, 0x70, 0x72, 0x6f, 0x74,
+ 0x6f, 0x73, 0x2e, 0x42, 0x65, 0x67, 0x69, 0x6e, 0x46, 0x72, 0x61, 0x6d,
+ 0x65, 0x53, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x53, 0x74, 0x61, 0x74, 0x65,
+ 0x52, 0x15, 0x62, 0x65, 0x67, 0x69, 0x6e, 0x46, 0x72, 0x61, 0x6d, 0x65,
+ 0x53, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x53, 0x74, 0x61, 0x74, 0x65, 0x12,
+ 0x64, 0x0a, 0x19, 0x63, 0x6f, 0x6d, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x6f,
+ 0x72, 0x5f, 0x74, 0x69, 0x6d, 0x69, 0x6e, 0x67, 0x5f, 0x68, 0x69, 0x73,
+ 0x74, 0x6f, 0x72, 0x79, 0x18, 0x11, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x28,
+ 0x2e, 0x70, 0x65, 0x72, 0x66, 0x65, 0x74, 0x74, 0x6f, 0x2e, 0x70, 0x72,
+ 0x6f, 0x74, 0x6f, 0x73, 0x2e, 0x43, 0x6f, 0x6d, 0x70, 0x6f, 0x73, 0x69,
+ 0x74, 0x6f, 0x72, 0x54, 0x69, 0x6d, 0x69, 0x6e, 0x67, 0x48, 0x69, 0x73,
+ 0x74, 0x6f, 0x72, 0x79, 0x52, 0x17, 0x63, 0x6f, 0x6d, 0x70, 0x6f, 0x73,
+ 0x69, 0x74, 0x6f, 0x72, 0x54, 0x69, 0x6d, 0x69, 0x6e, 0x67, 0x48, 0x69,
+ 0x73, 0x74, 0x6f, 0x72, 0x79, 0x22, 0xbe, 0x01, 0x0a, 0x1a, 0x42, 0x65,
+ 0x67, 0x69, 0x6e, 0x49, 0x6d, 0x70, 0x6c, 0x46, 0x72, 0x61, 0x6d, 0x65,
+ 0x44, 0x65, 0x61, 0x64, 0x6c, 0x69, 0x6e, 0x65, 0x4d, 0x6f, 0x64, 0x65,
+ 0x12, 0x1d, 0x0a, 0x19, 0x44, 0x45, 0x41, 0x44, 0x4c, 0x49, 0x4e, 0x45,
+ 0x5f, 0x4d, 0x4f, 0x44, 0x45, 0x5f, 0x55, 0x4e, 0x53, 0x50, 0x45, 0x43,
+ 0x49, 0x46, 0x49, 0x45, 0x44, 0x10, 0x00, 0x12, 0x16, 0x0a, 0x12, 0x44,
+ 0x45, 0x41, 0x44, 0x4c, 0x49, 0x4e, 0x45, 0x5f, 0x4d, 0x4f, 0x44, 0x45,
+ 0x5f, 0x4e, 0x4f, 0x4e, 0x45, 0x10, 0x01, 0x12, 0x1b, 0x0a, 0x17, 0x44,
+ 0x45, 0x41, 0x44, 0x4c, 0x49, 0x4e, 0x45, 0x5f, 0x4d, 0x4f, 0x44, 0x45,
+ 0x5f, 0x49, 0x4d, 0x4d, 0x45, 0x44, 0x49, 0x41, 0x54, 0x45, 0x10, 0x02,
+ 0x12, 0x19, 0x0a, 0x15, 0x44, 0x45, 0x41, 0x44, 0x4c, 0x49, 0x4e, 0x45,
+ 0x5f, 0x4d, 0x4f, 0x44, 0x45, 0x5f, 0x52, 0x45, 0x47, 0x55, 0x4c, 0x41,
+ 0x52, 0x10, 0x03, 0x12, 0x16, 0x0a, 0x12, 0x44, 0x45, 0x41, 0x44, 0x4c,
+ 0x49, 0x4e, 0x45, 0x5f, 0x4d, 0x4f, 0x44, 0x45, 0x5f, 0x4c, 0x41, 0x54,
+ 0x45, 0x10, 0x04, 0x12, 0x19, 0x0a, 0x15, 0x44, 0x45, 0x41, 0x44, 0x4c,
+ 0x49, 0x4e, 0x45, 0x5f, 0x4d, 0x4f, 0x44, 0x45, 0x5f, 0x42, 0x4c, 0x4f,
+ 0x43, 0x4b, 0x45, 0x44, 0x10, 0x05, 0x22, 0x86, 0x28, 0x0a, 0x1c, 0x43,
+ 0x68, 0x72, 0x6f, 0x6d, 0x65, 0x43, 0x6f, 0x6d, 0x70, 0x6f, 0x73, 0x69,
+ 0x74, 0x6f, 0x72, 0x53, 0x74, 0x61, 0x74, 0x65, 0x4d, 0x61, 0x63, 0x68,
+ 0x69, 0x6e, 0x65, 0x12, 0x59, 0x0a, 0x0b, 0x6d, 0x61, 0x6a, 0x6f, 0x72,
+ 0x5f, 0x73, 0x74, 0x61, 0x74, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b,
+ 0x32, 0x38, 0x2e, 0x70, 0x65, 0x72, 0x66, 0x65, 0x74, 0x74, 0x6f, 0x2e,
+ 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2e, 0x43, 0x68, 0x72, 0x6f, 0x6d,
+ 0x65, 0x43, 0x6f, 0x6d, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x6f, 0x72, 0x53,
+ 0x74, 0x61, 0x74, 0x65, 0x4d, 0x61, 0x63, 0x68, 0x69, 0x6e, 0x65, 0x2e,
+ 0x4d, 0x61, 0x6a, 0x6f, 0x72, 0x53, 0x74, 0x61, 0x74, 0x65, 0x52, 0x0a,
+ 0x6d, 0x61, 0x6a, 0x6f, 0x72, 0x53, 0x74, 0x61, 0x74, 0x65, 0x12, 0x59,
+ 0x0a, 0x0b, 0x6d, 0x69, 0x6e, 0x6f, 0x72, 0x5f, 0x73, 0x74, 0x61, 0x74,
+ 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x38, 0x2e, 0x70, 0x65,
0x72, 0x66, 0x65, 0x74, 0x74, 0x6f, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f,
0x73, 0x2e, 0x43, 0x68, 0x72, 0x6f, 0x6d, 0x65, 0x43, 0x6f, 0x6d, 0x70,
0x6f, 0x73, 0x69, 0x74, 0x6f, 0x72, 0x53, 0x74, 0x61, 0x74, 0x65, 0x4d,
- 0x61, 0x63, 0x68, 0x69, 0x6e, 0x65, 0x52, 0x0c, 0x73, 0x74, 0x61, 0x74,
- 0x65, 0x4d, 0x61, 0x63, 0x68, 0x69, 0x6e, 0x65, 0x12, 0x3f, 0x0a, 0x1c,
- 0x6f, 0x62, 0x73, 0x65, 0x72, 0x76, 0x69, 0x6e, 0x67, 0x5f, 0x62, 0x65,
- 0x67, 0x69, 0x6e, 0x5f, 0x66, 0x72, 0x61, 0x6d, 0x65, 0x5f, 0x73, 0x6f,
- 0x75, 0x72, 0x63, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x08, 0x52, 0x19,
- 0x6f, 0x62, 0x73, 0x65, 0x72, 0x76, 0x69, 0x6e, 0x67, 0x42, 0x65, 0x67,
- 0x69, 0x6e, 0x46, 0x72, 0x61, 0x6d, 0x65, 0x53, 0x6f, 0x75, 0x72, 0x63,
- 0x65, 0x12, 0x42, 0x0a, 0x1e, 0x62, 0x65, 0x67, 0x69, 0x6e, 0x5f, 0x69,
- 0x6d, 0x70, 0x6c, 0x5f, 0x66, 0x72, 0x61, 0x6d, 0x65, 0x5f, 0x64, 0x65,
- 0x61, 0x64, 0x6c, 0x69, 0x6e, 0x65, 0x5f, 0x74, 0x61, 0x73, 0x6b, 0x18,
- 0x03, 0x20, 0x01, 0x28, 0x08, 0x52, 0x1a, 0x62, 0x65, 0x67, 0x69, 0x6e,
- 0x49, 0x6d, 0x70, 0x6c, 0x46, 0x72, 0x61, 0x6d, 0x65, 0x44, 0x65, 0x61,
- 0x64, 0x6c, 0x69, 0x6e, 0x65, 0x54, 0x61, 0x73, 0x6b, 0x12, 0x37, 0x0a,
- 0x18, 0x70, 0x65, 0x6e, 0x64, 0x69, 0x6e, 0x67, 0x5f, 0x62, 0x65, 0x67,
- 0x69, 0x6e, 0x5f, 0x66, 0x72, 0x61, 0x6d, 0x65, 0x5f, 0x74, 0x61, 0x73,
- 0x6b, 0x18, 0x04, 0x20, 0x01, 0x28, 0x08, 0x52, 0x15, 0x70, 0x65, 0x6e,
- 0x64, 0x69, 0x6e, 0x67, 0x42, 0x65, 0x67, 0x69, 0x6e, 0x46, 0x72, 0x61,
- 0x6d, 0x65, 0x54, 0x61, 0x73, 0x6b, 0x12, 0x5b, 0x0a, 0x2b, 0x73, 0x6b,
- 0x69, 0x70, 0x70, 0x65, 0x64, 0x5f, 0x6c, 0x61, 0x73, 0x74, 0x5f, 0x66,
- 0x72, 0x61, 0x6d, 0x65, 0x5f, 0x6d, 0x69, 0x73, 0x73, 0x65, 0x64, 0x5f,
- 0x65, 0x78, 0x63, 0x65, 0x65, 0x64, 0x65, 0x64, 0x5f, 0x64, 0x65, 0x61,
- 0x64, 0x6c, 0x69, 0x6e, 0x65, 0x18, 0x05, 0x20, 0x01, 0x28, 0x08, 0x52,
- 0x26, 0x73, 0x6b, 0x69, 0x70, 0x70, 0x65, 0x64, 0x4c, 0x61, 0x73, 0x74,
- 0x46, 0x72, 0x61, 0x6d, 0x65, 0x4d, 0x69, 0x73, 0x73, 0x65, 0x64, 0x45,
- 0x78, 0x63, 0x65, 0x65, 0x64, 0x65, 0x64, 0x44, 0x65, 0x61, 0x64, 0x6c,
- 0x69, 0x6e, 0x65, 0x12, 0x4d, 0x0a, 0x24, 0x73, 0x6b, 0x69, 0x70, 0x70,
- 0x65, 0x64, 0x5f, 0x6c, 0x61, 0x73, 0x74, 0x5f, 0x66, 0x72, 0x61, 0x6d,
- 0x65, 0x5f, 0x74, 0x6f, 0x5f, 0x72, 0x65, 0x64, 0x75, 0x63, 0x65, 0x5f,
- 0x6c, 0x61, 0x74, 0x65, 0x6e, 0x63, 0x79, 0x18, 0x06, 0x20, 0x01, 0x28,
- 0x08, 0x52, 0x1f, 0x73, 0x6b, 0x69, 0x70, 0x70, 0x65, 0x64, 0x4c, 0x61,
- 0x73, 0x74, 0x46, 0x72, 0x61, 0x6d, 0x65, 0x54, 0x6f, 0x52, 0x65, 0x64,
- 0x75, 0x63, 0x65, 0x4c, 0x61, 0x74, 0x65, 0x6e, 0x63, 0x79, 0x12, 0x55,
- 0x0a, 0x0d, 0x69, 0x6e, 0x73, 0x69, 0x64, 0x65, 0x5f, 0x61, 0x63, 0x74,
- 0x69, 0x6f, 0x6e, 0x18, 0x07, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x30, 0x2e,
- 0x70, 0x65, 0x72, 0x66, 0x65, 0x74, 0x74, 0x6f, 0x2e, 0x70, 0x72, 0x6f,
- 0x74, 0x6f, 0x73, 0x2e, 0x43, 0x68, 0x72, 0x6f, 0x6d, 0x65, 0x43, 0x6f,
- 0x6d, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x6f, 0x72, 0x53, 0x63, 0x68, 0x65,
- 0x64, 0x75, 0x6c, 0x65, 0x72, 0x41, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x52,
- 0x0c, 0x69, 0x6e, 0x73, 0x69, 0x64, 0x65, 0x41, 0x63, 0x74, 0x69, 0x6f,
- 0x6e, 0x12, 0x6f, 0x0a, 0x0d, 0x64, 0x65, 0x61, 0x64, 0x6c, 0x69, 0x6e,
- 0x65, 0x5f, 0x6d, 0x6f, 0x64, 0x65, 0x18, 0x08, 0x20, 0x01, 0x28, 0x0e,
- 0x32, 0x4a, 0x2e, 0x70, 0x65, 0x72, 0x66, 0x65, 0x74, 0x74, 0x6f, 0x2e,
- 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2e, 0x43, 0x68, 0x72, 0x6f, 0x6d,
- 0x65, 0x43, 0x6f, 0x6d, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x6f, 0x72, 0x53,
- 0x63, 0x68, 0x65, 0x64, 0x75, 0x6c, 0x65, 0x72, 0x53, 0x74, 0x61, 0x74,
- 0x65, 0x2e, 0x42, 0x65, 0x67, 0x69, 0x6e, 0x49, 0x6d, 0x70, 0x6c, 0x46,
- 0x72, 0x61, 0x6d, 0x65, 0x44, 0x65, 0x61, 0x64, 0x6c, 0x69, 0x6e, 0x65,
- 0x4d, 0x6f, 0x64, 0x65, 0x52, 0x0c, 0x64, 0x65, 0x61, 0x64, 0x6c, 0x69,
- 0x6e, 0x65, 0x4d, 0x6f, 0x64, 0x65, 0x12, 0x1f, 0x0a, 0x0b, 0x64, 0x65,
- 0x61, 0x64, 0x6c, 0x69, 0x6e, 0x65, 0x5f, 0x75, 0x73, 0x18, 0x09, 0x20,
- 0x01, 0x28, 0x03, 0x52, 0x0a, 0x64, 0x65, 0x61, 0x64, 0x6c, 0x69, 0x6e,
- 0x65, 0x55, 0x73, 0x12, 0x37, 0x0a, 0x18, 0x64, 0x65, 0x61, 0x64, 0x6c,
- 0x69, 0x6e, 0x65, 0x5f, 0x73, 0x63, 0x68, 0x65, 0x64, 0x75, 0x6c, 0x65,
- 0x64, 0x5f, 0x61, 0x74, 0x5f, 0x75, 0x73, 0x18, 0x0a, 0x20, 0x01, 0x28,
- 0x03, 0x52, 0x15, 0x64, 0x65, 0x61, 0x64, 0x6c, 0x69, 0x6e, 0x65, 0x53,
- 0x63, 0x68, 0x65, 0x64, 0x75, 0x6c, 0x65, 0x64, 0x41, 0x74, 0x55, 0x73,
- 0x12, 0x15, 0x0a, 0x06, 0x6e, 0x6f, 0x77, 0x5f, 0x75, 0x73, 0x18, 0x0b,
- 0x20, 0x01, 0x28, 0x03, 0x52, 0x05, 0x6e, 0x6f, 0x77, 0x55, 0x73, 0x12,
- 0x36, 0x0a, 0x18, 0x6e, 0x6f, 0x77, 0x5f, 0x74, 0x6f, 0x5f, 0x64, 0x65,
- 0x61, 0x64, 0x6c, 0x69, 0x6e, 0x65, 0x5f, 0x64, 0x65, 0x6c, 0x74, 0x61,
- 0x5f, 0x75, 0x73, 0x18, 0x0c, 0x20, 0x01, 0x28, 0x03, 0x52, 0x14, 0x6e,
- 0x6f, 0x77, 0x54, 0x6f, 0x44, 0x65, 0x61, 0x64, 0x6c, 0x69, 0x6e, 0x65,
- 0x44, 0x65, 0x6c, 0x74, 0x61, 0x55, 0x73, 0x12, 0x4e, 0x0a, 0x25, 0x6e,
- 0x6f, 0x77, 0x5f, 0x74, 0x6f, 0x5f, 0x64, 0x65, 0x61, 0x64, 0x6c, 0x69,
- 0x6e, 0x65, 0x5f, 0x73, 0x63, 0x68, 0x65, 0x64, 0x75, 0x6c, 0x65, 0x64,
- 0x5f, 0x61, 0x74, 0x5f, 0x64, 0x65, 0x6c, 0x74, 0x61, 0x5f, 0x75, 0x73,
- 0x18, 0x0d, 0x20, 0x01, 0x28, 0x03, 0x52, 0x1f, 0x6e, 0x6f, 0x77, 0x54,
- 0x6f, 0x44, 0x65, 0x61, 0x64, 0x6c, 0x69, 0x6e, 0x65, 0x53, 0x63, 0x68,
- 0x65, 0x64, 0x75, 0x6c, 0x65, 0x64, 0x41, 0x74, 0x44, 0x65, 0x6c, 0x74,
- 0x61, 0x55, 0x73, 0x12, 0x56, 0x0a, 0x15, 0x62, 0x65, 0x67, 0x69, 0x6e,
- 0x5f, 0x69, 0x6d, 0x70, 0x6c, 0x5f, 0x66, 0x72, 0x61, 0x6d, 0x65, 0x5f,
- 0x61, 0x72, 0x67, 0x73, 0x18, 0x0e, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x23,
- 0x2e, 0x70, 0x65, 0x72, 0x66, 0x65, 0x74, 0x74, 0x6f, 0x2e, 0x70, 0x72,
- 0x6f, 0x74, 0x6f, 0x73, 0x2e, 0x42, 0x65, 0x67, 0x69, 0x6e, 0x49, 0x6d,
- 0x70, 0x6c, 0x46, 0x72, 0x61, 0x6d, 0x65, 0x41, 0x72, 0x67, 0x73, 0x52,
- 0x12, 0x62, 0x65, 0x67, 0x69, 0x6e, 0x49, 0x6d, 0x70, 0x6c, 0x46, 0x72,
- 0x61, 0x6d, 0x65, 0x41, 0x72, 0x67, 0x73, 0x12, 0x65, 0x0a, 0x1a, 0x62,
- 0x65, 0x67, 0x69, 0x6e, 0x5f, 0x66, 0x72, 0x61, 0x6d, 0x65, 0x5f, 0x6f,
- 0x62, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x5f, 0x73, 0x74, 0x61, 0x74,
- 0x65, 0x18, 0x0f, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x28, 0x2e, 0x70, 0x65,
- 0x72, 0x66, 0x65, 0x74, 0x74, 0x6f, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f,
- 0x73, 0x2e, 0x42, 0x65, 0x67, 0x69, 0x6e, 0x46, 0x72, 0x61, 0x6d, 0x65,
- 0x4f, 0x62, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x53, 0x74, 0x61, 0x74,
- 0x65, 0x52, 0x17, 0x62, 0x65, 0x67, 0x69, 0x6e, 0x46, 0x72, 0x61, 0x6d,
- 0x65, 0x4f, 0x62, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x53, 0x74, 0x61,
- 0x74, 0x65, 0x12, 0x5f, 0x0a, 0x18, 0x62, 0x65, 0x67, 0x69, 0x6e, 0x5f,
- 0x66, 0x72, 0x61, 0x6d, 0x65, 0x5f, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65,
- 0x5f, 0x73, 0x74, 0x61, 0x74, 0x65, 0x18, 0x10, 0x20, 0x01, 0x28, 0x0b,
- 0x32, 0x26, 0x2e, 0x70, 0x65, 0x72, 0x66, 0x65, 0x74, 0x74, 0x6f, 0x2e,
- 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2e, 0x42, 0x65, 0x67, 0x69, 0x6e,
- 0x46, 0x72, 0x61, 0x6d, 0x65, 0x53, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x53,
- 0x74, 0x61, 0x74, 0x65, 0x52, 0x15, 0x62, 0x65, 0x67, 0x69, 0x6e, 0x46,
- 0x72, 0x61, 0x6d, 0x65, 0x53, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x53, 0x74,
- 0x61, 0x74, 0x65, 0x12, 0x64, 0x0a, 0x19, 0x63, 0x6f, 0x6d, 0x70, 0x6f,
- 0x73, 0x69, 0x74, 0x6f, 0x72, 0x5f, 0x74, 0x69, 0x6d, 0x69, 0x6e, 0x67,
- 0x5f, 0x68, 0x69, 0x73, 0x74, 0x6f, 0x72, 0x79, 0x18, 0x11, 0x20, 0x01,
- 0x28, 0x0b, 0x32, 0x28, 0x2e, 0x70, 0x65, 0x72, 0x66, 0x65, 0x74, 0x74,
- 0x6f, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2e, 0x43, 0x6f, 0x6d,
- 0x70, 0x6f, 0x73, 0x69, 0x74, 0x6f, 0x72, 0x54, 0x69, 0x6d, 0x69, 0x6e,
- 0x67, 0x48, 0x69, 0x73, 0x74, 0x6f, 0x72, 0x79, 0x52, 0x17, 0x63, 0x6f,
- 0x6d, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x6f, 0x72, 0x54, 0x69, 0x6d, 0x69,
- 0x6e, 0x67, 0x48, 0x69, 0x73, 0x74, 0x6f, 0x72, 0x79, 0x22, 0xbe, 0x01,
- 0x0a, 0x1a, 0x42, 0x65, 0x67, 0x69, 0x6e, 0x49, 0x6d, 0x70, 0x6c, 0x46,
- 0x72, 0x61, 0x6d, 0x65, 0x44, 0x65, 0x61, 0x64, 0x6c, 0x69, 0x6e, 0x65,
- 0x4d, 0x6f, 0x64, 0x65, 0x12, 0x1d, 0x0a, 0x19, 0x44, 0x45, 0x41, 0x44,
- 0x4c, 0x49, 0x4e, 0x45, 0x5f, 0x4d, 0x4f, 0x44, 0x45, 0x5f, 0x55, 0x4e,
- 0x53, 0x50, 0x45, 0x43, 0x49, 0x46, 0x49, 0x45, 0x44, 0x10, 0x00, 0x12,
- 0x16, 0x0a, 0x12, 0x44, 0x45, 0x41, 0x44, 0x4c, 0x49, 0x4e, 0x45, 0x5f,
- 0x4d, 0x4f, 0x44, 0x45, 0x5f, 0x4e, 0x4f, 0x4e, 0x45, 0x10, 0x01, 0x12,
- 0x1b, 0x0a, 0x17, 0x44, 0x45, 0x41, 0x44, 0x4c, 0x49, 0x4e, 0x45, 0x5f,
- 0x4d, 0x4f, 0x44, 0x45, 0x5f, 0x49, 0x4d, 0x4d, 0x45, 0x44, 0x49, 0x41,
- 0x54, 0x45, 0x10, 0x02, 0x12, 0x19, 0x0a, 0x15, 0x44, 0x45, 0x41, 0x44,
- 0x4c, 0x49, 0x4e, 0x45, 0x5f, 0x4d, 0x4f, 0x44, 0x45, 0x5f, 0x52, 0x45,
- 0x47, 0x55, 0x4c, 0x41, 0x52, 0x10, 0x03, 0x12, 0x16, 0x0a, 0x12, 0x44,
- 0x45, 0x41, 0x44, 0x4c, 0x49, 0x4e, 0x45, 0x5f, 0x4d, 0x4f, 0x44, 0x45,
- 0x5f, 0x4c, 0x41, 0x54, 0x45, 0x10, 0x04, 0x12, 0x19, 0x0a, 0x15, 0x44,
- 0x45, 0x41, 0x44, 0x4c, 0x49, 0x4e, 0x45, 0x5f, 0x4d, 0x4f, 0x44, 0x45,
- 0x5f, 0x42, 0x4c, 0x4f, 0x43, 0x4b, 0x45, 0x44, 0x10, 0x05, 0x22, 0x86,
- 0x28, 0x0a, 0x1c, 0x43, 0x68, 0x72, 0x6f, 0x6d, 0x65, 0x43, 0x6f, 0x6d,
- 0x70, 0x6f, 0x73, 0x69, 0x74, 0x6f, 0x72, 0x53, 0x74, 0x61, 0x74, 0x65,
- 0x4d, 0x61, 0x63, 0x68, 0x69, 0x6e, 0x65, 0x12, 0x59, 0x0a, 0x0b, 0x6d,
- 0x61, 0x6a, 0x6f, 0x72, 0x5f, 0x73, 0x74, 0x61, 0x74, 0x65, 0x18, 0x01,
- 0x20, 0x01, 0x28, 0x0b, 0x32, 0x38, 0x2e, 0x70, 0x65, 0x72, 0x66, 0x65,
+ 0x61, 0x63, 0x68, 0x69, 0x6e, 0x65, 0x2e, 0x4d, 0x69, 0x6e, 0x6f, 0x72,
+ 0x53, 0x74, 0x61, 0x74, 0x65, 0x52, 0x0a, 0x6d, 0x69, 0x6e, 0x6f, 0x72,
+ 0x53, 0x74, 0x61, 0x74, 0x65, 0x1a, 0xf9, 0x0a, 0x0a, 0x0a, 0x4d, 0x61,
+ 0x6a, 0x6f, 0x72, 0x53, 0x74, 0x61, 0x74, 0x65, 0x12, 0x51, 0x0a, 0x0b,
+ 0x6e, 0x65, 0x78, 0x74, 0x5f, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x18,
+ 0x01, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x30, 0x2e, 0x70, 0x65, 0x72, 0x66,
+ 0x65, 0x74, 0x74, 0x6f, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2e,
+ 0x43, 0x68, 0x72, 0x6f, 0x6d, 0x65, 0x43, 0x6f, 0x6d, 0x70, 0x6f, 0x73,
+ 0x69, 0x74, 0x6f, 0x72, 0x53, 0x63, 0x68, 0x65, 0x64, 0x75, 0x6c, 0x65,
+ 0x72, 0x41, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x0a, 0x6e, 0x65, 0x78,
+ 0x74, 0x41, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x81, 0x01, 0x0a, 0x16,
+ 0x62, 0x65, 0x67, 0x69, 0x6e, 0x5f, 0x69, 0x6d, 0x70, 0x6c, 0x5f, 0x66,
+ 0x72, 0x61, 0x6d, 0x65, 0x5f, 0x73, 0x74, 0x61, 0x74, 0x65, 0x18, 0x02,
+ 0x20, 0x01, 0x28, 0x0e, 0x32, 0x4c, 0x2e, 0x70, 0x65, 0x72, 0x66, 0x65,
0x74, 0x74, 0x6f, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2e, 0x43,
0x68, 0x72, 0x6f, 0x6d, 0x65, 0x43, 0x6f, 0x6d, 0x70, 0x6f, 0x73, 0x69,
0x74, 0x6f, 0x72, 0x53, 0x74, 0x61, 0x74, 0x65, 0x4d, 0x61, 0x63, 0x68,
0x69, 0x6e, 0x65, 0x2e, 0x4d, 0x61, 0x6a, 0x6f, 0x72, 0x53, 0x74, 0x61,
- 0x74, 0x65, 0x52, 0x0a, 0x6d, 0x61, 0x6a, 0x6f, 0x72, 0x53, 0x74, 0x61,
- 0x74, 0x65, 0x12, 0x59, 0x0a, 0x0b, 0x6d, 0x69, 0x6e, 0x6f, 0x72, 0x5f,
- 0x73, 0x74, 0x61, 0x74, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32,
- 0x38, 0x2e, 0x70, 0x65, 0x72, 0x66, 0x65, 0x74, 0x74, 0x6f, 0x2e, 0x70,
+ 0x74, 0x65, 0x2e, 0x42, 0x65, 0x67, 0x69, 0x6e, 0x49, 0x6d, 0x70, 0x6c,
+ 0x46, 0x72, 0x61, 0x6d, 0x65, 0x53, 0x74, 0x61, 0x74, 0x65, 0x52, 0x13,
+ 0x62, 0x65, 0x67, 0x69, 0x6e, 0x49, 0x6d, 0x70, 0x6c, 0x46, 0x72, 0x61,
+ 0x6d, 0x65, 0x53, 0x74, 0x61, 0x74, 0x65, 0x12, 0x81, 0x01, 0x0a, 0x16,
+ 0x62, 0x65, 0x67, 0x69, 0x6e, 0x5f, 0x6d, 0x61, 0x69, 0x6e, 0x5f, 0x66,
+ 0x72, 0x61, 0x6d, 0x65, 0x5f, 0x73, 0x74, 0x61, 0x74, 0x65, 0x18, 0x03,
+ 0x20, 0x01, 0x28, 0x0e, 0x32, 0x4c, 0x2e, 0x70, 0x65, 0x72, 0x66, 0x65,
+ 0x74, 0x74, 0x6f, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2e, 0x43,
+ 0x68, 0x72, 0x6f, 0x6d, 0x65, 0x43, 0x6f, 0x6d, 0x70, 0x6f, 0x73, 0x69,
+ 0x74, 0x6f, 0x72, 0x53, 0x74, 0x61, 0x74, 0x65, 0x4d, 0x61, 0x63, 0x68,
+ 0x69, 0x6e, 0x65, 0x2e, 0x4d, 0x61, 0x6a, 0x6f, 0x72, 0x53, 0x74, 0x61,
+ 0x74, 0x65, 0x2e, 0x42, 0x65, 0x67, 0x69, 0x6e, 0x4d, 0x61, 0x69, 0x6e,
+ 0x46, 0x72, 0x61, 0x6d, 0x65, 0x53, 0x74, 0x61, 0x74, 0x65, 0x52, 0x13,
+ 0x62, 0x65, 0x67, 0x69, 0x6e, 0x4d, 0x61, 0x69, 0x6e, 0x46, 0x72, 0x61,
+ 0x6d, 0x65, 0x53, 0x74, 0x61, 0x74, 0x65, 0x12, 0x8e, 0x01, 0x0a, 0x1b,
+ 0x6c, 0x61, 0x79, 0x65, 0x72, 0x5f, 0x74, 0x72, 0x65, 0x65, 0x5f, 0x66,
+ 0x72, 0x61, 0x6d, 0x65, 0x5f, 0x73, 0x69, 0x6e, 0x6b, 0x5f, 0x73, 0x74,
+ 0x61, 0x74, 0x65, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x50, 0x2e,
+ 0x70, 0x65, 0x72, 0x66, 0x65, 0x74, 0x74, 0x6f, 0x2e, 0x70, 0x72, 0x6f,
+ 0x74, 0x6f, 0x73, 0x2e, 0x43, 0x68, 0x72, 0x6f, 0x6d, 0x65, 0x43, 0x6f,
+ 0x6d, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x6f, 0x72, 0x53, 0x74, 0x61, 0x74,
+ 0x65, 0x4d, 0x61, 0x63, 0x68, 0x69, 0x6e, 0x65, 0x2e, 0x4d, 0x61, 0x6a,
+ 0x6f, 0x72, 0x53, 0x74, 0x61, 0x74, 0x65, 0x2e, 0x4c, 0x61, 0x79, 0x65,
+ 0x72, 0x54, 0x72, 0x65, 0x65, 0x46, 0x72, 0x61, 0x6d, 0x65, 0x53, 0x69,
+ 0x6e, 0x6b, 0x53, 0x74, 0x61, 0x74, 0x65, 0x52, 0x17, 0x6c, 0x61, 0x79,
+ 0x65, 0x72, 0x54, 0x72, 0x65, 0x65, 0x46, 0x72, 0x61, 0x6d, 0x65, 0x53,
+ 0x69, 0x6e, 0x6b, 0x53, 0x74, 0x61, 0x74, 0x65, 0x12, 0x83, 0x01, 0x0a,
+ 0x13, 0x66, 0x6f, 0x72, 0x63, 0x65, 0x64, 0x5f, 0x72, 0x65, 0x64, 0x72,
+ 0x61, 0x77, 0x5f, 0x73, 0x74, 0x61, 0x74, 0x65, 0x18, 0x05, 0x20, 0x01,
+ 0x28, 0x0e, 0x32, 0x53, 0x2e, 0x70, 0x65, 0x72, 0x66, 0x65, 0x74, 0x74,
+ 0x6f, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2e, 0x43, 0x68, 0x72,
+ 0x6f, 0x6d, 0x65, 0x43, 0x6f, 0x6d, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x6f,
+ 0x72, 0x53, 0x74, 0x61, 0x74, 0x65, 0x4d, 0x61, 0x63, 0x68, 0x69, 0x6e,
+ 0x65, 0x2e, 0x4d, 0x61, 0x6a, 0x6f, 0x72, 0x53, 0x74, 0x61, 0x74, 0x65,
+ 0x2e, 0x46, 0x6f, 0x72, 0x63, 0x65, 0x64, 0x52, 0x65, 0x64, 0x72, 0x61,
+ 0x77, 0x4f, 0x6e, 0x54, 0x69, 0x6d, 0x65, 0x6f, 0x75, 0x74, 0x53, 0x74,
+ 0x61, 0x74, 0x65, 0x52, 0x11, 0x66, 0x6f, 0x72, 0x63, 0x65, 0x64, 0x52,
+ 0x65, 0x64, 0x72, 0x61, 0x77, 0x53, 0x74, 0x61, 0x74, 0x65, 0x22, 0xa1,
+ 0x01, 0x0a, 0x13, 0x42, 0x65, 0x67, 0x69, 0x6e, 0x49, 0x6d, 0x70, 0x6c,
+ 0x46, 0x72, 0x61, 0x6d, 0x65, 0x53, 0x74, 0x61, 0x74, 0x65, 0x12, 0x20,
+ 0x0a, 0x1c, 0x42, 0x45, 0x47, 0x49, 0x4e, 0x5f, 0x49, 0x4d, 0x50, 0x4c,
+ 0x5f, 0x46, 0x52, 0x41, 0x4d, 0x45, 0x5f, 0x55, 0x4e, 0x53, 0x50, 0x45,
+ 0x43, 0x49, 0x46, 0x49, 0x45, 0x44, 0x10, 0x00, 0x12, 0x19, 0x0a, 0x15,
+ 0x42, 0x45, 0x47, 0x49, 0x4e, 0x5f, 0x49, 0x4d, 0x50, 0x4c, 0x5f, 0x46,
+ 0x52, 0x41, 0x4d, 0x45, 0x5f, 0x49, 0x44, 0x4c, 0x45, 0x10, 0x01, 0x12,
+ 0x27, 0x0a, 0x23, 0x42, 0x45, 0x47, 0x49, 0x4e, 0x5f, 0x49, 0x4d, 0x50,
+ 0x4c, 0x5f, 0x46, 0x52, 0x41, 0x4d, 0x45, 0x5f, 0x49, 0x4e, 0x53, 0x49,
+ 0x44, 0x45, 0x5f, 0x42, 0x45, 0x47, 0x49, 0x4e, 0x5f, 0x46, 0x52, 0x41,
+ 0x4d, 0x45, 0x10, 0x02, 0x12, 0x24, 0x0a, 0x20, 0x42, 0x45, 0x47, 0x49,
+ 0x4e, 0x5f, 0x49, 0x4d, 0x50, 0x4c, 0x5f, 0x46, 0x52, 0x41, 0x4d, 0x45,
+ 0x5f, 0x49, 0x4e, 0x53, 0x49, 0x44, 0x45, 0x5f, 0x44, 0x45, 0x41, 0x44,
+ 0x4c, 0x49, 0x4e, 0x45, 0x10, 0x03, 0x22, 0x93, 0x01, 0x0a, 0x13, 0x42,
+ 0x65, 0x67, 0x69, 0x6e, 0x4d, 0x61, 0x69, 0x6e, 0x46, 0x72, 0x61, 0x6d,
+ 0x65, 0x53, 0x74, 0x61, 0x74, 0x65, 0x12, 0x20, 0x0a, 0x1c, 0x42, 0x45,
+ 0x47, 0x49, 0x4e, 0x5f, 0x4d, 0x41, 0x49, 0x4e, 0x5f, 0x46, 0x52, 0x41,
+ 0x4d, 0x45, 0x5f, 0x55, 0x4e, 0x53, 0x50, 0x45, 0x43, 0x49, 0x46, 0x49,
+ 0x45, 0x44, 0x10, 0x00, 0x12, 0x19, 0x0a, 0x15, 0x42, 0x45, 0x47, 0x49,
+ 0x4e, 0x5f, 0x4d, 0x41, 0x49, 0x4e, 0x5f, 0x46, 0x52, 0x41, 0x4d, 0x45,
+ 0x5f, 0x49, 0x44, 0x4c, 0x45, 0x10, 0x01, 0x12, 0x19, 0x0a, 0x15, 0x42,
+ 0x45, 0x47, 0x49, 0x4e, 0x5f, 0x4d, 0x41, 0x49, 0x4e, 0x5f, 0x46, 0x52,
+ 0x41, 0x4d, 0x45, 0x5f, 0x53, 0x45, 0x4e, 0x54, 0x10, 0x02, 0x12, 0x24,
+ 0x0a, 0x20, 0x42, 0x45, 0x47, 0x49, 0x4e, 0x5f, 0x4d, 0x41, 0x49, 0x4e,
+ 0x5f, 0x46, 0x52, 0x41, 0x4d, 0x45, 0x5f, 0x52, 0x45, 0x41, 0x44, 0x59,
+ 0x5f, 0x54, 0x4f, 0x5f, 0x43, 0x4f, 0x4d, 0x4d, 0x49, 0x54, 0x10, 0x03,
+ 0x22, 0xf4, 0x01, 0x0a, 0x17, 0x4c, 0x61, 0x79, 0x65, 0x72, 0x54, 0x72,
+ 0x65, 0x65, 0x46, 0x72, 0x61, 0x6d, 0x65, 0x53, 0x69, 0x6e, 0x6b, 0x53,
+ 0x74, 0x61, 0x74, 0x65, 0x12, 0x20, 0x0a, 0x1c, 0x4c, 0x41, 0x59, 0x45,
+ 0x52, 0x5f, 0x54, 0x52, 0x45, 0x45, 0x5f, 0x46, 0x52, 0x41, 0x4d, 0x45,
+ 0x5f, 0x55, 0x4e, 0x53, 0x50, 0x45, 0x43, 0x49, 0x46, 0x49, 0x45, 0x44,
+ 0x10, 0x00, 0x12, 0x19, 0x0a, 0x15, 0x4c, 0x41, 0x59, 0x45, 0x52, 0x5f,
+ 0x54, 0x52, 0x45, 0x45, 0x5f, 0x46, 0x52, 0x41, 0x4d, 0x45, 0x5f, 0x4e,
+ 0x4f, 0x4e, 0x45, 0x10, 0x01, 0x12, 0x1b, 0x0a, 0x17, 0x4c, 0x41, 0x59,
+ 0x45, 0x52, 0x5f, 0x54, 0x52, 0x45, 0x45, 0x5f, 0x46, 0x52, 0x41, 0x4d,
+ 0x45, 0x5f, 0x41, 0x43, 0x54, 0x49, 0x56, 0x45, 0x10, 0x02, 0x12, 0x1d,
+ 0x0a, 0x19, 0x4c, 0x41, 0x59, 0x45, 0x52, 0x5f, 0x54, 0x52, 0x45, 0x45,
+ 0x5f, 0x46, 0x52, 0x41, 0x4d, 0x45, 0x5f, 0x43, 0x52, 0x45, 0x41, 0x54,
+ 0x49, 0x4e, 0x47, 0x10, 0x03, 0x12, 0x2d, 0x0a, 0x29, 0x4c, 0x41, 0x59,
+ 0x45, 0x52, 0x5f, 0x54, 0x52, 0x45, 0x45, 0x5f, 0x46, 0x52, 0x41, 0x4d,
+ 0x45, 0x5f, 0x57, 0x41, 0x49, 0x54, 0x49, 0x4e, 0x47, 0x5f, 0x46, 0x4f,
+ 0x52, 0x5f, 0x46, 0x49, 0x52, 0x53, 0x54, 0x5f, 0x43, 0x4f, 0x4d, 0x4d,
+ 0x49, 0x54, 0x10, 0x04, 0x12, 0x31, 0x0a, 0x2d, 0x4c, 0x41, 0x59, 0x45,
+ 0x52, 0x5f, 0x54, 0x52, 0x45, 0x45, 0x5f, 0x46, 0x52, 0x41, 0x4d, 0x45,
+ 0x5f, 0x57, 0x41, 0x49, 0x54, 0x49, 0x4e, 0x47, 0x5f, 0x46, 0x4f, 0x52,
+ 0x5f, 0x46, 0x49, 0x52, 0x53, 0x54, 0x5f, 0x41, 0x43, 0x54, 0x49, 0x56,
+ 0x41, 0x54, 0x49, 0x4f, 0x4e, 0x10, 0x05, 0x22, 0xc7, 0x01, 0x0a, 0x1a,
+ 0x46, 0x6f, 0x72, 0x63, 0x65, 0x64, 0x52, 0x65, 0x64, 0x72, 0x61, 0x77,
+ 0x4f, 0x6e, 0x54, 0x69, 0x6d, 0x65, 0x6f, 0x75, 0x74, 0x53, 0x74, 0x61,
+ 0x74, 0x65, 0x12, 0x1d, 0x0a, 0x19, 0x46, 0x4f, 0x52, 0x43, 0x45, 0x44,
+ 0x5f, 0x52, 0x45, 0x44, 0x52, 0x41, 0x57, 0x5f, 0x55, 0x4e, 0x53, 0x50,
+ 0x45, 0x43, 0x49, 0x46, 0x49, 0x45, 0x44, 0x10, 0x00, 0x12, 0x16, 0x0a,
+ 0x12, 0x46, 0x4f, 0x52, 0x43, 0x45, 0x44, 0x5f, 0x52, 0x45, 0x44, 0x52,
+ 0x41, 0x57, 0x5f, 0x49, 0x44, 0x4c, 0x45, 0x10, 0x01, 0x12, 0x24, 0x0a,
+ 0x20, 0x46, 0x4f, 0x52, 0x43, 0x45, 0x44, 0x5f, 0x52, 0x45, 0x44, 0x52,
+ 0x41, 0x57, 0x5f, 0x57, 0x41, 0x49, 0x54, 0x49, 0x4e, 0x47, 0x5f, 0x46,
+ 0x4f, 0x52, 0x5f, 0x43, 0x4f, 0x4d, 0x4d, 0x49, 0x54, 0x10, 0x02, 0x12,
+ 0x28, 0x0a, 0x24, 0x46, 0x4f, 0x52, 0x43, 0x45, 0x44, 0x5f, 0x52, 0x45,
+ 0x44, 0x52, 0x41, 0x57, 0x5f, 0x57, 0x41, 0x49, 0x54, 0x49, 0x4e, 0x47,
+ 0x5f, 0x46, 0x4f, 0x52, 0x5f, 0x41, 0x43, 0x54, 0x49, 0x56, 0x41, 0x54,
+ 0x49, 0x4f, 0x4e, 0x10, 0x03, 0x12, 0x22, 0x0a, 0x1e, 0x46, 0x4f, 0x52,
+ 0x43, 0x45, 0x44, 0x5f, 0x52, 0x45, 0x44, 0x52, 0x41, 0x57, 0x5f, 0x57,
+ 0x41, 0x49, 0x54, 0x49, 0x4e, 0x47, 0x5f, 0x46, 0x4f, 0x52, 0x5f, 0x44,
+ 0x52, 0x41, 0x57, 0x10, 0x04, 0x1a, 0xb3, 0x1b, 0x0a, 0x0a, 0x4d, 0x69,
+ 0x6e, 0x6f, 0x72, 0x53, 0x74, 0x61, 0x74, 0x65, 0x12, 0x21, 0x0a, 0x0c,
+ 0x63, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x5f, 0x63, 0x6f, 0x75, 0x6e, 0x74,
+ 0x18, 0x01, 0x20, 0x01, 0x28, 0x05, 0x52, 0x0b, 0x63, 0x6f, 0x6d, 0x6d,
+ 0x69, 0x74, 0x43, 0x6f, 0x75, 0x6e, 0x74, 0x12, 0x30, 0x0a, 0x14, 0x63,
+ 0x75, 0x72, 0x72, 0x65, 0x6e, 0x74, 0x5f, 0x66, 0x72, 0x61, 0x6d, 0x65,
+ 0x5f, 0x6e, 0x75, 0x6d, 0x62, 0x65, 0x72, 0x18, 0x02, 0x20, 0x01, 0x28,
+ 0x05, 0x52, 0x12, 0x63, 0x75, 0x72, 0x72, 0x65, 0x6e, 0x74, 0x46, 0x72,
+ 0x61, 0x6d, 0x65, 0x4e, 0x75, 0x6d, 0x62, 0x65, 0x72, 0x12, 0x4a, 0x0a,
+ 0x22, 0x6c, 0x61, 0x73, 0x74, 0x5f, 0x66, 0x72, 0x61, 0x6d, 0x65, 0x5f,
+ 0x6e, 0x75, 0x6d, 0x62, 0x65, 0x72, 0x5f, 0x73, 0x75, 0x62, 0x6d, 0x69,
+ 0x74, 0x5f, 0x70, 0x65, 0x72, 0x66, 0x6f, 0x72, 0x6d, 0x65, 0x64, 0x18,
+ 0x03, 0x20, 0x01, 0x28, 0x05, 0x52, 0x1e, 0x6c, 0x61, 0x73, 0x74, 0x46,
+ 0x72, 0x61, 0x6d, 0x65, 0x4e, 0x75, 0x6d, 0x62, 0x65, 0x72, 0x53, 0x75,
+ 0x62, 0x6d, 0x69, 0x74, 0x50, 0x65, 0x72, 0x66, 0x6f, 0x72, 0x6d, 0x65,
+ 0x64, 0x12, 0x46, 0x0a, 0x20, 0x6c, 0x61, 0x73, 0x74, 0x5f, 0x66, 0x72,
+ 0x61, 0x6d, 0x65, 0x5f, 0x6e, 0x75, 0x6d, 0x62, 0x65, 0x72, 0x5f, 0x64,
+ 0x72, 0x61, 0x77, 0x5f, 0x70, 0x65, 0x72, 0x66, 0x6f, 0x72, 0x6d, 0x65,
+ 0x64, 0x18, 0x04, 0x20, 0x01, 0x28, 0x05, 0x52, 0x1c, 0x6c, 0x61, 0x73,
+ 0x74, 0x46, 0x72, 0x61, 0x6d, 0x65, 0x4e, 0x75, 0x6d, 0x62, 0x65, 0x72,
+ 0x44, 0x72, 0x61, 0x77, 0x50, 0x65, 0x72, 0x66, 0x6f, 0x72, 0x6d, 0x65,
+ 0x64, 0x12, 0x52, 0x0a, 0x27, 0x6c, 0x61, 0x73, 0x74, 0x5f, 0x66, 0x72,
+ 0x61, 0x6d, 0x65, 0x5f, 0x6e, 0x75, 0x6d, 0x62, 0x65, 0x72, 0x5f, 0x62,
+ 0x65, 0x67, 0x69, 0x6e, 0x5f, 0x6d, 0x61, 0x69, 0x6e, 0x5f, 0x66, 0x72,
+ 0x61, 0x6d, 0x65, 0x5f, 0x73, 0x65, 0x6e, 0x74, 0x18, 0x05, 0x20, 0x01,
+ 0x28, 0x05, 0x52, 0x21, 0x6c, 0x61, 0x73, 0x74, 0x46, 0x72, 0x61, 0x6d,
+ 0x65, 0x4e, 0x75, 0x6d, 0x62, 0x65, 0x72, 0x42, 0x65, 0x67, 0x69, 0x6e,
+ 0x4d, 0x61, 0x69, 0x6e, 0x46, 0x72, 0x61, 0x6d, 0x65, 0x53, 0x65, 0x6e,
+ 0x74, 0x12, 0x19, 0x0a, 0x08, 0x64, 0x69, 0x64, 0x5f, 0x64, 0x72, 0x61,
+ 0x77, 0x18, 0x06, 0x20, 0x01, 0x28, 0x08, 0x52, 0x07, 0x64, 0x69, 0x64,
+ 0x44, 0x72, 0x61, 0x77, 0x12, 0x59, 0x0a, 0x2b, 0x64, 0x69, 0x64, 0x5f,
+ 0x73, 0x65, 0x6e, 0x64, 0x5f, 0x62, 0x65, 0x67, 0x69, 0x6e, 0x5f, 0x6d,
+ 0x61, 0x69, 0x6e, 0x5f, 0x66, 0x72, 0x61, 0x6d, 0x65, 0x5f, 0x66, 0x6f,
+ 0x72, 0x5f, 0x63, 0x75, 0x72, 0x72, 0x65, 0x6e, 0x74, 0x5f, 0x66, 0x72,
+ 0x61, 0x6d, 0x65, 0x18, 0x07, 0x20, 0x01, 0x28, 0x08, 0x52, 0x24, 0x64,
+ 0x69, 0x64, 0x53, 0x65, 0x6e, 0x64, 0x42, 0x65, 0x67, 0x69, 0x6e, 0x4d,
+ 0x61, 0x69, 0x6e, 0x46, 0x72, 0x61, 0x6d, 0x65, 0x46, 0x6f, 0x72, 0x43,
+ 0x75, 0x72, 0x72, 0x65, 0x6e, 0x74, 0x46, 0x72, 0x61, 0x6d, 0x65, 0x12,
+ 0x5f, 0x0a, 0x2e, 0x64, 0x69, 0x64, 0x5f, 0x6e, 0x6f, 0x74, 0x69, 0x66,
+ 0x79, 0x5f, 0x62, 0x65, 0x67, 0x69, 0x6e, 0x5f, 0x6d, 0x61, 0x69, 0x6e,
+ 0x5f, 0x66, 0x72, 0x61, 0x6d, 0x65, 0x5f, 0x6e, 0x6f, 0x74, 0x5f, 0x65,
+ 0x78, 0x70, 0x65, 0x63, 0x74, 0x65, 0x64, 0x5f, 0x75, 0x6e, 0x74, 0x69,
+ 0x6c, 0x18, 0x08, 0x20, 0x01, 0x28, 0x08, 0x52, 0x27, 0x64, 0x69, 0x64,
+ 0x4e, 0x6f, 0x74, 0x69, 0x66, 0x79, 0x42, 0x65, 0x67, 0x69, 0x6e, 0x4d,
+ 0x61, 0x69, 0x6e, 0x46, 0x72, 0x61, 0x6d, 0x65, 0x4e, 0x6f, 0x74, 0x45,
+ 0x78, 0x70, 0x65, 0x63, 0x74, 0x65, 0x64, 0x55, 0x6e, 0x74, 0x69, 0x6c,
+ 0x12, 0x5d, 0x0a, 0x2d, 0x64, 0x69, 0x64, 0x5f, 0x6e, 0x6f, 0x74, 0x69,
+ 0x66, 0x79, 0x5f, 0x62, 0x65, 0x67, 0x69, 0x6e, 0x5f, 0x6d, 0x61, 0x69,
+ 0x6e, 0x5f, 0x66, 0x72, 0x61, 0x6d, 0x65, 0x5f, 0x6e, 0x6f, 0x74, 0x5f,
+ 0x65, 0x78, 0x70, 0x65, 0x63, 0x74, 0x65, 0x64, 0x5f, 0x73, 0x6f, 0x6f,
+ 0x6e, 0x18, 0x09, 0x20, 0x01, 0x28, 0x08, 0x52, 0x26, 0x64, 0x69, 0x64,
+ 0x4e, 0x6f, 0x74, 0x69, 0x66, 0x79, 0x42, 0x65, 0x67, 0x69, 0x6e, 0x4d,
+ 0x61, 0x69, 0x6e, 0x46, 0x72, 0x61, 0x6d, 0x65, 0x4e, 0x6f, 0x74, 0x45,
+ 0x78, 0x70, 0x65, 0x63, 0x74, 0x65, 0x64, 0x53, 0x6f, 0x6f, 0x6e, 0x12,
+ 0x4b, 0x0a, 0x23, 0x77, 0x61, 0x6e, 0x74, 0x73, 0x5f, 0x62, 0x65, 0x67,
+ 0x69, 0x6e, 0x5f, 0x6d, 0x61, 0x69, 0x6e, 0x5f, 0x66, 0x72, 0x61, 0x6d,
+ 0x65, 0x5f, 0x6e, 0x6f, 0x74, 0x5f, 0x65, 0x78, 0x70, 0x65, 0x63, 0x74,
+ 0x65, 0x64, 0x18, 0x0a, 0x20, 0x01, 0x28, 0x08, 0x52, 0x1e, 0x77, 0x61,
+ 0x6e, 0x74, 0x73, 0x42, 0x65, 0x67, 0x69, 0x6e, 0x4d, 0x61, 0x69, 0x6e,
+ 0x46, 0x72, 0x61, 0x6d, 0x65, 0x4e, 0x6f, 0x74, 0x45, 0x78, 0x70, 0x65,
+ 0x63, 0x74, 0x65, 0x64, 0x12, 0x35, 0x0a, 0x17, 0x64, 0x69, 0x64, 0x5f,
+ 0x63, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x5f, 0x64, 0x75, 0x72, 0x69, 0x6e,
+ 0x67, 0x5f, 0x66, 0x72, 0x61, 0x6d, 0x65, 0x18, 0x0b, 0x20, 0x01, 0x28,
+ 0x08, 0x52, 0x14, 0x64, 0x69, 0x64, 0x43, 0x6f, 0x6d, 0x6d, 0x69, 0x74,
+ 0x44, 0x75, 0x72, 0x69, 0x6e, 0x67, 0x46, 0x72, 0x61, 0x6d, 0x65, 0x12,
+ 0x4d, 0x0a, 0x24, 0x64, 0x69, 0x64, 0x5f, 0x69, 0x6e, 0x76, 0x61, 0x6c,
+ 0x69, 0x64, 0x61, 0x74, 0x65, 0x5f, 0x6c, 0x61, 0x79, 0x65, 0x72, 0x5f,
+ 0x74, 0x72, 0x65, 0x65, 0x5f, 0x66, 0x72, 0x61, 0x6d, 0x65, 0x5f, 0x73,
+ 0x69, 0x6e, 0x6b, 0x18, 0x0c, 0x20, 0x01, 0x28, 0x08, 0x52, 0x1f, 0x64,
+ 0x69, 0x64, 0x49, 0x6e, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x65,
+ 0x4c, 0x61, 0x79, 0x65, 0x72, 0x54, 0x72, 0x65, 0x65, 0x46, 0x72, 0x61,
+ 0x6d, 0x65, 0x53, 0x69, 0x6e, 0x6b, 0x12, 0x48, 0x0a, 0x21, 0x64, 0x69,
+ 0x64, 0x5f, 0x70, 0x65, 0x72, 0x66, 0x6f, 0x72, 0x6d, 0x5f, 0x69, 0x6d,
+ 0x70, 0x6c, 0x5f, 0x73, 0x69, 0x64, 0x65, 0x5f, 0x69, 0x6e, 0x76, 0x61,
+ 0x6c, 0x69, 0x64, 0x61, 0x69, 0x6f, 0x6e, 0x18, 0x0d, 0x20, 0x01, 0x28,
+ 0x08, 0x52, 0x1d, 0x64, 0x69, 0x64, 0x50, 0x65, 0x72, 0x66, 0x6f, 0x72,
+ 0x6d, 0x49, 0x6d, 0x70, 0x6c, 0x53, 0x69, 0x64, 0x65, 0x49, 0x6e, 0x76,
+ 0x61, 0x6c, 0x69, 0x64, 0x61, 0x69, 0x6f, 0x6e, 0x12, 0x2a, 0x0a, 0x11,
+ 0x64, 0x69, 0x64, 0x5f, 0x70, 0x72, 0x65, 0x70, 0x61, 0x72, 0x65, 0x5f,
+ 0x74, 0x69, 0x6c, 0x65, 0x73, 0x18, 0x0e, 0x20, 0x01, 0x28, 0x08, 0x52,
+ 0x0f, 0x64, 0x69, 0x64, 0x50, 0x72, 0x65, 0x70, 0x61, 0x72, 0x65, 0x54,
+ 0x69, 0x6c, 0x65, 0x73, 0x12, 0x4e, 0x0a, 0x23, 0x63, 0x6f, 0x6e, 0x73,
+ 0x65, 0x63, 0x75, 0x74, 0x69, 0x76, 0x65, 0x5f, 0x63, 0x68, 0x65, 0x63,
+ 0x6b, 0x65, 0x72, 0x62, 0x6f, 0x61, 0x72, 0x64, 0x5f, 0x61, 0x6e, 0x69,
+ 0x6d, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x18, 0x0f, 0x20, 0x01, 0x28,
+ 0x05, 0x52, 0x21, 0x63, 0x6f, 0x6e, 0x73, 0x65, 0x63, 0x75, 0x74, 0x69,
+ 0x76, 0x65, 0x43, 0x68, 0x65, 0x63, 0x6b, 0x65, 0x72, 0x62, 0x6f, 0x61,
+ 0x72, 0x64, 0x41, 0x6e, 0x69, 0x6d, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73,
+ 0x12, 0x32, 0x0a, 0x15, 0x70, 0x65, 0x6e, 0x64, 0x69, 0x6e, 0x67, 0x5f,
+ 0x73, 0x75, 0x62, 0x6d, 0x69, 0x74, 0x5f, 0x66, 0x72, 0x61, 0x6d, 0x65,
+ 0x73, 0x18, 0x10, 0x20, 0x01, 0x28, 0x05, 0x52, 0x13, 0x70, 0x65, 0x6e,
+ 0x64, 0x69, 0x6e, 0x67, 0x53, 0x75, 0x62, 0x6d, 0x69, 0x74, 0x46, 0x72,
+ 0x61, 0x6d, 0x65, 0x73, 0x12, 0x63, 0x0a, 0x30, 0x73, 0x75, 0x62, 0x6d,
+ 0x69, 0x74, 0x5f, 0x66, 0x72, 0x61, 0x6d, 0x65, 0x73, 0x5f, 0x77, 0x69,
+ 0x74, 0x68, 0x5f, 0x63, 0x75, 0x72, 0x72, 0x65, 0x6e, 0x74, 0x5f, 0x6c,
+ 0x61, 0x79, 0x65, 0x72, 0x5f, 0x74, 0x72, 0x65, 0x65, 0x5f, 0x66, 0x72,
+ 0x61, 0x6d, 0x65, 0x5f, 0x73, 0x69, 0x6e, 0x6b, 0x18, 0x11, 0x20, 0x01,
+ 0x28, 0x05, 0x52, 0x29, 0x73, 0x75, 0x62, 0x6d, 0x69, 0x74, 0x46, 0x72,
+ 0x61, 0x6d, 0x65, 0x73, 0x57, 0x69, 0x74, 0x68, 0x43, 0x75, 0x72, 0x72,
+ 0x65, 0x6e, 0x74, 0x4c, 0x61, 0x79, 0x65, 0x72, 0x54, 0x72, 0x65, 0x65,
+ 0x46, 0x72, 0x61, 0x6d, 0x65, 0x53, 0x69, 0x6e, 0x6b, 0x12, 0x21, 0x0a,
+ 0x0c, 0x6e, 0x65, 0x65, 0x64, 0x73, 0x5f, 0x72, 0x65, 0x64, 0x72, 0x61,
+ 0x77, 0x18, 0x12, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0b, 0x6e, 0x65, 0x65,
+ 0x64, 0x73, 0x52, 0x65, 0x64, 0x72, 0x61, 0x77, 0x12, 0x2e, 0x0a, 0x13,
+ 0x6e, 0x65, 0x65, 0x64, 0x73, 0x5f, 0x70, 0x72, 0x65, 0x70, 0x61, 0x72,
+ 0x65, 0x5f, 0x74, 0x69, 0x6c, 0x65, 0x73, 0x18, 0x13, 0x20, 0x01, 0x28,
+ 0x08, 0x52, 0x11, 0x6e, 0x65, 0x65, 0x64, 0x73, 0x50, 0x72, 0x65, 0x70,
+ 0x61, 0x72, 0x65, 0x54, 0x69, 0x6c, 0x65, 0x73, 0x12, 0x33, 0x0a, 0x16,
+ 0x6e, 0x65, 0x65, 0x64, 0x73, 0x5f, 0x62, 0x65, 0x67, 0x69, 0x6e, 0x5f,
+ 0x6d, 0x61, 0x69, 0x6e, 0x5f, 0x66, 0x72, 0x61, 0x6d, 0x65, 0x18, 0x14,
+ 0x20, 0x01, 0x28, 0x08, 0x52, 0x13, 0x6e, 0x65, 0x65, 0x64, 0x73, 0x42,
+ 0x65, 0x67, 0x69, 0x6e, 0x4d, 0x61, 0x69, 0x6e, 0x46, 0x72, 0x61, 0x6d,
+ 0x65, 0x12, 0x3a, 0x0a, 0x1a, 0x6e, 0x65, 0x65, 0x64, 0x73, 0x5f, 0x6f,
+ 0x6e, 0x65, 0x5f, 0x62, 0x65, 0x67, 0x69, 0x6e, 0x5f, 0x69, 0x6d, 0x70,
+ 0x6c, 0x5f, 0x66, 0x72, 0x61, 0x6d, 0x65, 0x18, 0x15, 0x20, 0x01, 0x28,
+ 0x08, 0x52, 0x16, 0x6e, 0x65, 0x65, 0x64, 0x73, 0x4f, 0x6e, 0x65, 0x42,
+ 0x65, 0x67, 0x69, 0x6e, 0x49, 0x6d, 0x70, 0x6c, 0x46, 0x72, 0x61, 0x6d,
+ 0x65, 0x12, 0x18, 0x0a, 0x07, 0x76, 0x69, 0x73, 0x69, 0x62, 0x6c, 0x65,
+ 0x18, 0x16, 0x20, 0x01, 0x28, 0x08, 0x52, 0x07, 0x76, 0x69, 0x73, 0x69,
+ 0x62, 0x6c, 0x65, 0x12, 0x39, 0x0a, 0x19, 0x62, 0x65, 0x67, 0x69, 0x6e,
+ 0x5f, 0x66, 0x72, 0x61, 0x6d, 0x65, 0x5f, 0x73, 0x6f, 0x75, 0x72, 0x63,
+ 0x65, 0x5f, 0x70, 0x61, 0x75, 0x73, 0x65, 0x64, 0x18, 0x17, 0x20, 0x01,
+ 0x28, 0x08, 0x52, 0x16, 0x62, 0x65, 0x67, 0x69, 0x6e, 0x46, 0x72, 0x61,
+ 0x6d, 0x65, 0x53, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x50, 0x61, 0x75, 0x73,
+ 0x65, 0x64, 0x12, 0x19, 0x0a, 0x08, 0x63, 0x61, 0x6e, 0x5f, 0x64, 0x72,
+ 0x61, 0x77, 0x18, 0x18, 0x20, 0x01, 0x28, 0x08, 0x52, 0x07, 0x63, 0x61,
+ 0x6e, 0x44, 0x72, 0x61, 0x77, 0x12, 0x2b, 0x0a, 0x11, 0x72, 0x65, 0x73,
+ 0x6f, 0x75, 0x72, 0x63, 0x65, 0x6c, 0x65, 0x73, 0x73, 0x5f, 0x64, 0x72,
+ 0x61, 0x77, 0x18, 0x19, 0x20, 0x01, 0x28, 0x08, 0x52, 0x10, 0x72, 0x65,
+ 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x6c, 0x65, 0x73, 0x73, 0x44, 0x72,
+ 0x61, 0x77, 0x12, 0x28, 0x0a, 0x10, 0x68, 0x61, 0x73, 0x5f, 0x70, 0x65,
+ 0x6e, 0x64, 0x69, 0x6e, 0x67, 0x5f, 0x74, 0x72, 0x65, 0x65, 0x18, 0x1a,
+ 0x20, 0x01, 0x28, 0x08, 0x52, 0x0e, 0x68, 0x61, 0x73, 0x50, 0x65, 0x6e,
+ 0x64, 0x69, 0x6e, 0x67, 0x54, 0x72, 0x65, 0x65, 0x12, 0x4d, 0x0a, 0x24,
+ 0x70, 0x65, 0x6e, 0x64, 0x69, 0x6e, 0x67, 0x5f, 0x74, 0x72, 0x65, 0x65,
+ 0x5f, 0x69, 0x73, 0x5f, 0x72, 0x65, 0x61, 0x64, 0x79, 0x5f, 0x66, 0x6f,
+ 0x72, 0x5f, 0x61, 0x63, 0x74, 0x69, 0x76, 0x61, 0x74, 0x69, 0x6f, 0x6e,
+ 0x18, 0x1b, 0x20, 0x01, 0x28, 0x08, 0x52, 0x1f, 0x70, 0x65, 0x6e, 0x64,
+ 0x69, 0x6e, 0x67, 0x54, 0x72, 0x65, 0x65, 0x49, 0x73, 0x52, 0x65, 0x61,
+ 0x64, 0x79, 0x46, 0x6f, 0x72, 0x41, 0x63, 0x74, 0x69, 0x76, 0x61, 0x74,
+ 0x69, 0x6f, 0x6e, 0x12, 0x3e, 0x0a, 0x1c, 0x61, 0x63, 0x74, 0x69, 0x76,
+ 0x65, 0x5f, 0x74, 0x72, 0x65, 0x65, 0x5f, 0x6e, 0x65, 0x65, 0x64, 0x73,
+ 0x5f, 0x66, 0x69, 0x72, 0x73, 0x74, 0x5f, 0x64, 0x72, 0x61, 0x77, 0x18,
+ 0x1c, 0x20, 0x01, 0x28, 0x08, 0x52, 0x18, 0x61, 0x63, 0x74, 0x69, 0x76,
+ 0x65, 0x54, 0x72, 0x65, 0x65, 0x4e, 0x65, 0x65, 0x64, 0x73, 0x46, 0x69,
+ 0x72, 0x73, 0x74, 0x44, 0x72, 0x61, 0x77, 0x12, 0x3d, 0x0a, 0x1c, 0x61,
+ 0x63, 0x74, 0x69, 0x76, 0x65, 0x5f, 0x74, 0x72, 0x65, 0x65, 0x5f, 0x69,
+ 0x73, 0x5f, 0x72, 0x65, 0x61, 0x64, 0x79, 0x5f, 0x74, 0x6f, 0x5f, 0x64,
+ 0x72, 0x61, 0x77, 0x18, 0x1d, 0x20, 0x01, 0x28, 0x08, 0x52, 0x17, 0x61,
+ 0x63, 0x74, 0x69, 0x76, 0x65, 0x54, 0x72, 0x65, 0x65, 0x49, 0x73, 0x52,
+ 0x65, 0x61, 0x64, 0x79, 0x54, 0x6f, 0x44, 0x72, 0x61, 0x77, 0x12, 0x6c,
+ 0x0a, 0x35, 0x64, 0x69, 0x64, 0x5f, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65,
+ 0x5f, 0x61, 0x6e, 0x64, 0x5f, 0x69, 0x6e, 0x69, 0x74, 0x69, 0x61, 0x6c,
+ 0x69, 0x7a, 0x65, 0x5f, 0x66, 0x69, 0x72, 0x73, 0x74, 0x5f, 0x6c, 0x61,
+ 0x79, 0x65, 0x72, 0x5f, 0x74, 0x72, 0x65, 0x65, 0x5f, 0x66, 0x72, 0x61,
+ 0x6d, 0x65, 0x5f, 0x73, 0x69, 0x6e, 0x6b, 0x18, 0x1e, 0x20, 0x01, 0x28,
+ 0x08, 0x52, 0x2d, 0x64, 0x69, 0x64, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65,
+ 0x41, 0x6e, 0x64, 0x49, 0x6e, 0x69, 0x74, 0x69, 0x61, 0x6c, 0x69, 0x7a,
+ 0x65, 0x46, 0x69, 0x72, 0x73, 0x74, 0x4c, 0x61, 0x79, 0x65, 0x72, 0x54,
+ 0x72, 0x65, 0x65, 0x46, 0x72, 0x61, 0x6d, 0x65, 0x53, 0x69, 0x6e, 0x6b,
+ 0x12, 0x6a, 0x0a, 0x0d, 0x74, 0x72, 0x65, 0x65, 0x5f, 0x70, 0x72, 0x69,
+ 0x6f, 0x72, 0x69, 0x74, 0x79, 0x18, 0x1f, 0x20, 0x01, 0x28, 0x0e, 0x32,
+ 0x45, 0x2e, 0x70, 0x65, 0x72, 0x66, 0x65, 0x74, 0x74, 0x6f, 0x2e, 0x70,
0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2e, 0x43, 0x68, 0x72, 0x6f, 0x6d, 0x65,
0x43, 0x6f, 0x6d, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x6f, 0x72, 0x53, 0x74,
0x61, 0x74, 0x65, 0x4d, 0x61, 0x63, 0x68, 0x69, 0x6e, 0x65, 0x2e, 0x4d,
- 0x69, 0x6e, 0x6f, 0x72, 0x53, 0x74, 0x61, 0x74, 0x65, 0x52, 0x0a, 0x6d,
- 0x69, 0x6e, 0x6f, 0x72, 0x53, 0x74, 0x61, 0x74, 0x65, 0x1a, 0xf9, 0x0a,
- 0x0a, 0x0a, 0x4d, 0x61, 0x6a, 0x6f, 0x72, 0x53, 0x74, 0x61, 0x74, 0x65,
- 0x12, 0x51, 0x0a, 0x0b, 0x6e, 0x65, 0x78, 0x74, 0x5f, 0x61, 0x63, 0x74,
- 0x69, 0x6f, 0x6e, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x30, 0x2e,
- 0x70, 0x65, 0x72, 0x66, 0x65, 0x74, 0x74, 0x6f, 0x2e, 0x70, 0x72, 0x6f,
- 0x74, 0x6f, 0x73, 0x2e, 0x43, 0x68, 0x72, 0x6f, 0x6d, 0x65, 0x43, 0x6f,
- 0x6d, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x6f, 0x72, 0x53, 0x63, 0x68, 0x65,
- 0x64, 0x75, 0x6c, 0x65, 0x72, 0x41, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x52,
- 0x0a, 0x6e, 0x65, 0x78, 0x74, 0x41, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x12,
- 0x81, 0x01, 0x0a, 0x16, 0x62, 0x65, 0x67, 0x69, 0x6e, 0x5f, 0x69, 0x6d,
- 0x70, 0x6c, 0x5f, 0x66, 0x72, 0x61, 0x6d, 0x65, 0x5f, 0x73, 0x74, 0x61,
- 0x74, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x4c, 0x2e, 0x70,
- 0x65, 0x72, 0x66, 0x65, 0x74, 0x74, 0x6f, 0x2e, 0x70, 0x72, 0x6f, 0x74,
- 0x6f, 0x73, 0x2e, 0x43, 0x68, 0x72, 0x6f, 0x6d, 0x65, 0x43, 0x6f, 0x6d,
- 0x70, 0x6f, 0x73, 0x69, 0x74, 0x6f, 0x72, 0x53, 0x74, 0x61, 0x74, 0x65,
- 0x4d, 0x61, 0x63, 0x68, 0x69, 0x6e, 0x65, 0x2e, 0x4d, 0x61, 0x6a, 0x6f,
- 0x72, 0x53, 0x74, 0x61, 0x74, 0x65, 0x2e, 0x42, 0x65, 0x67, 0x69, 0x6e,
- 0x49, 0x6d, 0x70, 0x6c, 0x46, 0x72, 0x61, 0x6d, 0x65, 0x53, 0x74, 0x61,
- 0x74, 0x65, 0x52, 0x13, 0x62, 0x65, 0x67, 0x69, 0x6e, 0x49, 0x6d, 0x70,
- 0x6c, 0x46, 0x72, 0x61, 0x6d, 0x65, 0x53, 0x74, 0x61, 0x74, 0x65, 0x12,
- 0x81, 0x01, 0x0a, 0x16, 0x62, 0x65, 0x67, 0x69, 0x6e, 0x5f, 0x6d, 0x61,
- 0x69, 0x6e, 0x5f, 0x66, 0x72, 0x61, 0x6d, 0x65, 0x5f, 0x73, 0x74, 0x61,
- 0x74, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x4c, 0x2e, 0x70,
- 0x65, 0x72, 0x66, 0x65, 0x74, 0x74, 0x6f, 0x2e, 0x70, 0x72, 0x6f, 0x74,
- 0x6f, 0x73, 0x2e, 0x43, 0x68, 0x72, 0x6f, 0x6d, 0x65, 0x43, 0x6f, 0x6d,
- 0x70, 0x6f, 0x73, 0x69, 0x74, 0x6f, 0x72, 0x53, 0x74, 0x61, 0x74, 0x65,
- 0x4d, 0x61, 0x63, 0x68, 0x69, 0x6e, 0x65, 0x2e, 0x4d, 0x61, 0x6a, 0x6f,
- 0x72, 0x53, 0x74, 0x61, 0x74, 0x65, 0x2e, 0x42, 0x65, 0x67, 0x69, 0x6e,
- 0x4d, 0x61, 0x69, 0x6e, 0x46, 0x72, 0x61, 0x6d, 0x65, 0x53, 0x74, 0x61,
- 0x74, 0x65, 0x52, 0x13, 0x62, 0x65, 0x67, 0x69, 0x6e, 0x4d, 0x61, 0x69,
- 0x6e, 0x46, 0x72, 0x61, 0x6d, 0x65, 0x53, 0x74, 0x61, 0x74, 0x65, 0x12,
- 0x8e, 0x01, 0x0a, 0x1b, 0x6c, 0x61, 0x79, 0x65, 0x72, 0x5f, 0x74, 0x72,
- 0x65, 0x65, 0x5f, 0x66, 0x72, 0x61, 0x6d, 0x65, 0x5f, 0x73, 0x69, 0x6e,
- 0x6b, 0x5f, 0x73, 0x74, 0x61, 0x74, 0x65, 0x18, 0x04, 0x20, 0x01, 0x28,
- 0x0e, 0x32, 0x50, 0x2e, 0x70, 0x65, 0x72, 0x66, 0x65, 0x74, 0x74, 0x6f,
- 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2e, 0x43, 0x68, 0x72, 0x6f,
- 0x6d, 0x65, 0x43, 0x6f, 0x6d, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x6f, 0x72,
- 0x53, 0x74, 0x61, 0x74, 0x65, 0x4d, 0x61, 0x63, 0x68, 0x69, 0x6e, 0x65,
- 0x2e, 0x4d, 0x61, 0x6a, 0x6f, 0x72, 0x53, 0x74, 0x61, 0x74, 0x65, 0x2e,
- 0x4c, 0x61, 0x79, 0x65, 0x72, 0x54, 0x72, 0x65, 0x65, 0x46, 0x72, 0x61,
- 0x6d, 0x65, 0x53, 0x69, 0x6e, 0x6b, 0x53, 0x74, 0x61, 0x74, 0x65, 0x52,
- 0x17, 0x6c, 0x61, 0x79, 0x65, 0x72, 0x54, 0x72, 0x65, 0x65, 0x46, 0x72,
- 0x61, 0x6d, 0x65, 0x53, 0x69, 0x6e, 0x6b, 0x53, 0x74, 0x61, 0x74, 0x65,
- 0x12, 0x83, 0x01, 0x0a, 0x13, 0x66, 0x6f, 0x72, 0x63, 0x65, 0x64, 0x5f,
- 0x72, 0x65, 0x64, 0x72, 0x61, 0x77, 0x5f, 0x73, 0x74, 0x61, 0x74, 0x65,
- 0x18, 0x05, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x53, 0x2e, 0x70, 0x65, 0x72,
+ 0x69, 0x6e, 0x6f, 0x72, 0x53, 0x74, 0x61, 0x74, 0x65, 0x2e, 0x54, 0x72,
+ 0x65, 0x65, 0x50, 0x72, 0x69, 0x6f, 0x72, 0x69, 0x74, 0x79, 0x52, 0x0c,
+ 0x74, 0x72, 0x65, 0x65, 0x50, 0x72, 0x69, 0x6f, 0x72, 0x69, 0x74, 0x79,
+ 0x12, 0x7d, 0x0a, 0x14, 0x73, 0x63, 0x72, 0x6f, 0x6c, 0x6c, 0x5f, 0x68,
+ 0x61, 0x6e, 0x64, 0x6c, 0x65, 0x72, 0x5f, 0x73, 0x74, 0x61, 0x74, 0x65,
+ 0x18, 0x20, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x4b, 0x2e, 0x70, 0x65, 0x72,
0x66, 0x65, 0x74, 0x74, 0x6f, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73,
0x2e, 0x43, 0x68, 0x72, 0x6f, 0x6d, 0x65, 0x43, 0x6f, 0x6d, 0x70, 0x6f,
0x73, 0x69, 0x74, 0x6f, 0x72, 0x53, 0x74, 0x61, 0x74, 0x65, 0x4d, 0x61,
- 0x63, 0x68, 0x69, 0x6e, 0x65, 0x2e, 0x4d, 0x61, 0x6a, 0x6f, 0x72, 0x53,
- 0x74, 0x61, 0x74, 0x65, 0x2e, 0x46, 0x6f, 0x72, 0x63, 0x65, 0x64, 0x52,
- 0x65, 0x64, 0x72, 0x61, 0x77, 0x4f, 0x6e, 0x54, 0x69, 0x6d, 0x65, 0x6f,
- 0x75, 0x74, 0x53, 0x74, 0x61, 0x74, 0x65, 0x52, 0x11, 0x66, 0x6f, 0x72,
- 0x63, 0x65, 0x64, 0x52, 0x65, 0x64, 0x72, 0x61, 0x77, 0x53, 0x74, 0x61,
- 0x74, 0x65, 0x22, 0xa1, 0x01, 0x0a, 0x13, 0x42, 0x65, 0x67, 0x69, 0x6e,
- 0x49, 0x6d, 0x70, 0x6c, 0x46, 0x72, 0x61, 0x6d, 0x65, 0x53, 0x74, 0x61,
- 0x74, 0x65, 0x12, 0x20, 0x0a, 0x1c, 0x42, 0x45, 0x47, 0x49, 0x4e, 0x5f,
- 0x49, 0x4d, 0x50, 0x4c, 0x5f, 0x46, 0x52, 0x41, 0x4d, 0x45, 0x5f, 0x55,
- 0x4e, 0x53, 0x50, 0x45, 0x43, 0x49, 0x46, 0x49, 0x45, 0x44, 0x10, 0x00,
- 0x12, 0x19, 0x0a, 0x15, 0x42, 0x45, 0x47, 0x49, 0x4e, 0x5f, 0x49, 0x4d,
- 0x50, 0x4c, 0x5f, 0x46, 0x52, 0x41, 0x4d, 0x45, 0x5f, 0x49, 0x44, 0x4c,
- 0x45, 0x10, 0x01, 0x12, 0x27, 0x0a, 0x23, 0x42, 0x45, 0x47, 0x49, 0x4e,
- 0x5f, 0x49, 0x4d, 0x50, 0x4c, 0x5f, 0x46, 0x52, 0x41, 0x4d, 0x45, 0x5f,
- 0x49, 0x4e, 0x53, 0x49, 0x44, 0x45, 0x5f, 0x42, 0x45, 0x47, 0x49, 0x4e,
- 0x5f, 0x46, 0x52, 0x41, 0x4d, 0x45, 0x10, 0x02, 0x12, 0x24, 0x0a, 0x20,
- 0x42, 0x45, 0x47, 0x49, 0x4e, 0x5f, 0x49, 0x4d, 0x50, 0x4c, 0x5f, 0x46,
- 0x52, 0x41, 0x4d, 0x45, 0x5f, 0x49, 0x4e, 0x53, 0x49, 0x44, 0x45, 0x5f,
- 0x44, 0x45, 0x41, 0x44, 0x4c, 0x49, 0x4e, 0x45, 0x10, 0x03, 0x22, 0x93,
- 0x01, 0x0a, 0x13, 0x42, 0x65, 0x67, 0x69, 0x6e, 0x4d, 0x61, 0x69, 0x6e,
- 0x46, 0x72, 0x61, 0x6d, 0x65, 0x53, 0x74, 0x61, 0x74, 0x65, 0x12, 0x20,
- 0x0a, 0x1c, 0x42, 0x45, 0x47, 0x49, 0x4e, 0x5f, 0x4d, 0x41, 0x49, 0x4e,
- 0x5f, 0x46, 0x52, 0x41, 0x4d, 0x45, 0x5f, 0x55, 0x4e, 0x53, 0x50, 0x45,
- 0x43, 0x49, 0x46, 0x49, 0x45, 0x44, 0x10, 0x00, 0x12, 0x19, 0x0a, 0x15,
- 0x42, 0x45, 0x47, 0x49, 0x4e, 0x5f, 0x4d, 0x41, 0x49, 0x4e, 0x5f, 0x46,
- 0x52, 0x41, 0x4d, 0x45, 0x5f, 0x49, 0x44, 0x4c, 0x45, 0x10, 0x01, 0x12,
- 0x19, 0x0a, 0x15, 0x42, 0x45, 0x47, 0x49, 0x4e, 0x5f, 0x4d, 0x41, 0x49,
- 0x4e, 0x5f, 0x46, 0x52, 0x41, 0x4d, 0x45, 0x5f, 0x53, 0x45, 0x4e, 0x54,
- 0x10, 0x02, 0x12, 0x24, 0x0a, 0x20, 0x42, 0x45, 0x47, 0x49, 0x4e, 0x5f,
- 0x4d, 0x41, 0x49, 0x4e, 0x5f, 0x46, 0x52, 0x41, 0x4d, 0x45, 0x5f, 0x52,
- 0x45, 0x41, 0x44, 0x59, 0x5f, 0x54, 0x4f, 0x5f, 0x43, 0x4f, 0x4d, 0x4d,
- 0x49, 0x54, 0x10, 0x03, 0x22, 0xf4, 0x01, 0x0a, 0x17, 0x4c, 0x61, 0x79,
- 0x65, 0x72, 0x54, 0x72, 0x65, 0x65, 0x46, 0x72, 0x61, 0x6d, 0x65, 0x53,
- 0x69, 0x6e, 0x6b, 0x53, 0x74, 0x61, 0x74, 0x65, 0x12, 0x20, 0x0a, 0x1c,
- 0x4c, 0x41, 0x59, 0x45, 0x52, 0x5f, 0x54, 0x52, 0x45, 0x45, 0x5f, 0x46,
- 0x52, 0x41, 0x4d, 0x45, 0x5f, 0x55, 0x4e, 0x53, 0x50, 0x45, 0x43, 0x49,
- 0x46, 0x49, 0x45, 0x44, 0x10, 0x00, 0x12, 0x19, 0x0a, 0x15, 0x4c, 0x41,
- 0x59, 0x45, 0x52, 0x5f, 0x54, 0x52, 0x45, 0x45, 0x5f, 0x46, 0x52, 0x41,
- 0x4d, 0x45, 0x5f, 0x4e, 0x4f, 0x4e, 0x45, 0x10, 0x01, 0x12, 0x1b, 0x0a,
- 0x17, 0x4c, 0x41, 0x59, 0x45, 0x52, 0x5f, 0x54, 0x52, 0x45, 0x45, 0x5f,
- 0x46, 0x52, 0x41, 0x4d, 0x45, 0x5f, 0x41, 0x43, 0x54, 0x49, 0x56, 0x45,
- 0x10, 0x02, 0x12, 0x1d, 0x0a, 0x19, 0x4c, 0x41, 0x59, 0x45, 0x52, 0x5f,
- 0x54, 0x52, 0x45, 0x45, 0x5f, 0x46, 0x52, 0x41, 0x4d, 0x45, 0x5f, 0x43,
- 0x52, 0x45, 0x41, 0x54, 0x49, 0x4e, 0x47, 0x10, 0x03, 0x12, 0x2d, 0x0a,
- 0x29, 0x4c, 0x41, 0x59, 0x45, 0x52, 0x5f, 0x54, 0x52, 0x45, 0x45, 0x5f,
- 0x46, 0x52, 0x41, 0x4d, 0x45, 0x5f, 0x57, 0x41, 0x49, 0x54, 0x49, 0x4e,
- 0x47, 0x5f, 0x46, 0x4f, 0x52, 0x5f, 0x46, 0x49, 0x52, 0x53, 0x54, 0x5f,
- 0x43, 0x4f, 0x4d, 0x4d, 0x49, 0x54, 0x10, 0x04, 0x12, 0x31, 0x0a, 0x2d,
- 0x4c, 0x41, 0x59, 0x45, 0x52, 0x5f, 0x54, 0x52, 0x45, 0x45, 0x5f, 0x46,
- 0x52, 0x41, 0x4d, 0x45, 0x5f, 0x57, 0x41, 0x49, 0x54, 0x49, 0x4e, 0x47,
- 0x5f, 0x46, 0x4f, 0x52, 0x5f, 0x46, 0x49, 0x52, 0x53, 0x54, 0x5f, 0x41,
- 0x43, 0x54, 0x49, 0x56, 0x41, 0x54, 0x49, 0x4f, 0x4e, 0x10, 0x05, 0x22,
- 0xc7, 0x01, 0x0a, 0x1a, 0x46, 0x6f, 0x72, 0x63, 0x65, 0x64, 0x52, 0x65,
- 0x64, 0x72, 0x61, 0x77, 0x4f, 0x6e, 0x54, 0x69, 0x6d, 0x65, 0x6f, 0x75,
- 0x74, 0x53, 0x74, 0x61, 0x74, 0x65, 0x12, 0x1d, 0x0a, 0x19, 0x46, 0x4f,
- 0x52, 0x43, 0x45, 0x44, 0x5f, 0x52, 0x45, 0x44, 0x52, 0x41, 0x57, 0x5f,
- 0x55, 0x4e, 0x53, 0x50, 0x45, 0x43, 0x49, 0x46, 0x49, 0x45, 0x44, 0x10,
- 0x00, 0x12, 0x16, 0x0a, 0x12, 0x46, 0x4f, 0x52, 0x43, 0x45, 0x44, 0x5f,
- 0x52, 0x45, 0x44, 0x52, 0x41, 0x57, 0x5f, 0x49, 0x44, 0x4c, 0x45, 0x10,
- 0x01, 0x12, 0x24, 0x0a, 0x20, 0x46, 0x4f, 0x52, 0x43, 0x45, 0x44, 0x5f,
- 0x52, 0x45, 0x44, 0x52, 0x41, 0x57, 0x5f, 0x57, 0x41, 0x49, 0x54, 0x49,
- 0x4e, 0x47, 0x5f, 0x46, 0x4f, 0x52, 0x5f, 0x43, 0x4f, 0x4d, 0x4d, 0x49,
- 0x54, 0x10, 0x02, 0x12, 0x28, 0x0a, 0x24, 0x46, 0x4f, 0x52, 0x43, 0x45,
- 0x44, 0x5f, 0x52, 0x45, 0x44, 0x52, 0x41, 0x57, 0x5f, 0x57, 0x41, 0x49,
- 0x54, 0x49, 0x4e, 0x47, 0x5f, 0x46, 0x4f, 0x52, 0x5f, 0x41, 0x43, 0x54,
- 0x49, 0x56, 0x41, 0x54, 0x49, 0x4f, 0x4e, 0x10, 0x03, 0x12, 0x22, 0x0a,
- 0x1e, 0x46, 0x4f, 0x52, 0x43, 0x45, 0x44, 0x5f, 0x52, 0x45, 0x44, 0x52,
- 0x41, 0x57, 0x5f, 0x57, 0x41, 0x49, 0x54, 0x49, 0x4e, 0x47, 0x5f, 0x46,
- 0x4f, 0x52, 0x5f, 0x44, 0x52, 0x41, 0x57, 0x10, 0x04, 0x1a, 0xb3, 0x1b,
- 0x0a, 0x0a, 0x4d, 0x69, 0x6e, 0x6f, 0x72, 0x53, 0x74, 0x61, 0x74, 0x65,
- 0x12, 0x21, 0x0a, 0x0c, 0x63, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x5f, 0x63,
- 0x6f, 0x75, 0x6e, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x05, 0x52, 0x0b,
- 0x63, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x43, 0x6f, 0x75, 0x6e, 0x74, 0x12,
- 0x30, 0x0a, 0x14, 0x63, 0x75, 0x72, 0x72, 0x65, 0x6e, 0x74, 0x5f, 0x66,
- 0x72, 0x61, 0x6d, 0x65, 0x5f, 0x6e, 0x75, 0x6d, 0x62, 0x65, 0x72, 0x18,
- 0x02, 0x20, 0x01, 0x28, 0x05, 0x52, 0x12, 0x63, 0x75, 0x72, 0x72, 0x65,
- 0x6e, 0x74, 0x46, 0x72, 0x61, 0x6d, 0x65, 0x4e, 0x75, 0x6d, 0x62, 0x65,
- 0x72, 0x12, 0x4a, 0x0a, 0x22, 0x6c, 0x61, 0x73, 0x74, 0x5f, 0x66, 0x72,
- 0x61, 0x6d, 0x65, 0x5f, 0x6e, 0x75, 0x6d, 0x62, 0x65, 0x72, 0x5f, 0x73,
- 0x75, 0x62, 0x6d, 0x69, 0x74, 0x5f, 0x70, 0x65, 0x72, 0x66, 0x6f, 0x72,
- 0x6d, 0x65, 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, 0x05, 0x52, 0x1e, 0x6c,
- 0x61, 0x73, 0x74, 0x46, 0x72, 0x61, 0x6d, 0x65, 0x4e, 0x75, 0x6d, 0x62,
- 0x65, 0x72, 0x53, 0x75, 0x62, 0x6d, 0x69, 0x74, 0x50, 0x65, 0x72, 0x66,
- 0x6f, 0x72, 0x6d, 0x65, 0x64, 0x12, 0x46, 0x0a, 0x20, 0x6c, 0x61, 0x73,
- 0x74, 0x5f, 0x66, 0x72, 0x61, 0x6d, 0x65, 0x5f, 0x6e, 0x75, 0x6d, 0x62,
- 0x65, 0x72, 0x5f, 0x64, 0x72, 0x61, 0x77, 0x5f, 0x70, 0x65, 0x72, 0x66,
- 0x6f, 0x72, 0x6d, 0x65, 0x64, 0x18, 0x04, 0x20, 0x01, 0x28, 0x05, 0x52,
- 0x1c, 0x6c, 0x61, 0x73, 0x74, 0x46, 0x72, 0x61, 0x6d, 0x65, 0x4e, 0x75,
- 0x6d, 0x62, 0x65, 0x72, 0x44, 0x72, 0x61, 0x77, 0x50, 0x65, 0x72, 0x66,
- 0x6f, 0x72, 0x6d, 0x65, 0x64, 0x12, 0x52, 0x0a, 0x27, 0x6c, 0x61, 0x73,
- 0x74, 0x5f, 0x66, 0x72, 0x61, 0x6d, 0x65, 0x5f, 0x6e, 0x75, 0x6d, 0x62,
- 0x65, 0x72, 0x5f, 0x62, 0x65, 0x67, 0x69, 0x6e, 0x5f, 0x6d, 0x61, 0x69,
- 0x6e, 0x5f, 0x66, 0x72, 0x61, 0x6d, 0x65, 0x5f, 0x73, 0x65, 0x6e, 0x74,
- 0x18, 0x05, 0x20, 0x01, 0x28, 0x05, 0x52, 0x21, 0x6c, 0x61, 0x73, 0x74,
- 0x46, 0x72, 0x61, 0x6d, 0x65, 0x4e, 0x75, 0x6d, 0x62, 0x65, 0x72, 0x42,
- 0x65, 0x67, 0x69, 0x6e, 0x4d, 0x61, 0x69, 0x6e, 0x46, 0x72, 0x61, 0x6d,
- 0x65, 0x53, 0x65, 0x6e, 0x74, 0x12, 0x19, 0x0a, 0x08, 0x64, 0x69, 0x64,
- 0x5f, 0x64, 0x72, 0x61, 0x77, 0x18, 0x06, 0x20, 0x01, 0x28, 0x08, 0x52,
- 0x07, 0x64, 0x69, 0x64, 0x44, 0x72, 0x61, 0x77, 0x12, 0x59, 0x0a, 0x2b,
- 0x64, 0x69, 0x64, 0x5f, 0x73, 0x65, 0x6e, 0x64, 0x5f, 0x62, 0x65, 0x67,
- 0x69, 0x6e, 0x5f, 0x6d, 0x61, 0x69, 0x6e, 0x5f, 0x66, 0x72, 0x61, 0x6d,
- 0x65, 0x5f, 0x66, 0x6f, 0x72, 0x5f, 0x63, 0x75, 0x72, 0x72, 0x65, 0x6e,
- 0x74, 0x5f, 0x66, 0x72, 0x61, 0x6d, 0x65, 0x18, 0x07, 0x20, 0x01, 0x28,
- 0x08, 0x52, 0x24, 0x64, 0x69, 0x64, 0x53, 0x65, 0x6e, 0x64, 0x42, 0x65,
+ 0x63, 0x68, 0x69, 0x6e, 0x65, 0x2e, 0x4d, 0x69, 0x6e, 0x6f, 0x72, 0x53,
+ 0x74, 0x61, 0x74, 0x65, 0x2e, 0x53, 0x63, 0x72, 0x6f, 0x6c, 0x6c, 0x48,
+ 0x61, 0x6e, 0x64, 0x6c, 0x65, 0x72, 0x53, 0x74, 0x61, 0x74, 0x65, 0x52,
+ 0x12, 0x73, 0x63, 0x72, 0x6f, 0x6c, 0x6c, 0x48, 0x61, 0x6e, 0x64, 0x6c,
+ 0x65, 0x72, 0x53, 0x74, 0x61, 0x74, 0x65, 0x12, 0x5d, 0x0a, 0x2d, 0x63,
+ 0x72, 0x69, 0x74, 0x69, 0x63, 0x61, 0x6c, 0x5f, 0x62, 0x65, 0x67, 0x69,
+ 0x6e, 0x5f, 0x6d, 0x61, 0x69, 0x6e, 0x5f, 0x66, 0x72, 0x61, 0x6d, 0x65,
+ 0x5f, 0x74, 0x6f, 0x5f, 0x61, 0x63, 0x74, 0x69, 0x76, 0x61, 0x74, 0x65,
+ 0x5f, 0x69, 0x73, 0x5f, 0x66, 0x61, 0x73, 0x74, 0x18, 0x21, 0x20, 0x01,
+ 0x28, 0x08, 0x52, 0x26, 0x63, 0x72, 0x69, 0x74, 0x69, 0x63, 0x61, 0x6c,
+ 0x42, 0x65, 0x67, 0x69, 0x6e, 0x4d, 0x61, 0x69, 0x6e, 0x46, 0x72, 0x61,
+ 0x6d, 0x65, 0x54, 0x6f, 0x41, 0x63, 0x74, 0x69, 0x76, 0x61, 0x74, 0x65,
+ 0x49, 0x73, 0x46, 0x61, 0x73, 0x74, 0x12, 0x46, 0x0a, 0x20, 0x6d, 0x61,
+ 0x69, 0x6e, 0x5f, 0x74, 0x68, 0x72, 0x65, 0x61, 0x64, 0x5f, 0x6d, 0x69,
+ 0x73, 0x73, 0x65, 0x64, 0x5f, 0x6c, 0x61, 0x73, 0x74, 0x5f, 0x64, 0x65,
+ 0x61, 0x64, 0x6c, 0x69, 0x6e, 0x65, 0x18, 0x22, 0x20, 0x01, 0x28, 0x08,
+ 0x52, 0x1c, 0x6d, 0x61, 0x69, 0x6e, 0x54, 0x68, 0x72, 0x65, 0x61, 0x64,
+ 0x4d, 0x69, 0x73, 0x73, 0x65, 0x64, 0x4c, 0x61, 0x73, 0x74, 0x44, 0x65,
+ 0x61, 0x64, 0x6c, 0x69, 0x6e, 0x65, 0x12, 0x5b, 0x0a, 0x2c, 0x73, 0x6b,
+ 0x69, 0x70, 0x5f, 0x6e, 0x65, 0x78, 0x74, 0x5f, 0x62, 0x65, 0x67, 0x69,
+ 0x6e, 0x5f, 0x6d, 0x61, 0x69, 0x6e, 0x5f, 0x66, 0x72, 0x61, 0x6d, 0x65,
+ 0x5f, 0x74, 0x6f, 0x5f, 0x72, 0x65, 0x64, 0x75, 0x63, 0x65, 0x5f, 0x6c,
+ 0x61, 0x74, 0x65, 0x6e, 0x63, 0x79, 0x18, 0x23, 0x20, 0x01, 0x28, 0x08,
+ 0x52, 0x25, 0x73, 0x6b, 0x69, 0x70, 0x4e, 0x65, 0x78, 0x74, 0x42, 0x65,
0x67, 0x69, 0x6e, 0x4d, 0x61, 0x69, 0x6e, 0x46, 0x72, 0x61, 0x6d, 0x65,
- 0x46, 0x6f, 0x72, 0x43, 0x75, 0x72, 0x72, 0x65, 0x6e, 0x74, 0x46, 0x72,
- 0x61, 0x6d, 0x65, 0x12, 0x5f, 0x0a, 0x2e, 0x64, 0x69, 0x64, 0x5f, 0x6e,
- 0x6f, 0x74, 0x69, 0x66, 0x79, 0x5f, 0x62, 0x65, 0x67, 0x69, 0x6e, 0x5f,
- 0x6d, 0x61, 0x69, 0x6e, 0x5f, 0x66, 0x72, 0x61, 0x6d, 0x65, 0x5f, 0x6e,
- 0x6f, 0x74, 0x5f, 0x65, 0x78, 0x70, 0x65, 0x63, 0x74, 0x65, 0x64, 0x5f,
- 0x75, 0x6e, 0x74, 0x69, 0x6c, 0x18, 0x08, 0x20, 0x01, 0x28, 0x08, 0x52,
- 0x27, 0x64, 0x69, 0x64, 0x4e, 0x6f, 0x74, 0x69, 0x66, 0x79, 0x42, 0x65,
- 0x67, 0x69, 0x6e, 0x4d, 0x61, 0x69, 0x6e, 0x46, 0x72, 0x61, 0x6d, 0x65,
- 0x4e, 0x6f, 0x74, 0x45, 0x78, 0x70, 0x65, 0x63, 0x74, 0x65, 0x64, 0x55,
- 0x6e, 0x74, 0x69, 0x6c, 0x12, 0x5d, 0x0a, 0x2d, 0x64, 0x69, 0x64, 0x5f,
- 0x6e, 0x6f, 0x74, 0x69, 0x66, 0x79, 0x5f, 0x62, 0x65, 0x67, 0x69, 0x6e,
- 0x5f, 0x6d, 0x61, 0x69, 0x6e, 0x5f, 0x66, 0x72, 0x61, 0x6d, 0x65, 0x5f,
- 0x6e, 0x6f, 0x74, 0x5f, 0x65, 0x78, 0x70, 0x65, 0x63, 0x74, 0x65, 0x64,
- 0x5f, 0x73, 0x6f, 0x6f, 0x6e, 0x18, 0x09, 0x20, 0x01, 0x28, 0x08, 0x52,
- 0x26, 0x64, 0x69, 0x64, 0x4e, 0x6f, 0x74, 0x69, 0x66, 0x79, 0x42, 0x65,
- 0x67, 0x69, 0x6e, 0x4d, 0x61, 0x69, 0x6e, 0x46, 0x72, 0x61, 0x6d, 0x65,
- 0x4e, 0x6f, 0x74, 0x45, 0x78, 0x70, 0x65, 0x63, 0x74, 0x65, 0x64, 0x53,
- 0x6f, 0x6f, 0x6e, 0x12, 0x4b, 0x0a, 0x23, 0x77, 0x61, 0x6e, 0x74, 0x73,
- 0x5f, 0x62, 0x65, 0x67, 0x69, 0x6e, 0x5f, 0x6d, 0x61, 0x69, 0x6e, 0x5f,
- 0x66, 0x72, 0x61, 0x6d, 0x65, 0x5f, 0x6e, 0x6f, 0x74, 0x5f, 0x65, 0x78,
- 0x70, 0x65, 0x63, 0x74, 0x65, 0x64, 0x18, 0x0a, 0x20, 0x01, 0x28, 0x08,
- 0x52, 0x1e, 0x77, 0x61, 0x6e, 0x74, 0x73, 0x42, 0x65, 0x67, 0x69, 0x6e,
- 0x4d, 0x61, 0x69, 0x6e, 0x46, 0x72, 0x61, 0x6d, 0x65, 0x4e, 0x6f, 0x74,
- 0x45, 0x78, 0x70, 0x65, 0x63, 0x74, 0x65, 0x64, 0x12, 0x35, 0x0a, 0x17,
- 0x64, 0x69, 0x64, 0x5f, 0x63, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x5f, 0x64,
- 0x75, 0x72, 0x69, 0x6e, 0x67, 0x5f, 0x66, 0x72, 0x61, 0x6d, 0x65, 0x18,
- 0x0b, 0x20, 0x01, 0x28, 0x08, 0x52, 0x14, 0x64, 0x69, 0x64, 0x43, 0x6f,
- 0x6d, 0x6d, 0x69, 0x74, 0x44, 0x75, 0x72, 0x69, 0x6e, 0x67, 0x46, 0x72,
- 0x61, 0x6d, 0x65, 0x12, 0x4d, 0x0a, 0x24, 0x64, 0x69, 0x64, 0x5f, 0x69,
- 0x6e, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x65, 0x5f, 0x6c, 0x61,
- 0x79, 0x65, 0x72, 0x5f, 0x74, 0x72, 0x65, 0x65, 0x5f, 0x66, 0x72, 0x61,
- 0x6d, 0x65, 0x5f, 0x73, 0x69, 0x6e, 0x6b, 0x18, 0x0c, 0x20, 0x01, 0x28,
- 0x08, 0x52, 0x1f, 0x64, 0x69, 0x64, 0x49, 0x6e, 0x76, 0x61, 0x6c, 0x69,
- 0x64, 0x61, 0x74, 0x65, 0x4c, 0x61, 0x79, 0x65, 0x72, 0x54, 0x72, 0x65,
- 0x65, 0x46, 0x72, 0x61, 0x6d, 0x65, 0x53, 0x69, 0x6e, 0x6b, 0x12, 0x48,
- 0x0a, 0x21, 0x64, 0x69, 0x64, 0x5f, 0x70, 0x65, 0x72, 0x66, 0x6f, 0x72,
- 0x6d, 0x5f, 0x69, 0x6d, 0x70, 0x6c, 0x5f, 0x73, 0x69, 0x64, 0x65, 0x5f,
- 0x69, 0x6e, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x69, 0x6f, 0x6e, 0x18,
- 0x0d, 0x20, 0x01, 0x28, 0x08, 0x52, 0x1d, 0x64, 0x69, 0x64, 0x50, 0x65,
- 0x72, 0x66, 0x6f, 0x72, 0x6d, 0x49, 0x6d, 0x70, 0x6c, 0x53, 0x69, 0x64,
- 0x65, 0x49, 0x6e, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x69, 0x6f, 0x6e,
- 0x12, 0x2a, 0x0a, 0x11, 0x64, 0x69, 0x64, 0x5f, 0x70, 0x72, 0x65, 0x70,
- 0x61, 0x72, 0x65, 0x5f, 0x74, 0x69, 0x6c, 0x65, 0x73, 0x18, 0x0e, 0x20,
- 0x01, 0x28, 0x08, 0x52, 0x0f, 0x64, 0x69, 0x64, 0x50, 0x72, 0x65, 0x70,
- 0x61, 0x72, 0x65, 0x54, 0x69, 0x6c, 0x65, 0x73, 0x12, 0x4e, 0x0a, 0x23,
- 0x63, 0x6f, 0x6e, 0x73, 0x65, 0x63, 0x75, 0x74, 0x69, 0x76, 0x65, 0x5f,
- 0x63, 0x68, 0x65, 0x63, 0x6b, 0x65, 0x72, 0x62, 0x6f, 0x61, 0x72, 0x64,
- 0x5f, 0x61, 0x6e, 0x69, 0x6d, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x18,
- 0x0f, 0x20, 0x01, 0x28, 0x05, 0x52, 0x21, 0x63, 0x6f, 0x6e, 0x73, 0x65,
- 0x63, 0x75, 0x74, 0x69, 0x76, 0x65, 0x43, 0x68, 0x65, 0x63, 0x6b, 0x65,
- 0x72, 0x62, 0x6f, 0x61, 0x72, 0x64, 0x41, 0x6e, 0x69, 0x6d, 0x61, 0x74,
- 0x69, 0x6f, 0x6e, 0x73, 0x12, 0x32, 0x0a, 0x15, 0x70, 0x65, 0x6e, 0x64,
- 0x69, 0x6e, 0x67, 0x5f, 0x73, 0x75, 0x62, 0x6d, 0x69, 0x74, 0x5f, 0x66,
- 0x72, 0x61, 0x6d, 0x65, 0x73, 0x18, 0x10, 0x20, 0x01, 0x28, 0x05, 0x52,
- 0x13, 0x70, 0x65, 0x6e, 0x64, 0x69, 0x6e, 0x67, 0x53, 0x75, 0x62, 0x6d,
- 0x69, 0x74, 0x46, 0x72, 0x61, 0x6d, 0x65, 0x73, 0x12, 0x63, 0x0a, 0x30,
- 0x73, 0x75, 0x62, 0x6d, 0x69, 0x74, 0x5f, 0x66, 0x72, 0x61, 0x6d, 0x65,
- 0x73, 0x5f, 0x77, 0x69, 0x74, 0x68, 0x5f, 0x63, 0x75, 0x72, 0x72, 0x65,
- 0x6e, 0x74, 0x5f, 0x6c, 0x61, 0x79, 0x65, 0x72, 0x5f, 0x74, 0x72, 0x65,
- 0x65, 0x5f, 0x66, 0x72, 0x61, 0x6d, 0x65, 0x5f, 0x73, 0x69, 0x6e, 0x6b,
- 0x18, 0x11, 0x20, 0x01, 0x28, 0x05, 0x52, 0x29, 0x73, 0x75, 0x62, 0x6d,
- 0x69, 0x74, 0x46, 0x72, 0x61, 0x6d, 0x65, 0x73, 0x57, 0x69, 0x74, 0x68,
- 0x43, 0x75, 0x72, 0x72, 0x65, 0x6e, 0x74, 0x4c, 0x61, 0x79, 0x65, 0x72,
- 0x54, 0x72, 0x65, 0x65, 0x46, 0x72, 0x61, 0x6d, 0x65, 0x53, 0x69, 0x6e,
- 0x6b, 0x12, 0x21, 0x0a, 0x0c, 0x6e, 0x65, 0x65, 0x64, 0x73, 0x5f, 0x72,
- 0x65, 0x64, 0x72, 0x61, 0x77, 0x18, 0x12, 0x20, 0x01, 0x28, 0x08, 0x52,
- 0x0b, 0x6e, 0x65, 0x65, 0x64, 0x73, 0x52, 0x65, 0x64, 0x72, 0x61, 0x77,
- 0x12, 0x2e, 0x0a, 0x13, 0x6e, 0x65, 0x65, 0x64, 0x73, 0x5f, 0x70, 0x72,
- 0x65, 0x70, 0x61, 0x72, 0x65, 0x5f, 0x74, 0x69, 0x6c, 0x65, 0x73, 0x18,
- 0x13, 0x20, 0x01, 0x28, 0x08, 0x52, 0x11, 0x6e, 0x65, 0x65, 0x64, 0x73,
- 0x50, 0x72, 0x65, 0x70, 0x61, 0x72, 0x65, 0x54, 0x69, 0x6c, 0x65, 0x73,
- 0x12, 0x33, 0x0a, 0x16, 0x6e, 0x65, 0x65, 0x64, 0x73, 0x5f, 0x62, 0x65,
+ 0x54, 0x6f, 0x52, 0x65, 0x64, 0x75, 0x63, 0x65, 0x4c, 0x61, 0x74, 0x65,
+ 0x6e, 0x63, 0x79, 0x12, 0x37, 0x0a, 0x18, 0x76, 0x69, 0x64, 0x65, 0x6f,
+ 0x5f, 0x6e, 0x65, 0x65, 0x64, 0x73, 0x5f, 0x62, 0x65, 0x67, 0x69, 0x6e,
+ 0x5f, 0x66, 0x72, 0x61, 0x6d, 0x65, 0x73, 0x18, 0x24, 0x20, 0x01, 0x28,
+ 0x08, 0x52, 0x15, 0x76, 0x69, 0x64, 0x65, 0x6f, 0x4e, 0x65, 0x65, 0x64,
+ 0x73, 0x42, 0x65, 0x67, 0x69, 0x6e, 0x46, 0x72, 0x61, 0x6d, 0x65, 0x73,
+ 0x12, 0x33, 0x0a, 0x16, 0x64, 0x65, 0x66, 0x65, 0x72, 0x5f, 0x62, 0x65,
0x67, 0x69, 0x6e, 0x5f, 0x6d, 0x61, 0x69, 0x6e, 0x5f, 0x66, 0x72, 0x61,
- 0x6d, 0x65, 0x18, 0x14, 0x20, 0x01, 0x28, 0x08, 0x52, 0x13, 0x6e, 0x65,
- 0x65, 0x64, 0x73, 0x42, 0x65, 0x67, 0x69, 0x6e, 0x4d, 0x61, 0x69, 0x6e,
- 0x46, 0x72, 0x61, 0x6d, 0x65, 0x12, 0x3a, 0x0a, 0x1a, 0x6e, 0x65, 0x65,
- 0x64, 0x73, 0x5f, 0x6f, 0x6e, 0x65, 0x5f, 0x62, 0x65, 0x67, 0x69, 0x6e,
- 0x5f, 0x69, 0x6d, 0x70, 0x6c, 0x5f, 0x66, 0x72, 0x61, 0x6d, 0x65, 0x18,
- 0x15, 0x20, 0x01, 0x28, 0x08, 0x52, 0x16, 0x6e, 0x65, 0x65, 0x64, 0x73,
- 0x4f, 0x6e, 0x65, 0x42, 0x65, 0x67, 0x69, 0x6e, 0x49, 0x6d, 0x70, 0x6c,
- 0x46, 0x72, 0x61, 0x6d, 0x65, 0x12, 0x18, 0x0a, 0x07, 0x76, 0x69, 0x73,
- 0x69, 0x62, 0x6c, 0x65, 0x18, 0x16, 0x20, 0x01, 0x28, 0x08, 0x52, 0x07,
- 0x76, 0x69, 0x73, 0x69, 0x62, 0x6c, 0x65, 0x12, 0x39, 0x0a, 0x19, 0x62,
- 0x65, 0x67, 0x69, 0x6e, 0x5f, 0x66, 0x72, 0x61, 0x6d, 0x65, 0x5f, 0x73,
- 0x6f, 0x75, 0x72, 0x63, 0x65, 0x5f, 0x70, 0x61, 0x75, 0x73, 0x65, 0x64,
- 0x18, 0x17, 0x20, 0x01, 0x28, 0x08, 0x52, 0x16, 0x62, 0x65, 0x67, 0x69,
- 0x6e, 0x46, 0x72, 0x61, 0x6d, 0x65, 0x53, 0x6f, 0x75, 0x72, 0x63, 0x65,
- 0x50, 0x61, 0x75, 0x73, 0x65, 0x64, 0x12, 0x19, 0x0a, 0x08, 0x63, 0x61,
- 0x6e, 0x5f, 0x64, 0x72, 0x61, 0x77, 0x18, 0x18, 0x20, 0x01, 0x28, 0x08,
- 0x52, 0x07, 0x63, 0x61, 0x6e, 0x44, 0x72, 0x61, 0x77, 0x12, 0x2b, 0x0a,
- 0x11, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x6c, 0x65, 0x73,
- 0x73, 0x5f, 0x64, 0x72, 0x61, 0x77, 0x18, 0x19, 0x20, 0x01, 0x28, 0x08,
- 0x52, 0x10, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x6c, 0x65,
- 0x73, 0x73, 0x44, 0x72, 0x61, 0x77, 0x12, 0x28, 0x0a, 0x10, 0x68, 0x61,
- 0x73, 0x5f, 0x70, 0x65, 0x6e, 0x64, 0x69, 0x6e, 0x67, 0x5f, 0x74, 0x72,
- 0x65, 0x65, 0x18, 0x1a, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0e, 0x68, 0x61,
- 0x73, 0x50, 0x65, 0x6e, 0x64, 0x69, 0x6e, 0x67, 0x54, 0x72, 0x65, 0x65,
- 0x12, 0x4d, 0x0a, 0x24, 0x70, 0x65, 0x6e, 0x64, 0x69, 0x6e, 0x67, 0x5f,
- 0x74, 0x72, 0x65, 0x65, 0x5f, 0x69, 0x73, 0x5f, 0x72, 0x65, 0x61, 0x64,
- 0x79, 0x5f, 0x66, 0x6f, 0x72, 0x5f, 0x61, 0x63, 0x74, 0x69, 0x76, 0x61,
- 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x1b, 0x20, 0x01, 0x28, 0x08, 0x52, 0x1f,
- 0x70, 0x65, 0x6e, 0x64, 0x69, 0x6e, 0x67, 0x54, 0x72, 0x65, 0x65, 0x49,
- 0x73, 0x52, 0x65, 0x61, 0x64, 0x79, 0x46, 0x6f, 0x72, 0x41, 0x63, 0x74,
- 0x69, 0x76, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x3e, 0x0a, 0x1c, 0x61,
- 0x63, 0x74, 0x69, 0x76, 0x65, 0x5f, 0x74, 0x72, 0x65, 0x65, 0x5f, 0x6e,
- 0x65, 0x65, 0x64, 0x73, 0x5f, 0x66, 0x69, 0x72, 0x73, 0x74, 0x5f, 0x64,
- 0x72, 0x61, 0x77, 0x18, 0x1c, 0x20, 0x01, 0x28, 0x08, 0x52, 0x18, 0x61,
- 0x63, 0x74, 0x69, 0x76, 0x65, 0x54, 0x72, 0x65, 0x65, 0x4e, 0x65, 0x65,
- 0x64, 0x73, 0x46, 0x69, 0x72, 0x73, 0x74, 0x44, 0x72, 0x61, 0x77, 0x12,
- 0x3d, 0x0a, 0x1c, 0x61, 0x63, 0x74, 0x69, 0x76, 0x65, 0x5f, 0x74, 0x72,
- 0x65, 0x65, 0x5f, 0x69, 0x73, 0x5f, 0x72, 0x65, 0x61, 0x64, 0x79, 0x5f,
- 0x74, 0x6f, 0x5f, 0x64, 0x72, 0x61, 0x77, 0x18, 0x1d, 0x20, 0x01, 0x28,
- 0x08, 0x52, 0x17, 0x61, 0x63, 0x74, 0x69, 0x76, 0x65, 0x54, 0x72, 0x65,
- 0x65, 0x49, 0x73, 0x52, 0x65, 0x61, 0x64, 0x79, 0x54, 0x6f, 0x44, 0x72,
- 0x61, 0x77, 0x12, 0x6c, 0x0a, 0x35, 0x64, 0x69, 0x64, 0x5f, 0x63, 0x72,
- 0x65, 0x61, 0x74, 0x65, 0x5f, 0x61, 0x6e, 0x64, 0x5f, 0x69, 0x6e, 0x69,
- 0x74, 0x69, 0x61, 0x6c, 0x69, 0x7a, 0x65, 0x5f, 0x66, 0x69, 0x72, 0x73,
- 0x74, 0x5f, 0x6c, 0x61, 0x79, 0x65, 0x72, 0x5f, 0x74, 0x72, 0x65, 0x65,
- 0x5f, 0x66, 0x72, 0x61, 0x6d, 0x65, 0x5f, 0x73, 0x69, 0x6e, 0x6b, 0x18,
- 0x1e, 0x20, 0x01, 0x28, 0x08, 0x52, 0x2d, 0x64, 0x69, 0x64, 0x43, 0x72,
- 0x65, 0x61, 0x74, 0x65, 0x41, 0x6e, 0x64, 0x49, 0x6e, 0x69, 0x74, 0x69,
- 0x61, 0x6c, 0x69, 0x7a, 0x65, 0x46, 0x69, 0x72, 0x73, 0x74, 0x4c, 0x61,
- 0x79, 0x65, 0x72, 0x54, 0x72, 0x65, 0x65, 0x46, 0x72, 0x61, 0x6d, 0x65,
- 0x53, 0x69, 0x6e, 0x6b, 0x12, 0x6a, 0x0a, 0x0d, 0x74, 0x72, 0x65, 0x65,
- 0x5f, 0x70, 0x72, 0x69, 0x6f, 0x72, 0x69, 0x74, 0x79, 0x18, 0x1f, 0x20,
- 0x01, 0x28, 0x0e, 0x32, 0x45, 0x2e, 0x70, 0x65, 0x72, 0x66, 0x65, 0x74,
- 0x74, 0x6f, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2e, 0x43, 0x68,
- 0x72, 0x6f, 0x6d, 0x65, 0x43, 0x6f, 0x6d, 0x70, 0x6f, 0x73, 0x69, 0x74,
- 0x6f, 0x72, 0x53, 0x74, 0x61, 0x74, 0x65, 0x4d, 0x61, 0x63, 0x68, 0x69,
- 0x6e, 0x65, 0x2e, 0x4d, 0x69, 0x6e, 0x6f, 0x72, 0x53, 0x74, 0x61, 0x74,
- 0x65, 0x2e, 0x54, 0x72, 0x65, 0x65, 0x50, 0x72, 0x69, 0x6f, 0x72, 0x69,
- 0x74, 0x79, 0x52, 0x0c, 0x74, 0x72, 0x65, 0x65, 0x50, 0x72, 0x69, 0x6f,
- 0x72, 0x69, 0x74, 0x79, 0x12, 0x7d, 0x0a, 0x14, 0x73, 0x63, 0x72, 0x6f,
- 0x6c, 0x6c, 0x5f, 0x68, 0x61, 0x6e, 0x64, 0x6c, 0x65, 0x72, 0x5f, 0x73,
- 0x74, 0x61, 0x74, 0x65, 0x18, 0x20, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x4b,
- 0x2e, 0x70, 0x65, 0x72, 0x66, 0x65, 0x74, 0x74, 0x6f, 0x2e, 0x70, 0x72,
- 0x6f, 0x74, 0x6f, 0x73, 0x2e, 0x43, 0x68, 0x72, 0x6f, 0x6d, 0x65, 0x43,
- 0x6f, 0x6d, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x6f, 0x72, 0x53, 0x74, 0x61,
- 0x74, 0x65, 0x4d, 0x61, 0x63, 0x68, 0x69, 0x6e, 0x65, 0x2e, 0x4d, 0x69,
- 0x6e, 0x6f, 0x72, 0x53, 0x74, 0x61, 0x74, 0x65, 0x2e, 0x53, 0x63, 0x72,
- 0x6f, 0x6c, 0x6c, 0x48, 0x61, 0x6e, 0x64, 0x6c, 0x65, 0x72, 0x53, 0x74,
- 0x61, 0x74, 0x65, 0x52, 0x12, 0x73, 0x63, 0x72, 0x6f, 0x6c, 0x6c, 0x48,
- 0x61, 0x6e, 0x64, 0x6c, 0x65, 0x72, 0x53, 0x74, 0x61, 0x74, 0x65, 0x12,
- 0x5d, 0x0a, 0x2d, 0x63, 0x72, 0x69, 0x74, 0x69, 0x63, 0x61, 0x6c, 0x5f,
- 0x62, 0x65, 0x67, 0x69, 0x6e, 0x5f, 0x6d, 0x61, 0x69, 0x6e, 0x5f, 0x66,
- 0x72, 0x61, 0x6d, 0x65, 0x5f, 0x74, 0x6f, 0x5f, 0x61, 0x63, 0x74, 0x69,
- 0x76, 0x61, 0x74, 0x65, 0x5f, 0x69, 0x73, 0x5f, 0x66, 0x61, 0x73, 0x74,
- 0x18, 0x21, 0x20, 0x01, 0x28, 0x08, 0x52, 0x26, 0x63, 0x72, 0x69, 0x74,
- 0x69, 0x63, 0x61, 0x6c, 0x42, 0x65, 0x67, 0x69, 0x6e, 0x4d, 0x61, 0x69,
- 0x6e, 0x46, 0x72, 0x61, 0x6d, 0x65, 0x54, 0x6f, 0x41, 0x63, 0x74, 0x69,
- 0x76, 0x61, 0x74, 0x65, 0x49, 0x73, 0x46, 0x61, 0x73, 0x74, 0x12, 0x46,
- 0x0a, 0x20, 0x6d, 0x61, 0x69, 0x6e, 0x5f, 0x74, 0x68, 0x72, 0x65, 0x61,
- 0x64, 0x5f, 0x6d, 0x69, 0x73, 0x73, 0x65, 0x64, 0x5f, 0x6c, 0x61, 0x73,
- 0x74, 0x5f, 0x64, 0x65, 0x61, 0x64, 0x6c, 0x69, 0x6e, 0x65, 0x18, 0x22,
- 0x20, 0x01, 0x28, 0x08, 0x52, 0x1c, 0x6d, 0x61, 0x69, 0x6e, 0x54, 0x68,
- 0x72, 0x65, 0x61, 0x64, 0x4d, 0x69, 0x73, 0x73, 0x65, 0x64, 0x4c, 0x61,
- 0x73, 0x74, 0x44, 0x65, 0x61, 0x64, 0x6c, 0x69, 0x6e, 0x65, 0x12, 0x5b,
- 0x0a, 0x2c, 0x73, 0x6b, 0x69, 0x70, 0x5f, 0x6e, 0x65, 0x78, 0x74, 0x5f,
- 0x62, 0x65, 0x67, 0x69, 0x6e, 0x5f, 0x6d, 0x61, 0x69, 0x6e, 0x5f, 0x66,
- 0x72, 0x61, 0x6d, 0x65, 0x5f, 0x74, 0x6f, 0x5f, 0x72, 0x65, 0x64, 0x75,
- 0x63, 0x65, 0x5f, 0x6c, 0x61, 0x74, 0x65, 0x6e, 0x63, 0x79, 0x18, 0x23,
- 0x20, 0x01, 0x28, 0x08, 0x52, 0x25, 0x73, 0x6b, 0x69, 0x70, 0x4e, 0x65,
- 0x78, 0x74, 0x42, 0x65, 0x67, 0x69, 0x6e, 0x4d, 0x61, 0x69, 0x6e, 0x46,
- 0x72, 0x61, 0x6d, 0x65, 0x54, 0x6f, 0x52, 0x65, 0x64, 0x75, 0x63, 0x65,
- 0x4c, 0x61, 0x74, 0x65, 0x6e, 0x63, 0x79, 0x12, 0x37, 0x0a, 0x18, 0x76,
- 0x69, 0x64, 0x65, 0x6f, 0x5f, 0x6e, 0x65, 0x65, 0x64, 0x73, 0x5f, 0x62,
- 0x65, 0x67, 0x69, 0x6e, 0x5f, 0x66, 0x72, 0x61, 0x6d, 0x65, 0x73, 0x18,
- 0x24, 0x20, 0x01, 0x28, 0x08, 0x52, 0x15, 0x76, 0x69, 0x64, 0x65, 0x6f,
- 0x4e, 0x65, 0x65, 0x64, 0x73, 0x42, 0x65, 0x67, 0x69, 0x6e, 0x46, 0x72,
- 0x61, 0x6d, 0x65, 0x73, 0x12, 0x33, 0x0a, 0x16, 0x64, 0x65, 0x66, 0x65,
- 0x72, 0x5f, 0x62, 0x65, 0x67, 0x69, 0x6e, 0x5f, 0x6d, 0x61, 0x69, 0x6e,
- 0x5f, 0x66, 0x72, 0x61, 0x6d, 0x65, 0x18, 0x25, 0x20, 0x01, 0x28, 0x08,
- 0x52, 0x13, 0x64, 0x65, 0x66, 0x65, 0x72, 0x42, 0x65, 0x67, 0x69, 0x6e,
- 0x4d, 0x61, 0x69, 0x6e, 0x46, 0x72, 0x61, 0x6d, 0x65, 0x12, 0x3a, 0x0a,
- 0x1a, 0x6c, 0x61, 0x73, 0x74, 0x5f, 0x63, 0x6f, 0x6d, 0x6d, 0x69, 0x74,
- 0x5f, 0x68, 0x61, 0x64, 0x5f, 0x6e, 0x6f, 0x5f, 0x75, 0x70, 0x64, 0x61,
- 0x74, 0x65, 0x73, 0x18, 0x26, 0x20, 0x01, 0x28, 0x08, 0x52, 0x16, 0x6c,
- 0x61, 0x73, 0x74, 0x43, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x48, 0x61, 0x64,
- 0x4e, 0x6f, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x73, 0x12, 0x32, 0x0a,
- 0x16, 0x64, 0x69, 0x64, 0x5f, 0x64, 0x72, 0x61, 0x77, 0x5f, 0x69, 0x6e,
- 0x5f, 0x6c, 0x61, 0x73, 0x74, 0x5f, 0x66, 0x72, 0x61, 0x6d, 0x65, 0x18,
- 0x27, 0x20, 0x01, 0x28, 0x08, 0x52, 0x12, 0x64, 0x69, 0x64, 0x44, 0x72,
- 0x61, 0x77, 0x49, 0x6e, 0x4c, 0x61, 0x73, 0x74, 0x46, 0x72, 0x61, 0x6d,
- 0x65, 0x12, 0x36, 0x0a, 0x18, 0x64, 0x69, 0x64, 0x5f, 0x73, 0x75, 0x62,
- 0x6d, 0x69, 0x74, 0x5f, 0x69, 0x6e, 0x5f, 0x6c, 0x61, 0x73, 0x74, 0x5f,
- 0x66, 0x72, 0x61, 0x6d, 0x65, 0x18, 0x28, 0x20, 0x01, 0x28, 0x08, 0x52,
- 0x14, 0x64, 0x69, 0x64, 0x53, 0x75, 0x62, 0x6d, 0x69, 0x74, 0x49, 0x6e,
- 0x4c, 0x61, 0x73, 0x74, 0x46, 0x72, 0x61, 0x6d, 0x65, 0x12, 0x3f, 0x0a,
- 0x1c, 0x6e, 0x65, 0x65, 0x64, 0x73, 0x5f, 0x69, 0x6d, 0x70, 0x6c, 0x5f,
- 0x73, 0x69, 0x64, 0x65, 0x5f, 0x69, 0x6e, 0x76, 0x61, 0x6c, 0x69, 0x64,
- 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x29, 0x20, 0x01, 0x28, 0x08, 0x52,
- 0x19, 0x6e, 0x65, 0x65, 0x64, 0x73, 0x49, 0x6d, 0x70, 0x6c, 0x53, 0x69,
- 0x64, 0x65, 0x49, 0x6e, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x69,
- 0x6f, 0x6e, 0x12, 0x47, 0x0a, 0x21, 0x63, 0x75, 0x72, 0x72, 0x65, 0x6e,
- 0x74, 0x5f, 0x70, 0x65, 0x6e, 0x64, 0x69, 0x6e, 0x67, 0x5f, 0x74, 0x72,
- 0x65, 0x65, 0x5f, 0x69, 0x73, 0x5f, 0x69, 0x6d, 0x70, 0x6c, 0x5f, 0x73,
- 0x69, 0x64, 0x65, 0x18, 0x2a, 0x20, 0x01, 0x28, 0x08, 0x52, 0x1c, 0x63,
- 0x75, 0x72, 0x72, 0x65, 0x6e, 0x74, 0x50, 0x65, 0x6e, 0x64, 0x69, 0x6e,
- 0x67, 0x54, 0x72, 0x65, 0x65, 0x49, 0x73, 0x49, 0x6d, 0x70, 0x6c, 0x53,
- 0x69, 0x64, 0x65, 0x12, 0x4b, 0x0a, 0x23, 0x70, 0x72, 0x65, 0x76, 0x69,
- 0x6f, 0x75, 0x73, 0x5f, 0x70, 0x65, 0x6e, 0x64, 0x69, 0x6e, 0x67, 0x5f,
- 0x74, 0x72, 0x65, 0x65, 0x5f, 0x77, 0x61, 0x73, 0x5f, 0x69, 0x6d, 0x70,
- 0x6c, 0x5f, 0x73, 0x69, 0x64, 0x65, 0x18, 0x2b, 0x20, 0x01, 0x28, 0x08,
- 0x52, 0x1e, 0x70, 0x72, 0x65, 0x76, 0x69, 0x6f, 0x75, 0x73, 0x50, 0x65,
- 0x6e, 0x64, 0x69, 0x6e, 0x67, 0x54, 0x72, 0x65, 0x65, 0x57, 0x61, 0x73,
- 0x49, 0x6d, 0x70, 0x6c, 0x53, 0x69, 0x64, 0x65, 0x12, 0x5f, 0x0a, 0x2d,
- 0x70, 0x72, 0x6f, 0x63, 0x65, 0x73, 0x73, 0x69, 0x6e, 0x67, 0x5f, 0x61,
- 0x6e, 0x69, 0x6d, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x77, 0x6f, 0x72,
- 0x6b, 0x6c, 0x65, 0x74, 0x73, 0x5f, 0x66, 0x6f, 0x72, 0x5f, 0x61, 0x63,
- 0x74, 0x69, 0x76, 0x65, 0x5f, 0x74, 0x72, 0x65, 0x65, 0x18, 0x2c, 0x20,
- 0x01, 0x28, 0x08, 0x52, 0x28, 0x70, 0x72, 0x6f, 0x63, 0x65, 0x73, 0x73,
- 0x69, 0x6e, 0x67, 0x41, 0x6e, 0x69, 0x6d, 0x61, 0x74, 0x69, 0x6f, 0x6e,
- 0x57, 0x6f, 0x72, 0x6b, 0x6c, 0x65, 0x74, 0x73, 0x46, 0x6f, 0x72, 0x41,
- 0x63, 0x74, 0x69, 0x76, 0x65, 0x54, 0x72, 0x65, 0x65, 0x12, 0x61, 0x0a,
- 0x2e, 0x70, 0x72, 0x6f, 0x63, 0x65, 0x73, 0x73, 0x69, 0x6e, 0x67, 0x5f,
- 0x61, 0x6e, 0x69, 0x6d, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x77, 0x6f,
- 0x72, 0x6b, 0x6c, 0x65, 0x74, 0x73, 0x5f, 0x66, 0x6f, 0x72, 0x5f, 0x70,
- 0x65, 0x6e, 0x64, 0x69, 0x6e, 0x67, 0x5f, 0x74, 0x72, 0x65, 0x65, 0x18,
- 0x2d, 0x20, 0x01, 0x28, 0x08, 0x52, 0x29, 0x70, 0x72, 0x6f, 0x63, 0x65,
- 0x73, 0x73, 0x69, 0x6e, 0x67, 0x41, 0x6e, 0x69, 0x6d, 0x61, 0x74, 0x69,
- 0x6f, 0x6e, 0x57, 0x6f, 0x72, 0x6b, 0x6c, 0x65, 0x74, 0x73, 0x46, 0x6f,
- 0x72, 0x50, 0x65, 0x6e, 0x64, 0x69, 0x6e, 0x67, 0x54, 0x72, 0x65, 0x65,
- 0x12, 0x59, 0x0a, 0x2a, 0x70, 0x72, 0x6f, 0x63, 0x65, 0x73, 0x73, 0x69,
- 0x6e, 0x67, 0x5f, 0x70, 0x61, 0x69, 0x6e, 0x74, 0x5f, 0x77, 0x6f, 0x72,
- 0x6b, 0x6c, 0x65, 0x74, 0x73, 0x5f, 0x66, 0x6f, 0x72, 0x5f, 0x70, 0x65,
- 0x6e, 0x64, 0x69, 0x6e, 0x67, 0x5f, 0x74, 0x72, 0x65, 0x65, 0x18, 0x2e,
- 0x20, 0x01, 0x28, 0x08, 0x52, 0x25, 0x70, 0x72, 0x6f, 0x63, 0x65, 0x73,
- 0x73, 0x69, 0x6e, 0x67, 0x50, 0x61, 0x69, 0x6e, 0x74, 0x57, 0x6f, 0x72,
- 0x6b, 0x6c, 0x65, 0x74, 0x73, 0x46, 0x6f, 0x72, 0x50, 0x65, 0x6e, 0x64,
- 0x69, 0x6e, 0x67, 0x54, 0x72, 0x65, 0x65, 0x22, 0xb8, 0x01, 0x0a, 0x0c,
- 0x54, 0x72, 0x65, 0x65, 0x50, 0x72, 0x69, 0x6f, 0x72, 0x69, 0x74, 0x79,
- 0x12, 0x1d, 0x0a, 0x19, 0x54, 0x52, 0x45, 0x45, 0x5f, 0x50, 0x52, 0x49,
- 0x4f, 0x52, 0x49, 0x54, 0x59, 0x5f, 0x55, 0x4e, 0x53, 0x50, 0x45, 0x43,
- 0x49, 0x46, 0x49, 0x45, 0x44, 0x10, 0x00, 0x12, 0x2e, 0x0a, 0x2a, 0x54,
- 0x52, 0x45, 0x45, 0x5f, 0x50, 0x52, 0x49, 0x4f, 0x52, 0x49, 0x54, 0x59,
- 0x5f, 0x53, 0x41, 0x4d, 0x45, 0x5f, 0x50, 0x52, 0x49, 0x4f, 0x52, 0x49,
- 0x54, 0x59, 0x5f, 0x46, 0x4f, 0x52, 0x5f, 0x42, 0x4f, 0x54, 0x48, 0x5f,
- 0x54, 0x52, 0x45, 0x45, 0x53, 0x10, 0x01, 0x12, 0x2b, 0x0a, 0x27, 0x54,
- 0x52, 0x45, 0x45, 0x5f, 0x50, 0x52, 0x49, 0x4f, 0x52, 0x49, 0x54, 0x59,
- 0x5f, 0x53, 0x4d, 0x4f, 0x4f, 0x54, 0x48, 0x4e, 0x45, 0x53, 0x53, 0x5f,
- 0x54, 0x41, 0x4b, 0x45, 0x53, 0x5f, 0x50, 0x52, 0x49, 0x4f, 0x52, 0x49,
- 0x54, 0x59, 0x10, 0x02, 0x12, 0x2c, 0x0a, 0x28, 0x54, 0x52, 0x45, 0x45,
- 0x5f, 0x50, 0x52, 0x49, 0x4f, 0x52, 0x49, 0x54, 0x59, 0x5f, 0x4e, 0x45,
- 0x57, 0x5f, 0x43, 0x4f, 0x4e, 0x54, 0x45, 0x4e, 0x54, 0x5f, 0x54, 0x41,
- 0x4b, 0x45, 0x53, 0x5f, 0x50, 0x52, 0x49, 0x4f, 0x52, 0x49, 0x54, 0x59,
- 0x10, 0x03, 0x22, 0x82, 0x01, 0x0a, 0x12, 0x53, 0x63, 0x72, 0x6f, 0x6c,
- 0x6c, 0x48, 0x61, 0x6e, 0x64, 0x6c, 0x65, 0x72, 0x53, 0x74, 0x61, 0x74,
- 0x65, 0x12, 0x1e, 0x0a, 0x1a, 0x53, 0x43, 0x52, 0x4f, 0x4c, 0x4c, 0x5f,
- 0x48, 0x41, 0x4e, 0x44, 0x4c, 0x45, 0x52, 0x5f, 0x55, 0x4e, 0x53, 0x50,
- 0x45, 0x43, 0x49, 0x46, 0x49, 0x45, 0x44, 0x10, 0x00, 0x12, 0x21, 0x0a,
- 0x1d, 0x53, 0x43, 0x52, 0x4f, 0x4c, 0x4c, 0x5f, 0x41, 0x46, 0x46, 0x45,
- 0x43, 0x54, 0x53, 0x5f, 0x53, 0x43, 0x52, 0x4f, 0x4c, 0x4c, 0x5f, 0x48,
- 0x41, 0x4e, 0x44, 0x4c, 0x45, 0x52, 0x10, 0x01, 0x12, 0x29, 0x0a, 0x25,
- 0x53, 0x43, 0x52, 0x4f, 0x4c, 0x4c, 0x5f, 0x44, 0x4f, 0x45, 0x53, 0x5f,
- 0x4e, 0x4f, 0x54, 0x5f, 0x41, 0x46, 0x46, 0x45, 0x43, 0x54, 0x5f, 0x53,
- 0x43, 0x52, 0x4f, 0x4c, 0x4c, 0x5f, 0x48, 0x41, 0x4e, 0x44, 0x4c, 0x45,
- 0x52, 0x10, 0x02, 0x22, 0x8f, 0x05, 0x0a, 0x0e, 0x42, 0x65, 0x67, 0x69,
- 0x6e, 0x46, 0x72, 0x61, 0x6d, 0x65, 0x41, 0x72, 0x67, 0x73, 0x12, 0x46,
- 0x0a, 0x04, 0x74, 0x79, 0x70, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0e,
- 0x32, 0x32, 0x2e, 0x70, 0x65, 0x72, 0x66, 0x65, 0x74, 0x74, 0x6f, 0x2e,
- 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2e, 0x42, 0x65, 0x67, 0x69, 0x6e,
- 0x46, 0x72, 0x61, 0x6d, 0x65, 0x41, 0x72, 0x67, 0x73, 0x2e, 0x42, 0x65,
- 0x67, 0x69, 0x6e, 0x46, 0x72, 0x61, 0x6d, 0x65, 0x41, 0x72, 0x67, 0x73,
- 0x54, 0x79, 0x70, 0x65, 0x52, 0x04, 0x74, 0x79, 0x70, 0x65, 0x12, 0x1b,
- 0x0a, 0x09, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x5f, 0x69, 0x64, 0x18,
- 0x02, 0x20, 0x01, 0x28, 0x04, 0x52, 0x08, 0x73, 0x6f, 0x75, 0x72, 0x63,
- 0x65, 0x49, 0x64, 0x12, 0x27, 0x0a, 0x0f, 0x73, 0x65, 0x71, 0x75, 0x65,
- 0x6e, 0x63, 0x65, 0x5f, 0x6e, 0x75, 0x6d, 0x62, 0x65, 0x72, 0x18, 0x03,
- 0x20, 0x01, 0x28, 0x04, 0x52, 0x0e, 0x73, 0x65, 0x71, 0x75, 0x65, 0x6e,
- 0x63, 0x65, 0x4e, 0x75, 0x6d, 0x62, 0x65, 0x72, 0x12, 0x22, 0x0a, 0x0d,
- 0x66, 0x72, 0x61, 0x6d, 0x65, 0x5f, 0x74, 0x69, 0x6d, 0x65, 0x5f, 0x75,
- 0x73, 0x18, 0x04, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0b, 0x66, 0x72, 0x61,
- 0x6d, 0x65, 0x54, 0x69, 0x6d, 0x65, 0x55, 0x73, 0x12, 0x1f, 0x0a, 0x0b,
- 0x64, 0x65, 0x61, 0x64, 0x6c, 0x69, 0x6e, 0x65, 0x5f, 0x75, 0x73, 0x18,
- 0x05, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0a, 0x64, 0x65, 0x61, 0x64, 0x6c,
- 0x69, 0x6e, 0x65, 0x55, 0x73, 0x12, 0x2a, 0x0a, 0x11, 0x69, 0x6e, 0x74,
- 0x65, 0x72, 0x76, 0x61, 0x6c, 0x5f, 0x64, 0x65, 0x6c, 0x74, 0x61, 0x5f,
- 0x75, 0x73, 0x18, 0x06, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0f, 0x69, 0x6e,
- 0x74, 0x65, 0x72, 0x76, 0x61, 0x6c, 0x44, 0x65, 0x6c, 0x74, 0x61, 0x55,
- 0x73, 0x12, 0x28, 0x0a, 0x10, 0x6f, 0x6e, 0x5f, 0x63, 0x72, 0x69, 0x74,
- 0x69, 0x63, 0x61, 0x6c, 0x5f, 0x70, 0x61, 0x74, 0x68, 0x18, 0x07, 0x20,
- 0x01, 0x28, 0x08, 0x52, 0x0e, 0x6f, 0x6e, 0x43, 0x72, 0x69, 0x74, 0x69,
- 0x63, 0x61, 0x6c, 0x50, 0x61, 0x74, 0x68, 0x12, 0x21, 0x0a, 0x0c, 0x61,
- 0x6e, 0x69, 0x6d, 0x61, 0x74, 0x65, 0x5f, 0x6f, 0x6e, 0x6c, 0x79, 0x18,
- 0x08, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0b, 0x61, 0x6e, 0x69, 0x6d, 0x61,
- 0x74, 0x65, 0x4f, 0x6e, 0x6c, 0x79, 0x12, 0x30, 0x0a, 0x13, 0x73, 0x6f,
- 0x75, 0x72, 0x63, 0x65, 0x5f, 0x6c, 0x6f, 0x63, 0x61, 0x74, 0x69, 0x6f,
- 0x6e, 0x5f, 0x69, 0x69, 0x64, 0x18, 0x09, 0x20, 0x01, 0x28, 0x04, 0x48,
- 0x00, 0x52, 0x11, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x4c, 0x6f, 0x63,
- 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x49, 0x69, 0x64, 0x12, 0x4a, 0x0a, 0x0f,
- 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x5f, 0x6c, 0x6f, 0x63, 0x61, 0x74,
- 0x69, 0x6f, 0x6e, 0x18, 0x0a, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1f, 0x2e,
- 0x70, 0x65, 0x72, 0x66, 0x65, 0x74, 0x74, 0x6f, 0x2e, 0x70, 0x72, 0x6f,
- 0x74, 0x6f, 0x73, 0x2e, 0x53, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x4c, 0x6f,
- 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x48, 0x00, 0x52, 0x0e, 0x73, 0x6f,
- 0x75, 0x72, 0x63, 0x65, 0x4c, 0x6f, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e,
- 0x22, 0xa2, 0x01, 0x0a, 0x12, 0x42, 0x65, 0x67, 0x69, 0x6e, 0x46, 0x72,
- 0x61, 0x6d, 0x65, 0x41, 0x72, 0x67, 0x73, 0x54, 0x79, 0x70, 0x65, 0x12,
- 0x25, 0x0a, 0x21, 0x42, 0x45, 0x47, 0x49, 0x4e, 0x5f, 0x46, 0x52, 0x41,
- 0x4d, 0x45, 0x5f, 0x41, 0x52, 0x47, 0x53, 0x5f, 0x54, 0x59, 0x50, 0x45,
- 0x5f, 0x55, 0x4e, 0x53, 0x50, 0x45, 0x43, 0x49, 0x46, 0x49, 0x45, 0x44,
- 0x10, 0x00, 0x12, 0x21, 0x0a, 0x1d, 0x42, 0x45, 0x47, 0x49, 0x4e, 0x5f,
- 0x46, 0x52, 0x41, 0x4d, 0x45, 0x5f, 0x41, 0x52, 0x47, 0x53, 0x5f, 0x54,
- 0x59, 0x50, 0x45, 0x5f, 0x49, 0x4e, 0x56, 0x41, 0x4c, 0x49, 0x44, 0x10,
- 0x01, 0x12, 0x20, 0x0a, 0x1c, 0x42, 0x45, 0x47, 0x49, 0x4e, 0x5f, 0x46,
- 0x52, 0x41, 0x4d, 0x45, 0x5f, 0x41, 0x52, 0x47, 0x53, 0x5f, 0x54, 0x59,
- 0x50, 0x45, 0x5f, 0x4e, 0x4f, 0x52, 0x4d, 0x41, 0x4c, 0x10, 0x02, 0x12,
- 0x20, 0x0a, 0x1c, 0x42, 0x45, 0x47, 0x49, 0x4e, 0x5f, 0x46, 0x52, 0x41,
- 0x4d, 0x45, 0x5f, 0x41, 0x52, 0x47, 0x53, 0x5f, 0x54, 0x59, 0x50, 0x45,
- 0x5f, 0x4d, 0x49, 0x53, 0x53, 0x45, 0x44, 0x10, 0x03, 0x42, 0x0e, 0x0a,
- 0x0c, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x64, 0x5f, 0x66, 0x72, 0x6f,
- 0x6d, 0x22, 0xf5, 0x05, 0x0a, 0x12, 0x42, 0x65, 0x67, 0x69, 0x6e, 0x49,
- 0x6d, 0x70, 0x6c, 0x46, 0x72, 0x61, 0x6d, 0x65, 0x41, 0x72, 0x67, 0x73,
- 0x12, 0x22, 0x0a, 0x0d, 0x75, 0x70, 0x64, 0x61, 0x74, 0x65, 0x64, 0x5f,
- 0x61, 0x74, 0x5f, 0x75, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x03, 0x52,
- 0x0b, 0x75, 0x70, 0x64, 0x61, 0x74, 0x65, 0x64, 0x41, 0x74, 0x55, 0x73,
- 0x12, 0x24, 0x0a, 0x0e, 0x66, 0x69, 0x6e, 0x69, 0x73, 0x68, 0x65, 0x64,
- 0x5f, 0x61, 0x74, 0x5f, 0x75, 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x03,
- 0x52, 0x0c, 0x66, 0x69, 0x6e, 0x69, 0x73, 0x68, 0x65, 0x64, 0x41, 0x74,
- 0x55, 0x73, 0x12, 0x3f, 0x0a, 0x05, 0x73, 0x74, 0x61, 0x74, 0x65, 0x18,
- 0x03, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x29, 0x2e, 0x70, 0x65, 0x72, 0x66,
+ 0x6d, 0x65, 0x18, 0x25, 0x20, 0x01, 0x28, 0x08, 0x52, 0x13, 0x64, 0x65,
+ 0x66, 0x65, 0x72, 0x42, 0x65, 0x67, 0x69, 0x6e, 0x4d, 0x61, 0x69, 0x6e,
+ 0x46, 0x72, 0x61, 0x6d, 0x65, 0x12, 0x3a, 0x0a, 0x1a, 0x6c, 0x61, 0x73,
+ 0x74, 0x5f, 0x63, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x5f, 0x68, 0x61, 0x64,
+ 0x5f, 0x6e, 0x6f, 0x5f, 0x75, 0x70, 0x64, 0x61, 0x74, 0x65, 0x73, 0x18,
+ 0x26, 0x20, 0x01, 0x28, 0x08, 0x52, 0x16, 0x6c, 0x61, 0x73, 0x74, 0x43,
+ 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x48, 0x61, 0x64, 0x4e, 0x6f, 0x55, 0x70,
+ 0x64, 0x61, 0x74, 0x65, 0x73, 0x12, 0x32, 0x0a, 0x16, 0x64, 0x69, 0x64,
+ 0x5f, 0x64, 0x72, 0x61, 0x77, 0x5f, 0x69, 0x6e, 0x5f, 0x6c, 0x61, 0x73,
+ 0x74, 0x5f, 0x66, 0x72, 0x61, 0x6d, 0x65, 0x18, 0x27, 0x20, 0x01, 0x28,
+ 0x08, 0x52, 0x12, 0x64, 0x69, 0x64, 0x44, 0x72, 0x61, 0x77, 0x49, 0x6e,
+ 0x4c, 0x61, 0x73, 0x74, 0x46, 0x72, 0x61, 0x6d, 0x65, 0x12, 0x36, 0x0a,
+ 0x18, 0x64, 0x69, 0x64, 0x5f, 0x73, 0x75, 0x62, 0x6d, 0x69, 0x74, 0x5f,
+ 0x69, 0x6e, 0x5f, 0x6c, 0x61, 0x73, 0x74, 0x5f, 0x66, 0x72, 0x61, 0x6d,
+ 0x65, 0x18, 0x28, 0x20, 0x01, 0x28, 0x08, 0x52, 0x14, 0x64, 0x69, 0x64,
+ 0x53, 0x75, 0x62, 0x6d, 0x69, 0x74, 0x49, 0x6e, 0x4c, 0x61, 0x73, 0x74,
+ 0x46, 0x72, 0x61, 0x6d, 0x65, 0x12, 0x3f, 0x0a, 0x1c, 0x6e, 0x65, 0x65,
+ 0x64, 0x73, 0x5f, 0x69, 0x6d, 0x70, 0x6c, 0x5f, 0x73, 0x69, 0x64, 0x65,
+ 0x5f, 0x69, 0x6e, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x69, 0x6f,
+ 0x6e, 0x18, 0x29, 0x20, 0x01, 0x28, 0x08, 0x52, 0x19, 0x6e, 0x65, 0x65,
+ 0x64, 0x73, 0x49, 0x6d, 0x70, 0x6c, 0x53, 0x69, 0x64, 0x65, 0x49, 0x6e,
+ 0x76, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x47,
+ 0x0a, 0x21, 0x63, 0x75, 0x72, 0x72, 0x65, 0x6e, 0x74, 0x5f, 0x70, 0x65,
+ 0x6e, 0x64, 0x69, 0x6e, 0x67, 0x5f, 0x74, 0x72, 0x65, 0x65, 0x5f, 0x69,
+ 0x73, 0x5f, 0x69, 0x6d, 0x70, 0x6c, 0x5f, 0x73, 0x69, 0x64, 0x65, 0x18,
+ 0x2a, 0x20, 0x01, 0x28, 0x08, 0x52, 0x1c, 0x63, 0x75, 0x72, 0x72, 0x65,
+ 0x6e, 0x74, 0x50, 0x65, 0x6e, 0x64, 0x69, 0x6e, 0x67, 0x54, 0x72, 0x65,
+ 0x65, 0x49, 0x73, 0x49, 0x6d, 0x70, 0x6c, 0x53, 0x69, 0x64, 0x65, 0x12,
+ 0x4b, 0x0a, 0x23, 0x70, 0x72, 0x65, 0x76, 0x69, 0x6f, 0x75, 0x73, 0x5f,
+ 0x70, 0x65, 0x6e, 0x64, 0x69, 0x6e, 0x67, 0x5f, 0x74, 0x72, 0x65, 0x65,
+ 0x5f, 0x77, 0x61, 0x73, 0x5f, 0x69, 0x6d, 0x70, 0x6c, 0x5f, 0x73, 0x69,
+ 0x64, 0x65, 0x18, 0x2b, 0x20, 0x01, 0x28, 0x08, 0x52, 0x1e, 0x70, 0x72,
+ 0x65, 0x76, 0x69, 0x6f, 0x75, 0x73, 0x50, 0x65, 0x6e, 0x64, 0x69, 0x6e,
+ 0x67, 0x54, 0x72, 0x65, 0x65, 0x57, 0x61, 0x73, 0x49, 0x6d, 0x70, 0x6c,
+ 0x53, 0x69, 0x64, 0x65, 0x12, 0x5f, 0x0a, 0x2d, 0x70, 0x72, 0x6f, 0x63,
+ 0x65, 0x73, 0x73, 0x69, 0x6e, 0x67, 0x5f, 0x61, 0x6e, 0x69, 0x6d, 0x61,
+ 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x77, 0x6f, 0x72, 0x6b, 0x6c, 0x65, 0x74,
+ 0x73, 0x5f, 0x66, 0x6f, 0x72, 0x5f, 0x61, 0x63, 0x74, 0x69, 0x76, 0x65,
+ 0x5f, 0x74, 0x72, 0x65, 0x65, 0x18, 0x2c, 0x20, 0x01, 0x28, 0x08, 0x52,
+ 0x28, 0x70, 0x72, 0x6f, 0x63, 0x65, 0x73, 0x73, 0x69, 0x6e, 0x67, 0x41,
+ 0x6e, 0x69, 0x6d, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x57, 0x6f, 0x72, 0x6b,
+ 0x6c, 0x65, 0x74, 0x73, 0x46, 0x6f, 0x72, 0x41, 0x63, 0x74, 0x69, 0x76,
+ 0x65, 0x54, 0x72, 0x65, 0x65, 0x12, 0x61, 0x0a, 0x2e, 0x70, 0x72, 0x6f,
+ 0x63, 0x65, 0x73, 0x73, 0x69, 0x6e, 0x67, 0x5f, 0x61, 0x6e, 0x69, 0x6d,
+ 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x77, 0x6f, 0x72, 0x6b, 0x6c, 0x65,
+ 0x74, 0x73, 0x5f, 0x66, 0x6f, 0x72, 0x5f, 0x70, 0x65, 0x6e, 0x64, 0x69,
+ 0x6e, 0x67, 0x5f, 0x74, 0x72, 0x65, 0x65, 0x18, 0x2d, 0x20, 0x01, 0x28,
+ 0x08, 0x52, 0x29, 0x70, 0x72, 0x6f, 0x63, 0x65, 0x73, 0x73, 0x69, 0x6e,
+ 0x67, 0x41, 0x6e, 0x69, 0x6d, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x57, 0x6f,
+ 0x72, 0x6b, 0x6c, 0x65, 0x74, 0x73, 0x46, 0x6f, 0x72, 0x50, 0x65, 0x6e,
+ 0x64, 0x69, 0x6e, 0x67, 0x54, 0x72, 0x65, 0x65, 0x12, 0x59, 0x0a, 0x2a,
+ 0x70, 0x72, 0x6f, 0x63, 0x65, 0x73, 0x73, 0x69, 0x6e, 0x67, 0x5f, 0x70,
+ 0x61, 0x69, 0x6e, 0x74, 0x5f, 0x77, 0x6f, 0x72, 0x6b, 0x6c, 0x65, 0x74,
+ 0x73, 0x5f, 0x66, 0x6f, 0x72, 0x5f, 0x70, 0x65, 0x6e, 0x64, 0x69, 0x6e,
+ 0x67, 0x5f, 0x74, 0x72, 0x65, 0x65, 0x18, 0x2e, 0x20, 0x01, 0x28, 0x08,
+ 0x52, 0x25, 0x70, 0x72, 0x6f, 0x63, 0x65, 0x73, 0x73, 0x69, 0x6e, 0x67,
+ 0x50, 0x61, 0x69, 0x6e, 0x74, 0x57, 0x6f, 0x72, 0x6b, 0x6c, 0x65, 0x74,
+ 0x73, 0x46, 0x6f, 0x72, 0x50, 0x65, 0x6e, 0x64, 0x69, 0x6e, 0x67, 0x54,
+ 0x72, 0x65, 0x65, 0x22, 0xb8, 0x01, 0x0a, 0x0c, 0x54, 0x72, 0x65, 0x65,
+ 0x50, 0x72, 0x69, 0x6f, 0x72, 0x69, 0x74, 0x79, 0x12, 0x1d, 0x0a, 0x19,
+ 0x54, 0x52, 0x45, 0x45, 0x5f, 0x50, 0x52, 0x49, 0x4f, 0x52, 0x49, 0x54,
+ 0x59, 0x5f, 0x55, 0x4e, 0x53, 0x50, 0x45, 0x43, 0x49, 0x46, 0x49, 0x45,
+ 0x44, 0x10, 0x00, 0x12, 0x2e, 0x0a, 0x2a, 0x54, 0x52, 0x45, 0x45, 0x5f,
+ 0x50, 0x52, 0x49, 0x4f, 0x52, 0x49, 0x54, 0x59, 0x5f, 0x53, 0x41, 0x4d,
+ 0x45, 0x5f, 0x50, 0x52, 0x49, 0x4f, 0x52, 0x49, 0x54, 0x59, 0x5f, 0x46,
+ 0x4f, 0x52, 0x5f, 0x42, 0x4f, 0x54, 0x48, 0x5f, 0x54, 0x52, 0x45, 0x45,
+ 0x53, 0x10, 0x01, 0x12, 0x2b, 0x0a, 0x27, 0x54, 0x52, 0x45, 0x45, 0x5f,
+ 0x50, 0x52, 0x49, 0x4f, 0x52, 0x49, 0x54, 0x59, 0x5f, 0x53, 0x4d, 0x4f,
+ 0x4f, 0x54, 0x48, 0x4e, 0x45, 0x53, 0x53, 0x5f, 0x54, 0x41, 0x4b, 0x45,
+ 0x53, 0x5f, 0x50, 0x52, 0x49, 0x4f, 0x52, 0x49, 0x54, 0x59, 0x10, 0x02,
+ 0x12, 0x2c, 0x0a, 0x28, 0x54, 0x52, 0x45, 0x45, 0x5f, 0x50, 0x52, 0x49,
+ 0x4f, 0x52, 0x49, 0x54, 0x59, 0x5f, 0x4e, 0x45, 0x57, 0x5f, 0x43, 0x4f,
+ 0x4e, 0x54, 0x45, 0x4e, 0x54, 0x5f, 0x54, 0x41, 0x4b, 0x45, 0x53, 0x5f,
+ 0x50, 0x52, 0x49, 0x4f, 0x52, 0x49, 0x54, 0x59, 0x10, 0x03, 0x22, 0x82,
+ 0x01, 0x0a, 0x12, 0x53, 0x63, 0x72, 0x6f, 0x6c, 0x6c, 0x48, 0x61, 0x6e,
+ 0x64, 0x6c, 0x65, 0x72, 0x53, 0x74, 0x61, 0x74, 0x65, 0x12, 0x1e, 0x0a,
+ 0x1a, 0x53, 0x43, 0x52, 0x4f, 0x4c, 0x4c, 0x5f, 0x48, 0x41, 0x4e, 0x44,
+ 0x4c, 0x45, 0x52, 0x5f, 0x55, 0x4e, 0x53, 0x50, 0x45, 0x43, 0x49, 0x46,
+ 0x49, 0x45, 0x44, 0x10, 0x00, 0x12, 0x21, 0x0a, 0x1d, 0x53, 0x43, 0x52,
+ 0x4f, 0x4c, 0x4c, 0x5f, 0x41, 0x46, 0x46, 0x45, 0x43, 0x54, 0x53, 0x5f,
+ 0x53, 0x43, 0x52, 0x4f, 0x4c, 0x4c, 0x5f, 0x48, 0x41, 0x4e, 0x44, 0x4c,
+ 0x45, 0x52, 0x10, 0x01, 0x12, 0x29, 0x0a, 0x25, 0x53, 0x43, 0x52, 0x4f,
+ 0x4c, 0x4c, 0x5f, 0x44, 0x4f, 0x45, 0x53, 0x5f, 0x4e, 0x4f, 0x54, 0x5f,
+ 0x41, 0x46, 0x46, 0x45, 0x43, 0x54, 0x5f, 0x53, 0x43, 0x52, 0x4f, 0x4c,
+ 0x4c, 0x5f, 0x48, 0x41, 0x4e, 0x44, 0x4c, 0x45, 0x52, 0x10, 0x02, 0x22,
+ 0x8f, 0x05, 0x0a, 0x0e, 0x42, 0x65, 0x67, 0x69, 0x6e, 0x46, 0x72, 0x61,
+ 0x6d, 0x65, 0x41, 0x72, 0x67, 0x73, 0x12, 0x46, 0x0a, 0x04, 0x74, 0x79,
+ 0x70, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x32, 0x2e, 0x70,
+ 0x65, 0x72, 0x66, 0x65, 0x74, 0x74, 0x6f, 0x2e, 0x70, 0x72, 0x6f, 0x74,
+ 0x6f, 0x73, 0x2e, 0x42, 0x65, 0x67, 0x69, 0x6e, 0x46, 0x72, 0x61, 0x6d,
+ 0x65, 0x41, 0x72, 0x67, 0x73, 0x2e, 0x42, 0x65, 0x67, 0x69, 0x6e, 0x46,
+ 0x72, 0x61, 0x6d, 0x65, 0x41, 0x72, 0x67, 0x73, 0x54, 0x79, 0x70, 0x65,
+ 0x52, 0x04, 0x74, 0x79, 0x70, 0x65, 0x12, 0x1b, 0x0a, 0x09, 0x73, 0x6f,
+ 0x75, 0x72, 0x63, 0x65, 0x5f, 0x69, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28,
+ 0x04, 0x52, 0x08, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x49, 0x64, 0x12,
+ 0x27, 0x0a, 0x0f, 0x73, 0x65, 0x71, 0x75, 0x65, 0x6e, 0x63, 0x65, 0x5f,
+ 0x6e, 0x75, 0x6d, 0x62, 0x65, 0x72, 0x18, 0x03, 0x20, 0x01, 0x28, 0x04,
+ 0x52, 0x0e, 0x73, 0x65, 0x71, 0x75, 0x65, 0x6e, 0x63, 0x65, 0x4e, 0x75,
+ 0x6d, 0x62, 0x65, 0x72, 0x12, 0x22, 0x0a, 0x0d, 0x66, 0x72, 0x61, 0x6d,
+ 0x65, 0x5f, 0x74, 0x69, 0x6d, 0x65, 0x5f, 0x75, 0x73, 0x18, 0x04, 0x20,
+ 0x01, 0x28, 0x03, 0x52, 0x0b, 0x66, 0x72, 0x61, 0x6d, 0x65, 0x54, 0x69,
+ 0x6d, 0x65, 0x55, 0x73, 0x12, 0x1f, 0x0a, 0x0b, 0x64, 0x65, 0x61, 0x64,
+ 0x6c, 0x69, 0x6e, 0x65, 0x5f, 0x75, 0x73, 0x18, 0x05, 0x20, 0x01, 0x28,
+ 0x03, 0x52, 0x0a, 0x64, 0x65, 0x61, 0x64, 0x6c, 0x69, 0x6e, 0x65, 0x55,
+ 0x73, 0x12, 0x2a, 0x0a, 0x11, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x76, 0x61,
+ 0x6c, 0x5f, 0x64, 0x65, 0x6c, 0x74, 0x61, 0x5f, 0x75, 0x73, 0x18, 0x06,
+ 0x20, 0x01, 0x28, 0x03, 0x52, 0x0f, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x76,
+ 0x61, 0x6c, 0x44, 0x65, 0x6c, 0x74, 0x61, 0x55, 0x73, 0x12, 0x28, 0x0a,
+ 0x10, 0x6f, 0x6e, 0x5f, 0x63, 0x72, 0x69, 0x74, 0x69, 0x63, 0x61, 0x6c,
+ 0x5f, 0x70, 0x61, 0x74, 0x68, 0x18, 0x07, 0x20, 0x01, 0x28, 0x08, 0x52,
+ 0x0e, 0x6f, 0x6e, 0x43, 0x72, 0x69, 0x74, 0x69, 0x63, 0x61, 0x6c, 0x50,
+ 0x61, 0x74, 0x68, 0x12, 0x21, 0x0a, 0x0c, 0x61, 0x6e, 0x69, 0x6d, 0x61,
+ 0x74, 0x65, 0x5f, 0x6f, 0x6e, 0x6c, 0x79, 0x18, 0x08, 0x20, 0x01, 0x28,
+ 0x08, 0x52, 0x0b, 0x61, 0x6e, 0x69, 0x6d, 0x61, 0x74, 0x65, 0x4f, 0x6e,
+ 0x6c, 0x79, 0x12, 0x30, 0x0a, 0x13, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65,
+ 0x5f, 0x6c, 0x6f, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x69, 0x69,
+ 0x64, 0x18, 0x09, 0x20, 0x01, 0x28, 0x04, 0x48, 0x00, 0x52, 0x11, 0x73,
+ 0x6f, 0x75, 0x72, 0x63, 0x65, 0x4c, 0x6f, 0x63, 0x61, 0x74, 0x69, 0x6f,
+ 0x6e, 0x49, 0x69, 0x64, 0x12, 0x4a, 0x0a, 0x0f, 0x73, 0x6f, 0x75, 0x72,
+ 0x63, 0x65, 0x5f, 0x6c, 0x6f, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x18,
+ 0x0a, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1f, 0x2e, 0x70, 0x65, 0x72, 0x66,
0x65, 0x74, 0x74, 0x6f, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2e,
- 0x42, 0x65, 0x67, 0x69, 0x6e, 0x49, 0x6d, 0x70, 0x6c, 0x46, 0x72, 0x61,
- 0x6d, 0x65, 0x41, 0x72, 0x67, 0x73, 0x2e, 0x53, 0x74, 0x61, 0x74, 0x65,
- 0x52, 0x05, 0x73, 0x74, 0x61, 0x74, 0x65, 0x12, 0x44, 0x0a, 0x0c, 0x63,
- 0x75, 0x72, 0x72, 0x65, 0x6e, 0x74, 0x5f, 0x61, 0x72, 0x67, 0x73, 0x18,
- 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1f, 0x2e, 0x70, 0x65, 0x72, 0x66,
- 0x65, 0x74, 0x74, 0x6f, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2e,
- 0x42, 0x65, 0x67, 0x69, 0x6e, 0x46, 0x72, 0x61, 0x6d, 0x65, 0x41, 0x72,
- 0x67, 0x73, 0x48, 0x00, 0x52, 0x0b, 0x63, 0x75, 0x72, 0x72, 0x65, 0x6e,
- 0x74, 0x41, 0x72, 0x67, 0x73, 0x12, 0x3e, 0x0a, 0x09, 0x6c, 0x61, 0x73,
- 0x74, 0x5f, 0x61, 0x72, 0x67, 0x73, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0b,
- 0x32, 0x1f, 0x2e, 0x70, 0x65, 0x72, 0x66, 0x65, 0x74, 0x74, 0x6f, 0x2e,
- 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2e, 0x42, 0x65, 0x67, 0x69, 0x6e,
- 0x46, 0x72, 0x61, 0x6d, 0x65, 0x41, 0x72, 0x67, 0x73, 0x48, 0x00, 0x52,
- 0x08, 0x6c, 0x61, 0x73, 0x74, 0x41, 0x72, 0x67, 0x73, 0x12, 0x5c, 0x0a,
- 0x10, 0x74, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x73, 0x5f,
- 0x69, 0x6e, 0x5f, 0x75, 0x73, 0x18, 0x06, 0x20, 0x01, 0x28, 0x0b, 0x32,
- 0x32, 0x2e, 0x70, 0x65, 0x72, 0x66, 0x65, 0x74, 0x74, 0x6f, 0x2e, 0x70,
- 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2e, 0x42, 0x65, 0x67, 0x69, 0x6e, 0x49,
- 0x6d, 0x70, 0x6c, 0x46, 0x72, 0x61, 0x6d, 0x65, 0x41, 0x72, 0x67, 0x73,
- 0x2e, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x73, 0x49,
- 0x6e, 0x55, 0x73, 0x52, 0x0e, 0x74, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61,
- 0x6d, 0x70, 0x73, 0x49, 0x6e, 0x55, 0x73, 0x1a, 0xad, 0x02, 0x0a, 0x0e,
- 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x73, 0x49, 0x6e,
- 0x55, 0x73, 0x12, 0x25, 0x0a, 0x0e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x76,
- 0x61, 0x6c, 0x5f, 0x64, 0x65, 0x6c, 0x74, 0x61, 0x18, 0x01, 0x20, 0x01,
- 0x28, 0x03, 0x52, 0x0d, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x76, 0x61, 0x6c,
- 0x44, 0x65, 0x6c, 0x74, 0x61, 0x12, 0x31, 0x0a, 0x15, 0x6e, 0x6f, 0x77,
- 0x5f, 0x74, 0x6f, 0x5f, 0x64, 0x65, 0x61, 0x64, 0x6c, 0x69, 0x6e, 0x65,
- 0x5f, 0x64, 0x65, 0x6c, 0x74, 0x61, 0x18, 0x02, 0x20, 0x01, 0x28, 0x03,
- 0x52, 0x12, 0x6e, 0x6f, 0x77, 0x54, 0x6f, 0x44, 0x65, 0x61, 0x64, 0x6c,
- 0x69, 0x6e, 0x65, 0x44, 0x65, 0x6c, 0x74, 0x61, 0x12, 0x34, 0x0a, 0x17,
- 0x66, 0x72, 0x61, 0x6d, 0x65, 0x5f, 0x74, 0x69, 0x6d, 0x65, 0x5f, 0x74,
- 0x6f, 0x5f, 0x6e, 0x6f, 0x77, 0x5f, 0x64, 0x65, 0x6c, 0x74, 0x61, 0x18,
- 0x03, 0x20, 0x01, 0x28, 0x03, 0x52, 0x13, 0x66, 0x72, 0x61, 0x6d, 0x65,
- 0x54, 0x69, 0x6d, 0x65, 0x54, 0x6f, 0x4e, 0x6f, 0x77, 0x44, 0x65, 0x6c,
- 0x74, 0x61, 0x12, 0x3e, 0x0a, 0x1c, 0x66, 0x72, 0x61, 0x6d, 0x65, 0x5f,
- 0x74, 0x69, 0x6d, 0x65, 0x5f, 0x74, 0x6f, 0x5f, 0x64, 0x65, 0x61, 0x64,
- 0x6c, 0x69, 0x6e, 0x65, 0x5f, 0x64, 0x65, 0x6c, 0x74, 0x61, 0x18, 0x04,
- 0x20, 0x01, 0x28, 0x03, 0x52, 0x18, 0x66, 0x72, 0x61, 0x6d, 0x65, 0x54,
- 0x69, 0x6d, 0x65, 0x54, 0x6f, 0x44, 0x65, 0x61, 0x64, 0x6c, 0x69, 0x6e,
- 0x65, 0x44, 0x65, 0x6c, 0x74, 0x61, 0x12, 0x10, 0x0a, 0x03, 0x6e, 0x6f,
- 0x77, 0x18, 0x05, 0x20, 0x01, 0x28, 0x03, 0x52, 0x03, 0x6e, 0x6f, 0x77,
- 0x12, 0x1d, 0x0a, 0x0a, 0x66, 0x72, 0x61, 0x6d, 0x65, 0x5f, 0x74, 0x69,
- 0x6d, 0x65, 0x18, 0x06, 0x20, 0x01, 0x28, 0x03, 0x52, 0x09, 0x66, 0x72,
- 0x61, 0x6d, 0x65, 0x54, 0x69, 0x6d, 0x65, 0x12, 0x1a, 0x0a, 0x08, 0x64,
- 0x65, 0x61, 0x64, 0x6c, 0x69, 0x6e, 0x65, 0x18, 0x07, 0x20, 0x01, 0x28,
- 0x03, 0x52, 0x08, 0x64, 0x65, 0x61, 0x64, 0x6c, 0x69, 0x6e, 0x65, 0x22,
- 0x38, 0x0a, 0x05, 0x53, 0x74, 0x61, 0x74, 0x65, 0x12, 0x18, 0x0a, 0x14,
- 0x42, 0x45, 0x47, 0x49, 0x4e, 0x5f, 0x46, 0x52, 0x41, 0x4d, 0x45, 0x5f,
- 0x46, 0x49, 0x4e, 0x49, 0x53, 0x48, 0x45, 0x44, 0x10, 0x00, 0x12, 0x15,
- 0x0a, 0x11, 0x42, 0x45, 0x47, 0x49, 0x4e, 0x5f, 0x46, 0x52, 0x41, 0x4d,
- 0x45, 0x5f, 0x55, 0x53, 0x49, 0x4e, 0x47, 0x10, 0x01, 0x42, 0x06, 0x0a,
- 0x04, 0x61, 0x72, 0x67, 0x73, 0x22, 0xa6, 0x01, 0x0a, 0x17, 0x42, 0x65,
- 0x67, 0x69, 0x6e, 0x46, 0x72, 0x61, 0x6d, 0x65, 0x4f, 0x62, 0x73, 0x65,
- 0x72, 0x76, 0x65, 0x72, 0x53, 0x74, 0x61, 0x74, 0x65, 0x12, 0x37, 0x0a,
- 0x18, 0x64, 0x72, 0x6f, 0x70, 0x70, 0x65, 0x64, 0x5f, 0x62, 0x65, 0x67,
- 0x69, 0x6e, 0x5f, 0x66, 0x72, 0x61, 0x6d, 0x65, 0x5f, 0x61, 0x72, 0x67,
- 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x03, 0x52, 0x15, 0x64, 0x72, 0x6f,
- 0x70, 0x70, 0x65, 0x64, 0x42, 0x65, 0x67, 0x69, 0x6e, 0x46, 0x72, 0x61,
- 0x6d, 0x65, 0x41, 0x72, 0x67, 0x73, 0x12, 0x52, 0x0a, 0x15, 0x6c, 0x61,
- 0x73, 0x74, 0x5f, 0x62, 0x65, 0x67, 0x69, 0x6e, 0x5f, 0x66, 0x72, 0x61,
- 0x6d, 0x65, 0x5f, 0x61, 0x72, 0x67, 0x73, 0x18, 0x02, 0x20, 0x01, 0x28,
+ 0x53, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x4c, 0x6f, 0x63, 0x61, 0x74, 0x69,
+ 0x6f, 0x6e, 0x48, 0x00, 0x52, 0x0e, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65,
+ 0x4c, 0x6f, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x22, 0xa2, 0x01, 0x0a,
+ 0x12, 0x42, 0x65, 0x67, 0x69, 0x6e, 0x46, 0x72, 0x61, 0x6d, 0x65, 0x41,
+ 0x72, 0x67, 0x73, 0x54, 0x79, 0x70, 0x65, 0x12, 0x25, 0x0a, 0x21, 0x42,
+ 0x45, 0x47, 0x49, 0x4e, 0x5f, 0x46, 0x52, 0x41, 0x4d, 0x45, 0x5f, 0x41,
+ 0x52, 0x47, 0x53, 0x5f, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x55, 0x4e, 0x53,
+ 0x50, 0x45, 0x43, 0x49, 0x46, 0x49, 0x45, 0x44, 0x10, 0x00, 0x12, 0x21,
+ 0x0a, 0x1d, 0x42, 0x45, 0x47, 0x49, 0x4e, 0x5f, 0x46, 0x52, 0x41, 0x4d,
+ 0x45, 0x5f, 0x41, 0x52, 0x47, 0x53, 0x5f, 0x54, 0x59, 0x50, 0x45, 0x5f,
+ 0x49, 0x4e, 0x56, 0x41, 0x4c, 0x49, 0x44, 0x10, 0x01, 0x12, 0x20, 0x0a,
+ 0x1c, 0x42, 0x45, 0x47, 0x49, 0x4e, 0x5f, 0x46, 0x52, 0x41, 0x4d, 0x45,
+ 0x5f, 0x41, 0x52, 0x47, 0x53, 0x5f, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x4e,
+ 0x4f, 0x52, 0x4d, 0x41, 0x4c, 0x10, 0x02, 0x12, 0x20, 0x0a, 0x1c, 0x42,
+ 0x45, 0x47, 0x49, 0x4e, 0x5f, 0x46, 0x52, 0x41, 0x4d, 0x45, 0x5f, 0x41,
+ 0x52, 0x47, 0x53, 0x5f, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x4d, 0x49, 0x53,
+ 0x53, 0x45, 0x44, 0x10, 0x03, 0x42, 0x0e, 0x0a, 0x0c, 0x63, 0x72, 0x65,
+ 0x61, 0x74, 0x65, 0x64, 0x5f, 0x66, 0x72, 0x6f, 0x6d, 0x22, 0xf5, 0x05,
+ 0x0a, 0x12, 0x42, 0x65, 0x67, 0x69, 0x6e, 0x49, 0x6d, 0x70, 0x6c, 0x46,
+ 0x72, 0x61, 0x6d, 0x65, 0x41, 0x72, 0x67, 0x73, 0x12, 0x22, 0x0a, 0x0d,
+ 0x75, 0x70, 0x64, 0x61, 0x74, 0x65, 0x64, 0x5f, 0x61, 0x74, 0x5f, 0x75,
+ 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0b, 0x75, 0x70, 0x64,
+ 0x61, 0x74, 0x65, 0x64, 0x41, 0x74, 0x55, 0x73, 0x12, 0x24, 0x0a, 0x0e,
+ 0x66, 0x69, 0x6e, 0x69, 0x73, 0x68, 0x65, 0x64, 0x5f, 0x61, 0x74, 0x5f,
+ 0x75, 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0c, 0x66, 0x69,
+ 0x6e, 0x69, 0x73, 0x68, 0x65, 0x64, 0x41, 0x74, 0x55, 0x73, 0x12, 0x3f,
+ 0x0a, 0x05, 0x73, 0x74, 0x61, 0x74, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28,
+ 0x0e, 0x32, 0x29, 0x2e, 0x70, 0x65, 0x72, 0x66, 0x65, 0x74, 0x74, 0x6f,
+ 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2e, 0x42, 0x65, 0x67, 0x69,
+ 0x6e, 0x49, 0x6d, 0x70, 0x6c, 0x46, 0x72, 0x61, 0x6d, 0x65, 0x41, 0x72,
+ 0x67, 0x73, 0x2e, 0x53, 0x74, 0x61, 0x74, 0x65, 0x52, 0x05, 0x73, 0x74,
+ 0x61, 0x74, 0x65, 0x12, 0x44, 0x0a, 0x0c, 0x63, 0x75, 0x72, 0x72, 0x65,
+ 0x6e, 0x74, 0x5f, 0x61, 0x72, 0x67, 0x73, 0x18, 0x04, 0x20, 0x01, 0x28,
0x0b, 0x32, 0x1f, 0x2e, 0x70, 0x65, 0x72, 0x66, 0x65, 0x74, 0x74, 0x6f,
0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2e, 0x42, 0x65, 0x67, 0x69,
- 0x6e, 0x46, 0x72, 0x61, 0x6d, 0x65, 0x41, 0x72, 0x67, 0x73, 0x52, 0x12,
- 0x6c, 0x61, 0x73, 0x74, 0x42, 0x65, 0x67, 0x69, 0x6e, 0x46, 0x72, 0x61,
- 0x6d, 0x65, 0x41, 0x72, 0x67, 0x73, 0x22, 0xc5, 0x01, 0x0a, 0x15, 0x42,
- 0x65, 0x67, 0x69, 0x6e, 0x46, 0x72, 0x61, 0x6d, 0x65, 0x53, 0x6f, 0x75,
- 0x72, 0x63, 0x65, 0x53, 0x74, 0x61, 0x74, 0x65, 0x12, 0x1b, 0x0a, 0x09,
- 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20,
- 0x01, 0x28, 0x0d, 0x52, 0x08, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x49,
- 0x64, 0x12, 0x16, 0x0a, 0x06, 0x70, 0x61, 0x75, 0x73, 0x65, 0x64, 0x18,
- 0x02, 0x20, 0x01, 0x28, 0x08, 0x52, 0x06, 0x70, 0x61, 0x75, 0x73, 0x65,
- 0x64, 0x12, 0x23, 0x0a, 0x0d, 0x6e, 0x75, 0x6d, 0x5f, 0x6f, 0x62, 0x73,
- 0x65, 0x72, 0x76, 0x65, 0x72, 0x73, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0d,
- 0x52, 0x0c, 0x6e, 0x75, 0x6d, 0x4f, 0x62, 0x73, 0x65, 0x72, 0x76, 0x65,
- 0x72, 0x73, 0x12, 0x52, 0x0a, 0x15, 0x6c, 0x61, 0x73, 0x74, 0x5f, 0x62,
+ 0x6e, 0x46, 0x72, 0x61, 0x6d, 0x65, 0x41, 0x72, 0x67, 0x73, 0x48, 0x00,
+ 0x52, 0x0b, 0x63, 0x75, 0x72, 0x72, 0x65, 0x6e, 0x74, 0x41, 0x72, 0x67,
+ 0x73, 0x12, 0x3e, 0x0a, 0x09, 0x6c, 0x61, 0x73, 0x74, 0x5f, 0x61, 0x72,
+ 0x67, 0x73, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1f, 0x2e, 0x70,
+ 0x65, 0x72, 0x66, 0x65, 0x74, 0x74, 0x6f, 0x2e, 0x70, 0x72, 0x6f, 0x74,
+ 0x6f, 0x73, 0x2e, 0x42, 0x65, 0x67, 0x69, 0x6e, 0x46, 0x72, 0x61, 0x6d,
+ 0x65, 0x41, 0x72, 0x67, 0x73, 0x48, 0x00, 0x52, 0x08, 0x6c, 0x61, 0x73,
+ 0x74, 0x41, 0x72, 0x67, 0x73, 0x12, 0x5c, 0x0a, 0x10, 0x74, 0x69, 0x6d,
+ 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x73, 0x5f, 0x69, 0x6e, 0x5f, 0x75,
+ 0x73, 0x18, 0x06, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x32, 0x2e, 0x70, 0x65,
+ 0x72, 0x66, 0x65, 0x74, 0x74, 0x6f, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f,
+ 0x73, 0x2e, 0x42, 0x65, 0x67, 0x69, 0x6e, 0x49, 0x6d, 0x70, 0x6c, 0x46,
+ 0x72, 0x61, 0x6d, 0x65, 0x41, 0x72, 0x67, 0x73, 0x2e, 0x54, 0x69, 0x6d,
+ 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x73, 0x49, 0x6e, 0x55, 0x73, 0x52,
+ 0x0e, 0x74, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x73, 0x49,
+ 0x6e, 0x55, 0x73, 0x1a, 0xad, 0x02, 0x0a, 0x0e, 0x54, 0x69, 0x6d, 0x65,
+ 0x73, 0x74, 0x61, 0x6d, 0x70, 0x73, 0x49, 0x6e, 0x55, 0x73, 0x12, 0x25,
+ 0x0a, 0x0e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x76, 0x61, 0x6c, 0x5f, 0x64,
+ 0x65, 0x6c, 0x74, 0x61, 0x18, 0x01, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0d,
+ 0x69, 0x6e, 0x74, 0x65, 0x72, 0x76, 0x61, 0x6c, 0x44, 0x65, 0x6c, 0x74,
+ 0x61, 0x12, 0x31, 0x0a, 0x15, 0x6e, 0x6f, 0x77, 0x5f, 0x74, 0x6f, 0x5f,
+ 0x64, 0x65, 0x61, 0x64, 0x6c, 0x69, 0x6e, 0x65, 0x5f, 0x64, 0x65, 0x6c,
+ 0x74, 0x61, 0x18, 0x02, 0x20, 0x01, 0x28, 0x03, 0x52, 0x12, 0x6e, 0x6f,
+ 0x77, 0x54, 0x6f, 0x44, 0x65, 0x61, 0x64, 0x6c, 0x69, 0x6e, 0x65, 0x44,
+ 0x65, 0x6c, 0x74, 0x61, 0x12, 0x34, 0x0a, 0x17, 0x66, 0x72, 0x61, 0x6d,
+ 0x65, 0x5f, 0x74, 0x69, 0x6d, 0x65, 0x5f, 0x74, 0x6f, 0x5f, 0x6e, 0x6f,
+ 0x77, 0x5f, 0x64, 0x65, 0x6c, 0x74, 0x61, 0x18, 0x03, 0x20, 0x01, 0x28,
+ 0x03, 0x52, 0x13, 0x66, 0x72, 0x61, 0x6d, 0x65, 0x54, 0x69, 0x6d, 0x65,
+ 0x54, 0x6f, 0x4e, 0x6f, 0x77, 0x44, 0x65, 0x6c, 0x74, 0x61, 0x12, 0x3e,
+ 0x0a, 0x1c, 0x66, 0x72, 0x61, 0x6d, 0x65, 0x5f, 0x74, 0x69, 0x6d, 0x65,
+ 0x5f, 0x74, 0x6f, 0x5f, 0x64, 0x65, 0x61, 0x64, 0x6c, 0x69, 0x6e, 0x65,
+ 0x5f, 0x64, 0x65, 0x6c, 0x74, 0x61, 0x18, 0x04, 0x20, 0x01, 0x28, 0x03,
+ 0x52, 0x18, 0x66, 0x72, 0x61, 0x6d, 0x65, 0x54, 0x69, 0x6d, 0x65, 0x54,
+ 0x6f, 0x44, 0x65, 0x61, 0x64, 0x6c, 0x69, 0x6e, 0x65, 0x44, 0x65, 0x6c,
+ 0x74, 0x61, 0x12, 0x10, 0x0a, 0x03, 0x6e, 0x6f, 0x77, 0x18, 0x05, 0x20,
+ 0x01, 0x28, 0x03, 0x52, 0x03, 0x6e, 0x6f, 0x77, 0x12, 0x1d, 0x0a, 0x0a,
+ 0x66, 0x72, 0x61, 0x6d, 0x65, 0x5f, 0x74, 0x69, 0x6d, 0x65, 0x18, 0x06,
+ 0x20, 0x01, 0x28, 0x03, 0x52, 0x09, 0x66, 0x72, 0x61, 0x6d, 0x65, 0x54,
+ 0x69, 0x6d, 0x65, 0x12, 0x1a, 0x0a, 0x08, 0x64, 0x65, 0x61, 0x64, 0x6c,
+ 0x69, 0x6e, 0x65, 0x18, 0x07, 0x20, 0x01, 0x28, 0x03, 0x52, 0x08, 0x64,
+ 0x65, 0x61, 0x64, 0x6c, 0x69, 0x6e, 0x65, 0x22, 0x38, 0x0a, 0x05, 0x53,
+ 0x74, 0x61, 0x74, 0x65, 0x12, 0x18, 0x0a, 0x14, 0x42, 0x45, 0x47, 0x49,
+ 0x4e, 0x5f, 0x46, 0x52, 0x41, 0x4d, 0x45, 0x5f, 0x46, 0x49, 0x4e, 0x49,
+ 0x53, 0x48, 0x45, 0x44, 0x10, 0x00, 0x12, 0x15, 0x0a, 0x11, 0x42, 0x45,
+ 0x47, 0x49, 0x4e, 0x5f, 0x46, 0x52, 0x41, 0x4d, 0x45, 0x5f, 0x55, 0x53,
+ 0x49, 0x4e, 0x47, 0x10, 0x01, 0x42, 0x06, 0x0a, 0x04, 0x61, 0x72, 0x67,
+ 0x73, 0x22, 0xa6, 0x01, 0x0a, 0x17, 0x42, 0x65, 0x67, 0x69, 0x6e, 0x46,
+ 0x72, 0x61, 0x6d, 0x65, 0x4f, 0x62, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72,
+ 0x53, 0x74, 0x61, 0x74, 0x65, 0x12, 0x37, 0x0a, 0x18, 0x64, 0x72, 0x6f,
+ 0x70, 0x70, 0x65, 0x64, 0x5f, 0x62, 0x65, 0x67, 0x69, 0x6e, 0x5f, 0x66,
+ 0x72, 0x61, 0x6d, 0x65, 0x5f, 0x61, 0x72, 0x67, 0x73, 0x18, 0x01, 0x20,
+ 0x01, 0x28, 0x03, 0x52, 0x15, 0x64, 0x72, 0x6f, 0x70, 0x70, 0x65, 0x64,
+ 0x42, 0x65, 0x67, 0x69, 0x6e, 0x46, 0x72, 0x61, 0x6d, 0x65, 0x41, 0x72,
+ 0x67, 0x73, 0x12, 0x52, 0x0a, 0x15, 0x6c, 0x61, 0x73, 0x74, 0x5f, 0x62,
0x65, 0x67, 0x69, 0x6e, 0x5f, 0x66, 0x72, 0x61, 0x6d, 0x65, 0x5f, 0x61,
- 0x72, 0x67, 0x73, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1f, 0x2e,
+ 0x72, 0x67, 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1f, 0x2e,
0x70, 0x65, 0x72, 0x66, 0x65, 0x74, 0x74, 0x6f, 0x2e, 0x70, 0x72, 0x6f,
0x74, 0x6f, 0x73, 0x2e, 0x42, 0x65, 0x67, 0x69, 0x6e, 0x46, 0x72, 0x61,
0x6d, 0x65, 0x41, 0x72, 0x67, 0x73, 0x52, 0x12, 0x6c, 0x61, 0x73, 0x74,
0x42, 0x65, 0x67, 0x69, 0x6e, 0x46, 0x72, 0x61, 0x6d, 0x65, 0x41, 0x72,
- 0x67, 0x73, 0x22, 0xfd, 0x04, 0x0a, 0x17, 0x43, 0x6f, 0x6d, 0x70, 0x6f,
- 0x73, 0x69, 0x74, 0x6f, 0x72, 0x54, 0x69, 0x6d, 0x69, 0x6e, 0x67, 0x48,
- 0x69, 0x73, 0x74, 0x6f, 0x72, 0x79, 0x12, 0x65, 0x0a, 0x31, 0x62, 0x65,
- 0x67, 0x69, 0x6e, 0x5f, 0x6d, 0x61, 0x69, 0x6e, 0x5f, 0x66, 0x72, 0x61,
- 0x6d, 0x65, 0x5f, 0x71, 0x75, 0x65, 0x75, 0x65, 0x5f, 0x63, 0x72, 0x69,
- 0x74, 0x69, 0x63, 0x61, 0x6c, 0x5f, 0x65, 0x73, 0x74, 0x69, 0x6d, 0x61,
- 0x74, 0x65, 0x5f, 0x64, 0x65, 0x6c, 0x74, 0x61, 0x5f, 0x75, 0x73, 0x18,
- 0x01, 0x20, 0x01, 0x28, 0x03, 0x52, 0x2a, 0x62, 0x65, 0x67, 0x69, 0x6e,
- 0x4d, 0x61, 0x69, 0x6e, 0x46, 0x72, 0x61, 0x6d, 0x65, 0x51, 0x75, 0x65,
- 0x75, 0x65, 0x43, 0x72, 0x69, 0x74, 0x69, 0x63, 0x61, 0x6c, 0x45, 0x73,
- 0x74, 0x69, 0x6d, 0x61, 0x74, 0x65, 0x44, 0x65, 0x6c, 0x74, 0x61, 0x55,
- 0x73, 0x12, 0x6c, 0x0a, 0x35, 0x62, 0x65, 0x67, 0x69, 0x6e, 0x5f, 0x6d,
- 0x61, 0x69, 0x6e, 0x5f, 0x66, 0x72, 0x61, 0x6d, 0x65, 0x5f, 0x71, 0x75,
- 0x65, 0x75, 0x65, 0x5f, 0x6e, 0x6f, 0x74, 0x5f, 0x63, 0x72, 0x69, 0x74,
- 0x69, 0x63, 0x61, 0x6c, 0x5f, 0x65, 0x73, 0x74, 0x69, 0x6d, 0x61, 0x74,
- 0x65, 0x5f, 0x64, 0x65, 0x6c, 0x74, 0x61, 0x5f, 0x75, 0x73, 0x18, 0x02,
- 0x20, 0x01, 0x28, 0x03, 0x52, 0x2d, 0x62, 0x65, 0x67, 0x69, 0x6e, 0x4d,
- 0x61, 0x69, 0x6e, 0x46, 0x72, 0x61, 0x6d, 0x65, 0x51, 0x75, 0x65, 0x75,
- 0x65, 0x4e, 0x6f, 0x74, 0x43, 0x72, 0x69, 0x74, 0x69, 0x63, 0x61, 0x6c,
- 0x45, 0x73, 0x74, 0x69, 0x6d, 0x61, 0x74, 0x65, 0x44, 0x65, 0x6c, 0x74,
- 0x61, 0x55, 0x73, 0x12, 0x76, 0x0a, 0x3b, 0x62, 0x65, 0x67, 0x69, 0x6e,
- 0x5f, 0x6d, 0x61, 0x69, 0x6e, 0x5f, 0x66, 0x72, 0x61, 0x6d, 0x65, 0x5f,
- 0x73, 0x74, 0x61, 0x72, 0x74, 0x5f, 0x74, 0x6f, 0x5f, 0x72, 0x65, 0x61,
- 0x64, 0x79, 0x5f, 0x74, 0x6f, 0x5f, 0x63, 0x6f, 0x6d, 0x6d, 0x69, 0x74,
+ 0x67, 0x73, 0x22, 0xc5, 0x01, 0x0a, 0x15, 0x42, 0x65, 0x67, 0x69, 0x6e,
+ 0x46, 0x72, 0x61, 0x6d, 0x65, 0x53, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x53,
+ 0x74, 0x61, 0x74, 0x65, 0x12, 0x1b, 0x0a, 0x09, 0x73, 0x6f, 0x75, 0x72,
+ 0x63, 0x65, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0d, 0x52,
+ 0x08, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x49, 0x64, 0x12, 0x16, 0x0a,
+ 0x06, 0x70, 0x61, 0x75, 0x73, 0x65, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28,
+ 0x08, 0x52, 0x06, 0x70, 0x61, 0x75, 0x73, 0x65, 0x64, 0x12, 0x23, 0x0a,
+ 0x0d, 0x6e, 0x75, 0x6d, 0x5f, 0x6f, 0x62, 0x73, 0x65, 0x72, 0x76, 0x65,
+ 0x72, 0x73, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x0c, 0x6e, 0x75,
+ 0x6d, 0x4f, 0x62, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x73, 0x12, 0x52,
+ 0x0a, 0x15, 0x6c, 0x61, 0x73, 0x74, 0x5f, 0x62, 0x65, 0x67, 0x69, 0x6e,
+ 0x5f, 0x66, 0x72, 0x61, 0x6d, 0x65, 0x5f, 0x61, 0x72, 0x67, 0x73, 0x18,
+ 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1f, 0x2e, 0x70, 0x65, 0x72, 0x66,
+ 0x65, 0x74, 0x74, 0x6f, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2e,
+ 0x42, 0x65, 0x67, 0x69, 0x6e, 0x46, 0x72, 0x61, 0x6d, 0x65, 0x41, 0x72,
+ 0x67, 0x73, 0x52, 0x12, 0x6c, 0x61, 0x73, 0x74, 0x42, 0x65, 0x67, 0x69,
+ 0x6e, 0x46, 0x72, 0x61, 0x6d, 0x65, 0x41, 0x72, 0x67, 0x73, 0x22, 0xfd,
+ 0x04, 0x0a, 0x17, 0x43, 0x6f, 0x6d, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x6f,
+ 0x72, 0x54, 0x69, 0x6d, 0x69, 0x6e, 0x67, 0x48, 0x69, 0x73, 0x74, 0x6f,
+ 0x72, 0x79, 0x12, 0x65, 0x0a, 0x31, 0x62, 0x65, 0x67, 0x69, 0x6e, 0x5f,
+ 0x6d, 0x61, 0x69, 0x6e, 0x5f, 0x66, 0x72, 0x61, 0x6d, 0x65, 0x5f, 0x71,
+ 0x75, 0x65, 0x75, 0x65, 0x5f, 0x63, 0x72, 0x69, 0x74, 0x69, 0x63, 0x61,
+ 0x6c, 0x5f, 0x65, 0x73, 0x74, 0x69, 0x6d, 0x61, 0x74, 0x65, 0x5f, 0x64,
+ 0x65, 0x6c, 0x74, 0x61, 0x5f, 0x75, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28,
+ 0x03, 0x52, 0x2a, 0x62, 0x65, 0x67, 0x69, 0x6e, 0x4d, 0x61, 0x69, 0x6e,
+ 0x46, 0x72, 0x61, 0x6d, 0x65, 0x51, 0x75, 0x65, 0x75, 0x65, 0x43, 0x72,
+ 0x69, 0x74, 0x69, 0x63, 0x61, 0x6c, 0x45, 0x73, 0x74, 0x69, 0x6d, 0x61,
+ 0x74, 0x65, 0x44, 0x65, 0x6c, 0x74, 0x61, 0x55, 0x73, 0x12, 0x6c, 0x0a,
+ 0x35, 0x62, 0x65, 0x67, 0x69, 0x6e, 0x5f, 0x6d, 0x61, 0x69, 0x6e, 0x5f,
+ 0x66, 0x72, 0x61, 0x6d, 0x65, 0x5f, 0x71, 0x75, 0x65, 0x75, 0x65, 0x5f,
+ 0x6e, 0x6f, 0x74, 0x5f, 0x63, 0x72, 0x69, 0x74, 0x69, 0x63, 0x61, 0x6c,
0x5f, 0x65, 0x73, 0x74, 0x69, 0x6d, 0x61, 0x74, 0x65, 0x5f, 0x64, 0x65,
- 0x6c, 0x74, 0x61, 0x5f, 0x75, 0x73, 0x18, 0x03, 0x20, 0x01, 0x28, 0x03,
- 0x52, 0x31, 0x62, 0x65, 0x67, 0x69, 0x6e, 0x4d, 0x61, 0x69, 0x6e, 0x46,
- 0x72, 0x61, 0x6d, 0x65, 0x53, 0x74, 0x61, 0x72, 0x74, 0x54, 0x6f, 0x52,
- 0x65, 0x61, 0x64, 0x79, 0x54, 0x6f, 0x43, 0x6f, 0x6d, 0x6d, 0x69, 0x74,
- 0x45, 0x73, 0x74, 0x69, 0x6d, 0x61, 0x74, 0x65, 0x44, 0x65, 0x6c, 0x74,
- 0x61, 0x55, 0x73, 0x12, 0x5d, 0x0a, 0x2d, 0x63, 0x6f, 0x6d, 0x6d, 0x69,
+ 0x6c, 0x74, 0x61, 0x5f, 0x75, 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x03,
+ 0x52, 0x2d, 0x62, 0x65, 0x67, 0x69, 0x6e, 0x4d, 0x61, 0x69, 0x6e, 0x46,
+ 0x72, 0x61, 0x6d, 0x65, 0x51, 0x75, 0x65, 0x75, 0x65, 0x4e, 0x6f, 0x74,
+ 0x43, 0x72, 0x69, 0x74, 0x69, 0x63, 0x61, 0x6c, 0x45, 0x73, 0x74, 0x69,
+ 0x6d, 0x61, 0x74, 0x65, 0x44, 0x65, 0x6c, 0x74, 0x61, 0x55, 0x73, 0x12,
+ 0x76, 0x0a, 0x3b, 0x62, 0x65, 0x67, 0x69, 0x6e, 0x5f, 0x6d, 0x61, 0x69,
+ 0x6e, 0x5f, 0x66, 0x72, 0x61, 0x6d, 0x65, 0x5f, 0x73, 0x74, 0x61, 0x72,
0x74, 0x5f, 0x74, 0x6f, 0x5f, 0x72, 0x65, 0x61, 0x64, 0x79, 0x5f, 0x74,
- 0x6f, 0x5f, 0x61, 0x63, 0x74, 0x69, 0x76, 0x61, 0x74, 0x65, 0x5f, 0x65,
- 0x73, 0x74, 0x69, 0x6d, 0x61, 0x74, 0x65, 0x5f, 0x64, 0x65, 0x6c, 0x74,
- 0x61, 0x5f, 0x75, 0x73, 0x18, 0x04, 0x20, 0x01, 0x28, 0x03, 0x52, 0x26,
- 0x63, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x54, 0x6f, 0x52, 0x65, 0x61, 0x64,
- 0x79, 0x54, 0x6f, 0x41, 0x63, 0x74, 0x69, 0x76, 0x61, 0x74, 0x65, 0x45,
+ 0x6f, 0x5f, 0x63, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x5f, 0x65, 0x73, 0x74,
+ 0x69, 0x6d, 0x61, 0x74, 0x65, 0x5f, 0x64, 0x65, 0x6c, 0x74, 0x61, 0x5f,
+ 0x75, 0x73, 0x18, 0x03, 0x20, 0x01, 0x28, 0x03, 0x52, 0x31, 0x62, 0x65,
+ 0x67, 0x69, 0x6e, 0x4d, 0x61, 0x69, 0x6e, 0x46, 0x72, 0x61, 0x6d, 0x65,
+ 0x53, 0x74, 0x61, 0x72, 0x74, 0x54, 0x6f, 0x52, 0x65, 0x61, 0x64, 0x79,
+ 0x54, 0x6f, 0x43, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x45, 0x73, 0x74, 0x69,
+ 0x6d, 0x61, 0x74, 0x65, 0x44, 0x65, 0x6c, 0x74, 0x61, 0x55, 0x73, 0x12,
+ 0x5d, 0x0a, 0x2d, 0x63, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x5f, 0x74, 0x6f,
+ 0x5f, 0x72, 0x65, 0x61, 0x64, 0x79, 0x5f, 0x74, 0x6f, 0x5f, 0x61, 0x63,
+ 0x74, 0x69, 0x76, 0x61, 0x74, 0x65, 0x5f, 0x65, 0x73, 0x74, 0x69, 0x6d,
+ 0x61, 0x74, 0x65, 0x5f, 0x64, 0x65, 0x6c, 0x74, 0x61, 0x5f, 0x75, 0x73,
+ 0x18, 0x04, 0x20, 0x01, 0x28, 0x03, 0x52, 0x26, 0x63, 0x6f, 0x6d, 0x6d,
+ 0x69, 0x74, 0x54, 0x6f, 0x52, 0x65, 0x61, 0x64, 0x79, 0x54, 0x6f, 0x41,
+ 0x63, 0x74, 0x69, 0x76, 0x61, 0x74, 0x65, 0x45, 0x73, 0x74, 0x69, 0x6d,
+ 0x61, 0x74, 0x65, 0x44, 0x65, 0x6c, 0x74, 0x61, 0x55, 0x73, 0x12, 0x44,
+ 0x0a, 0x1f, 0x70, 0x72, 0x65, 0x70, 0x61, 0x72, 0x65, 0x5f, 0x74, 0x69,
+ 0x6c, 0x65, 0x73, 0x5f, 0x65, 0x73, 0x74, 0x69, 0x6d, 0x61, 0x74, 0x65,
+ 0x5f, 0x64, 0x65, 0x6c, 0x74, 0x61, 0x5f, 0x75, 0x73, 0x18, 0x05, 0x20,
+ 0x01, 0x28, 0x03, 0x52, 0x1b, 0x70, 0x72, 0x65, 0x70, 0x61, 0x72, 0x65,
+ 0x54, 0x69, 0x6c, 0x65, 0x73, 0x45, 0x73, 0x74, 0x69, 0x6d, 0x61, 0x74,
+ 0x65, 0x44, 0x65, 0x6c, 0x74, 0x61, 0x55, 0x73, 0x12, 0x3b, 0x0a, 0x1a,
+ 0x61, 0x63, 0x74, 0x69, 0x76, 0x61, 0x74, 0x65, 0x5f, 0x65, 0x73, 0x74,
+ 0x69, 0x6d, 0x61, 0x74, 0x65, 0x5f, 0x64, 0x65, 0x6c, 0x74, 0x61, 0x5f,
+ 0x75, 0x73, 0x18, 0x06, 0x20, 0x01, 0x28, 0x03, 0x52, 0x17, 0x61, 0x63,
+ 0x74, 0x69, 0x76, 0x61, 0x74, 0x65, 0x45, 0x73, 0x74, 0x69, 0x6d, 0x61,
+ 0x74, 0x65, 0x44, 0x65, 0x6c, 0x74, 0x61, 0x55, 0x73, 0x12, 0x33, 0x0a,
+ 0x16, 0x64, 0x72, 0x61, 0x77, 0x5f, 0x65, 0x73, 0x74, 0x69, 0x6d, 0x61,
+ 0x74, 0x65, 0x5f, 0x64, 0x65, 0x6c, 0x74, 0x61, 0x5f, 0x75, 0x73, 0x18,
+ 0x07, 0x20, 0x01, 0x28, 0x03, 0x52, 0x13, 0x64, 0x72, 0x61, 0x77, 0x45,
0x73, 0x74, 0x69, 0x6d, 0x61, 0x74, 0x65, 0x44, 0x65, 0x6c, 0x74, 0x61,
- 0x55, 0x73, 0x12, 0x44, 0x0a, 0x1f, 0x70, 0x72, 0x65, 0x70, 0x61, 0x72,
- 0x65, 0x5f, 0x74, 0x69, 0x6c, 0x65, 0x73, 0x5f, 0x65, 0x73, 0x74, 0x69,
- 0x6d, 0x61, 0x74, 0x65, 0x5f, 0x64, 0x65, 0x6c, 0x74, 0x61, 0x5f, 0x75,
- 0x73, 0x18, 0x05, 0x20, 0x01, 0x28, 0x03, 0x52, 0x1b, 0x70, 0x72, 0x65,
- 0x70, 0x61, 0x72, 0x65, 0x54, 0x69, 0x6c, 0x65, 0x73, 0x45, 0x73, 0x74,
- 0x69, 0x6d, 0x61, 0x74, 0x65, 0x44, 0x65, 0x6c, 0x74, 0x61, 0x55, 0x73,
- 0x12, 0x3b, 0x0a, 0x1a, 0x61, 0x63, 0x74, 0x69, 0x76, 0x61, 0x74, 0x65,
- 0x5f, 0x65, 0x73, 0x74, 0x69, 0x6d, 0x61, 0x74, 0x65, 0x5f, 0x64, 0x65,
- 0x6c, 0x74, 0x61, 0x5f, 0x75, 0x73, 0x18, 0x06, 0x20, 0x01, 0x28, 0x03,
- 0x52, 0x17, 0x61, 0x63, 0x74, 0x69, 0x76, 0x61, 0x74, 0x65, 0x45, 0x73,
- 0x74, 0x69, 0x6d, 0x61, 0x74, 0x65, 0x44, 0x65, 0x6c, 0x74, 0x61, 0x55,
- 0x73, 0x12, 0x33, 0x0a, 0x16, 0x64, 0x72, 0x61, 0x77, 0x5f, 0x65, 0x73,
- 0x74, 0x69, 0x6d, 0x61, 0x74, 0x65, 0x5f, 0x64, 0x65, 0x6c, 0x74, 0x61,
- 0x5f, 0x75, 0x73, 0x18, 0x07, 0x20, 0x01, 0x28, 0x03, 0x52, 0x13, 0x64,
- 0x72, 0x61, 0x77, 0x45, 0x73, 0x74, 0x69, 0x6d, 0x61, 0x74, 0x65, 0x44,
- 0x65, 0x6c, 0x74, 0x61, 0x55, 0x73, 0x2a, 0xb0, 0x05, 0x0a, 0x1f, 0x43,
- 0x68, 0x72, 0x6f, 0x6d, 0x65, 0x43, 0x6f, 0x6d, 0x70, 0x6f, 0x73, 0x69,
- 0x74, 0x6f, 0x72, 0x53, 0x63, 0x68, 0x65, 0x64, 0x75, 0x6c, 0x65, 0x72,
- 0x41, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x23, 0x0a, 0x1f, 0x43, 0x43,
- 0x5f, 0x53, 0x43, 0x48, 0x45, 0x44, 0x55, 0x4c, 0x45, 0x52, 0x5f, 0x41,
- 0x43, 0x54, 0x49, 0x4f, 0x4e, 0x5f, 0x55, 0x4e, 0x53, 0x50, 0x45, 0x43,
- 0x49, 0x46, 0x49, 0x45, 0x44, 0x10, 0x00, 0x12, 0x1c, 0x0a, 0x18, 0x43,
- 0x43, 0x5f, 0x53, 0x43, 0x48, 0x45, 0x44, 0x55, 0x4c, 0x45, 0x52, 0x5f,
- 0x41, 0x43, 0x54, 0x49, 0x4f, 0x4e, 0x5f, 0x4e, 0x4f, 0x4e, 0x45, 0x10,
- 0x01, 0x12, 0x2d, 0x0a, 0x29, 0x43, 0x43, 0x5f, 0x53, 0x43, 0x48, 0x45,
- 0x44, 0x55, 0x4c, 0x45, 0x52, 0x5f, 0x41, 0x43, 0x54, 0x49, 0x4f, 0x4e,
- 0x5f, 0x53, 0x45, 0x4e, 0x44, 0x5f, 0x42, 0x45, 0x47, 0x49, 0x4e, 0x5f,
- 0x4d, 0x41, 0x49, 0x4e, 0x5f, 0x46, 0x52, 0x41, 0x4d, 0x45, 0x10, 0x02,
- 0x12, 0x1e, 0x0a, 0x1a, 0x43, 0x43, 0x5f, 0x53, 0x43, 0x48, 0x45, 0x44,
- 0x55, 0x4c, 0x45, 0x52, 0x5f, 0x41, 0x43, 0x54, 0x49, 0x4f, 0x4e, 0x5f,
- 0x43, 0x4f, 0x4d, 0x4d, 0x49, 0x54, 0x10, 0x03, 0x12, 0x2a, 0x0a, 0x26,
- 0x43, 0x43, 0x5f, 0x53, 0x43, 0x48, 0x45, 0x44, 0x55, 0x4c, 0x45, 0x52,
- 0x5f, 0x41, 0x43, 0x54, 0x49, 0x4f, 0x4e, 0x5f, 0x41, 0x43, 0x54, 0x49,
- 0x56, 0x41, 0x54, 0x45, 0x5f, 0x53, 0x59, 0x4e, 0x43, 0x5f, 0x54, 0x52,
- 0x45, 0x45, 0x10, 0x04, 0x12, 0x28, 0x0a, 0x24, 0x43, 0x43, 0x5f, 0x53,
- 0x43, 0x48, 0x45, 0x44, 0x55, 0x4c, 0x45, 0x52, 0x5f, 0x41, 0x43, 0x54,
- 0x49, 0x4f, 0x4e, 0x5f, 0x44, 0x52, 0x41, 0x57, 0x5f, 0x49, 0x46, 0x5f,
- 0x50, 0x4f, 0x53, 0x53, 0x49, 0x42, 0x4c, 0x45, 0x10, 0x05, 0x12, 0x23,
- 0x0a, 0x1f, 0x43, 0x43, 0x5f, 0x53, 0x43, 0x48, 0x45, 0x44, 0x55, 0x4c,
- 0x45, 0x52, 0x5f, 0x41, 0x43, 0x54, 0x49, 0x4f, 0x4e, 0x5f, 0x44, 0x52,
- 0x41, 0x57, 0x5f, 0x46, 0x4f, 0x52, 0x43, 0x45, 0x44, 0x10, 0x06, 0x12,
- 0x22, 0x0a, 0x1e, 0x43, 0x43, 0x5f, 0x53, 0x43, 0x48, 0x45, 0x44, 0x55,
- 0x4c, 0x45, 0x52, 0x5f, 0x41, 0x43, 0x54, 0x49, 0x4f, 0x4e, 0x5f, 0x44,
- 0x52, 0x41, 0x57, 0x5f, 0x41, 0x42, 0x4f, 0x52, 0x54, 0x10, 0x07, 0x12,
- 0x3c, 0x0a, 0x38, 0x43, 0x43, 0x5f, 0x53, 0x43, 0x48, 0x45, 0x44, 0x55,
- 0x4c, 0x45, 0x52, 0x5f, 0x41, 0x43, 0x54, 0x49, 0x4f, 0x4e, 0x5f, 0x42,
- 0x45, 0x47, 0x49, 0x4e, 0x5f, 0x4c, 0x41, 0x59, 0x45, 0x52, 0x5f, 0x54,
- 0x52, 0x45, 0x45, 0x5f, 0x46, 0x52, 0x41, 0x4d, 0x45, 0x5f, 0x53, 0x49,
- 0x4e, 0x4b, 0x5f, 0x43, 0x52, 0x45, 0x41, 0x54, 0x49, 0x4f, 0x4e, 0x10,
- 0x08, 0x12, 0x25, 0x0a, 0x21, 0x43, 0x43, 0x5f, 0x53, 0x43, 0x48, 0x45,
- 0x44, 0x55, 0x4c, 0x45, 0x52, 0x5f, 0x41, 0x43, 0x54, 0x49, 0x4f, 0x4e,
- 0x5f, 0x50, 0x52, 0x45, 0x50, 0x41, 0x52, 0x45, 0x5f, 0x54, 0x49, 0x4c,
- 0x45, 0x53, 0x10, 0x09, 0x12, 0x38, 0x0a, 0x34, 0x43, 0x43, 0x5f, 0x53,
- 0x43, 0x48, 0x45, 0x44, 0x55, 0x4c, 0x45, 0x52, 0x5f, 0x41, 0x43, 0x54,
- 0x49, 0x4f, 0x4e, 0x5f, 0x49, 0x4e, 0x56, 0x41, 0x4c, 0x49, 0x44, 0x41,
- 0x54, 0x45, 0x5f, 0x4c, 0x41, 0x59, 0x45, 0x52, 0x5f, 0x54, 0x52, 0x45,
- 0x45, 0x5f, 0x46, 0x52, 0x41, 0x4d, 0x45, 0x5f, 0x53, 0x49, 0x4e, 0x4b,
- 0x10, 0x0a, 0x12, 0x36, 0x0a, 0x32, 0x43, 0x43, 0x5f, 0x53, 0x43, 0x48,
+ 0x55, 0x73, 0x2a, 0xb0, 0x05, 0x0a, 0x1f, 0x43, 0x68, 0x72, 0x6f, 0x6d,
+ 0x65, 0x43, 0x6f, 0x6d, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x6f, 0x72, 0x53,
+ 0x63, 0x68, 0x65, 0x64, 0x75, 0x6c, 0x65, 0x72, 0x41, 0x63, 0x74, 0x69,
+ 0x6f, 0x6e, 0x12, 0x23, 0x0a, 0x1f, 0x43, 0x43, 0x5f, 0x53, 0x43, 0x48,
0x45, 0x44, 0x55, 0x4c, 0x45, 0x52, 0x5f, 0x41, 0x43, 0x54, 0x49, 0x4f,
- 0x4e, 0x5f, 0x50, 0x45, 0x52, 0x46, 0x4f, 0x52, 0x4d, 0x5f, 0x49, 0x4d,
- 0x50, 0x4c, 0x5f, 0x53, 0x49, 0x44, 0x45, 0x5f, 0x49, 0x4e, 0x56, 0x41,
- 0x4c, 0x49, 0x44, 0x41, 0x54, 0x49, 0x4f, 0x4e, 0x10, 0x0b, 0x12, 0x42,
- 0x0a, 0x3e, 0x43, 0x43, 0x5f, 0x53, 0x43, 0x48, 0x45, 0x44, 0x55, 0x4c,
- 0x45, 0x52, 0x5f, 0x41, 0x43, 0x54, 0x49, 0x4f, 0x4e, 0x5f, 0x4e, 0x4f,
- 0x54, 0x49, 0x46, 0x59, 0x5f, 0x42, 0x45, 0x47, 0x49, 0x4e, 0x5f, 0x4d,
- 0x41, 0x49, 0x4e, 0x5f, 0x46, 0x52, 0x41, 0x4d, 0x45, 0x5f, 0x4e, 0x4f,
- 0x54, 0x5f, 0x45, 0x58, 0x50, 0x45, 0x43, 0x54, 0x45, 0x44, 0x5f, 0x55,
- 0x4e, 0x54, 0x49, 0x4c, 0x10, 0x0c, 0x12, 0x41, 0x0a, 0x3d, 0x43, 0x43,
+ 0x4e, 0x5f, 0x55, 0x4e, 0x53, 0x50, 0x45, 0x43, 0x49, 0x46, 0x49, 0x45,
+ 0x44, 0x10, 0x00, 0x12, 0x1c, 0x0a, 0x18, 0x43, 0x43, 0x5f, 0x53, 0x43,
+ 0x48, 0x45, 0x44, 0x55, 0x4c, 0x45, 0x52, 0x5f, 0x41, 0x43, 0x54, 0x49,
+ 0x4f, 0x4e, 0x5f, 0x4e, 0x4f, 0x4e, 0x45, 0x10, 0x01, 0x12, 0x2d, 0x0a,
+ 0x29, 0x43, 0x43, 0x5f, 0x53, 0x43, 0x48, 0x45, 0x44, 0x55, 0x4c, 0x45,
+ 0x52, 0x5f, 0x41, 0x43, 0x54, 0x49, 0x4f, 0x4e, 0x5f, 0x53, 0x45, 0x4e,
+ 0x44, 0x5f, 0x42, 0x45, 0x47, 0x49, 0x4e, 0x5f, 0x4d, 0x41, 0x49, 0x4e,
+ 0x5f, 0x46, 0x52, 0x41, 0x4d, 0x45, 0x10, 0x02, 0x12, 0x1e, 0x0a, 0x1a,
+ 0x43, 0x43, 0x5f, 0x53, 0x43, 0x48, 0x45, 0x44, 0x55, 0x4c, 0x45, 0x52,
+ 0x5f, 0x41, 0x43, 0x54, 0x49, 0x4f, 0x4e, 0x5f, 0x43, 0x4f, 0x4d, 0x4d,
+ 0x49, 0x54, 0x10, 0x03, 0x12, 0x2a, 0x0a, 0x26, 0x43, 0x43, 0x5f, 0x53,
+ 0x43, 0x48, 0x45, 0x44, 0x55, 0x4c, 0x45, 0x52, 0x5f, 0x41, 0x43, 0x54,
+ 0x49, 0x4f, 0x4e, 0x5f, 0x41, 0x43, 0x54, 0x49, 0x56, 0x41, 0x54, 0x45,
+ 0x5f, 0x53, 0x59, 0x4e, 0x43, 0x5f, 0x54, 0x52, 0x45, 0x45, 0x10, 0x04,
+ 0x12, 0x28, 0x0a, 0x24, 0x43, 0x43, 0x5f, 0x53, 0x43, 0x48, 0x45, 0x44,
+ 0x55, 0x4c, 0x45, 0x52, 0x5f, 0x41, 0x43, 0x54, 0x49, 0x4f, 0x4e, 0x5f,
+ 0x44, 0x52, 0x41, 0x57, 0x5f, 0x49, 0x46, 0x5f, 0x50, 0x4f, 0x53, 0x53,
+ 0x49, 0x42, 0x4c, 0x45, 0x10, 0x05, 0x12, 0x23, 0x0a, 0x1f, 0x43, 0x43,
+ 0x5f, 0x53, 0x43, 0x48, 0x45, 0x44, 0x55, 0x4c, 0x45, 0x52, 0x5f, 0x41,
+ 0x43, 0x54, 0x49, 0x4f, 0x4e, 0x5f, 0x44, 0x52, 0x41, 0x57, 0x5f, 0x46,
+ 0x4f, 0x52, 0x43, 0x45, 0x44, 0x10, 0x06, 0x12, 0x22, 0x0a, 0x1e, 0x43,
+ 0x43, 0x5f, 0x53, 0x43, 0x48, 0x45, 0x44, 0x55, 0x4c, 0x45, 0x52, 0x5f,
+ 0x41, 0x43, 0x54, 0x49, 0x4f, 0x4e, 0x5f, 0x44, 0x52, 0x41, 0x57, 0x5f,
+ 0x41, 0x42, 0x4f, 0x52, 0x54, 0x10, 0x07, 0x12, 0x3c, 0x0a, 0x38, 0x43,
+ 0x43, 0x5f, 0x53, 0x43, 0x48, 0x45, 0x44, 0x55, 0x4c, 0x45, 0x52, 0x5f,
+ 0x41, 0x43, 0x54, 0x49, 0x4f, 0x4e, 0x5f, 0x42, 0x45, 0x47, 0x49, 0x4e,
+ 0x5f, 0x4c, 0x41, 0x59, 0x45, 0x52, 0x5f, 0x54, 0x52, 0x45, 0x45, 0x5f,
+ 0x46, 0x52, 0x41, 0x4d, 0x45, 0x5f, 0x53, 0x49, 0x4e, 0x4b, 0x5f, 0x43,
+ 0x52, 0x45, 0x41, 0x54, 0x49, 0x4f, 0x4e, 0x10, 0x08, 0x12, 0x25, 0x0a,
+ 0x21, 0x43, 0x43, 0x5f, 0x53, 0x43, 0x48, 0x45, 0x44, 0x55, 0x4c, 0x45,
+ 0x52, 0x5f, 0x41, 0x43, 0x54, 0x49, 0x4f, 0x4e, 0x5f, 0x50, 0x52, 0x45,
+ 0x50, 0x41, 0x52, 0x45, 0x5f, 0x54, 0x49, 0x4c, 0x45, 0x53, 0x10, 0x09,
+ 0x12, 0x38, 0x0a, 0x34, 0x43, 0x43, 0x5f, 0x53, 0x43, 0x48, 0x45, 0x44,
+ 0x55, 0x4c, 0x45, 0x52, 0x5f, 0x41, 0x43, 0x54, 0x49, 0x4f, 0x4e, 0x5f,
+ 0x49, 0x4e, 0x56, 0x41, 0x4c, 0x49, 0x44, 0x41, 0x54, 0x45, 0x5f, 0x4c,
+ 0x41, 0x59, 0x45, 0x52, 0x5f, 0x54, 0x52, 0x45, 0x45, 0x5f, 0x46, 0x52,
+ 0x41, 0x4d, 0x45, 0x5f, 0x53, 0x49, 0x4e, 0x4b, 0x10, 0x0a, 0x12, 0x36,
+ 0x0a, 0x32, 0x43, 0x43, 0x5f, 0x53, 0x43, 0x48, 0x45, 0x44, 0x55, 0x4c,
+ 0x45, 0x52, 0x5f, 0x41, 0x43, 0x54, 0x49, 0x4f, 0x4e, 0x5f, 0x50, 0x45,
+ 0x52, 0x46, 0x4f, 0x52, 0x4d, 0x5f, 0x49, 0x4d, 0x50, 0x4c, 0x5f, 0x53,
+ 0x49, 0x44, 0x45, 0x5f, 0x49, 0x4e, 0x56, 0x41, 0x4c, 0x49, 0x44, 0x41,
+ 0x54, 0x49, 0x4f, 0x4e, 0x10, 0x0b, 0x12, 0x42, 0x0a, 0x3e, 0x43, 0x43,
0x5f, 0x53, 0x43, 0x48, 0x45, 0x44, 0x55, 0x4c, 0x45, 0x52, 0x5f, 0x41,
0x43, 0x54, 0x49, 0x4f, 0x4e, 0x5f, 0x4e, 0x4f, 0x54, 0x49, 0x46, 0x59,
0x5f, 0x42, 0x45, 0x47, 0x49, 0x4e, 0x5f, 0x4d, 0x41, 0x49, 0x4e, 0x5f,
0x46, 0x52, 0x41, 0x4d, 0x45, 0x5f, 0x4e, 0x4f, 0x54, 0x5f, 0x45, 0x58,
- 0x50, 0x45, 0x43, 0x54, 0x45, 0x44, 0x5f, 0x53, 0x4f, 0x4f, 0x4e, 0x10,
- 0x0d, 0x42, 0x02, 0x48, 0x03}};
+ 0x50, 0x45, 0x43, 0x54, 0x45, 0x44, 0x5f, 0x55, 0x4e, 0x54, 0x49, 0x4c,
+ 0x10, 0x0c, 0x12, 0x41, 0x0a, 0x3d, 0x43, 0x43, 0x5f, 0x53, 0x43, 0x48,
+ 0x45, 0x44, 0x55, 0x4c, 0x45, 0x52, 0x5f, 0x41, 0x43, 0x54, 0x49, 0x4f,
+ 0x4e, 0x5f, 0x4e, 0x4f, 0x54, 0x49, 0x46, 0x59, 0x5f, 0x42, 0x45, 0x47,
+ 0x49, 0x4e, 0x5f, 0x4d, 0x41, 0x49, 0x4e, 0x5f, 0x46, 0x52, 0x41, 0x4d,
+ 0x45, 0x5f, 0x4e, 0x4f, 0x54, 0x5f, 0x45, 0x58, 0x50, 0x45, 0x43, 0x54,
+ 0x45, 0x44, 0x5f, 0x53, 0x4f, 0x4f, 0x4e, 0x10, 0x0d}};
} // namespace perfetto
diff --git a/src/trace_processor/importers/proto/graphics_event_module.cc b/src/trace_processor/importers/proto/graphics_event_module.cc
index 38979f2..f003464 100644
--- a/src/trace_processor/importers/proto/graphics_event_module.cc
+++ b/src/trace_processor/importers/proto/graphics_event_module.cc
@@ -57,7 +57,7 @@
decoder.vulkan_memory_event());
return;
case TracePacket::kVulkanApiEventFieldNumber:
- parser_.ParseVulkanApiEvent(decoder.vulkan_api_event());
+ parser_.ParseVulkanApiEvent(ttp.timestamp, decoder.vulkan_api_event());
return;
}
}
diff --git a/src/trace_processor/importers/proto/graphics_event_parser.cc b/src/trace_processor/importers/proto/graphics_event_parser.cc
index 1805731..ed87c84 100644
--- a/src/trace_processor/importers/proto/graphics_event_parser.cc
+++ b/src/trace_processor/importers/proto/graphics_event_parser.cc
@@ -16,12 +16,16 @@
#include "src/trace_processor/importers/proto/graphics_event_parser.h"
+#include <inttypes.h>
+
+#include "perfetto/ext/base/utils.h"
#include "perfetto/protozero/field.h"
#include "src/trace_processor/args_tracker.h"
#include "src/trace_processor/event_tracker.h"
#include "src/trace_processor/process_tracker.h"
#include "src/trace_processor/slice_tracker.h"
#include "src/trace_processor/trace_processor_context.h"
+#include "src/trace_processor/trace_storage.h"
#include "src/trace_processor/track_tracker.h"
#include "protos/perfetto/common/gpu_counter_descriptor.pbzero.h"
@@ -136,7 +140,10 @@
context_->storage->InternString("WARNING"),
context_->storage->InternString("ERROR"),
context_->storage->InternString(
- "UNKNOWN_SEVERITY") /* must be last */}} {}
+ "UNKNOWN_SEVERITY") /* must be last */}},
+ vk_event_track_id_(context->storage->InternString("Vulkan Events")),
+ vk_event_scope_id_(context->storage->InternString("vulkan_events")),
+ vk_queue_submit_id_(context->storage->InternString("vkQueueSubmit")) {}
void GraphicsEventParser::ParseGpuCounterEvent(int64_t ts, ConstBytes blob) {
protos::pbzero::GpuCounterEvent::Decoder event(blob.data, blob.size);
@@ -162,7 +169,7 @@
gpu_counter_track_ids_.end()) {
auto desc = spec.description();
- StringId unit_id = 0;
+ StringId unit_id = kNullStringId;
if (spec.has_numerator_units() || spec.has_denominator_units()) {
char buffer[1024];
base::StringWriter unit(buffer, sizeof(buffer));
@@ -226,7 +233,7 @@
}
const StringId GraphicsEventParser::GetFullStageName(
- const protos::pbzero::GpuRenderStageEvent_Decoder& event) {
+ const protos::pbzero::GpuRenderStageEvent_Decoder& event) const {
size_t stage_id = static_cast<size_t>(event.stage_id());
StringId stage_name;
@@ -237,27 +244,6 @@
snprintf(buffer, sizeof(buffer), "render stage(%zu)", stage_id);
stage_name = context_->storage->InternString(buffer);
}
- // If the slice has a render target handle, we append the hex value of the
- // handle to the name. If a debug marker is available, we append the name
- // of the render target.
- if (event.has_render_target_handle()) {
- char buffer[256];
- base::StringWriter str_writer(buffer, sizeof(buffer));
- str_writer.AppendString(context_->storage->GetString(stage_name));
- auto framebuffer_names =
- debug_marker_names_[static_cast<int32_t>(VK_OBJECT_TYPE_FRAMEBUFFER)];
- auto debug_marker_name =
- framebuffer_names.find(event.render_target_handle());
- str_writer.AppendChar('[');
- if (debug_marker_name == framebuffer_names.end()) {
- str_writer.AppendLiteral("0x");
- str_writer.AppendHexInt(event.render_target_handle());
- } else {
- str_writer.AppendString(base::StringView(debug_marker_name->second));
- }
- str_writer.AppendChar(']');
- stage_name = context_->storage->InternString(str_writer.GetStringView());
- }
return stage_name;
}
@@ -271,7 +257,7 @@
StringId track_name = context_->storage->InternString(hw_queue.name());
if (gpu_hw_queue_counter_ >= gpu_hw_queue_ids_.size() ||
!gpu_hw_queue_ids_[gpu_hw_queue_counter_].has_value()) {
- tables::GpuTrackTable::Row track(track_name.id);
+ tables::GpuTrackTable::Row track(track_name);
track.scope = gpu_render_stage_scope_id_;
track.description = context_->storage->InternString(hw_queue.description());
if (gpu_hw_queue_counter_ >= gpu_hw_queue_ids_.size()) {
@@ -298,7 +284,7 @@
context_->storage->mutable_gpu_track_table()->mutable_description()->Set(
row, context_->storage->InternString(hw_queue.description()));
} else {
- tables::GpuTrackTable::Row track(track_name.id);
+ tables::GpuTrackTable::Row track(track_name);
track.scope = gpu_render_stage_scope_id_;
track.description =
context_->storage->InternString(hw_queue.description());
@@ -306,6 +292,21 @@
}
++gpu_hw_queue_counter_;
}
+base::Optional<std::string> GraphicsEventParser::FindDebugName(
+ int32_t vk_object_type,
+ uint64_t vk_handle) const {
+ auto map = debug_marker_names_.find(vk_object_type);
+ if (map == debug_marker_names_.end()) {
+ return base::nullopt;
+ }
+
+ auto name = map->second.find(vk_handle);
+ if (name == map->second.end()) {
+ return base::nullopt;
+ } else {
+ return name->second;
+ }
+}
void GraphicsEventParser::ParseGpuRenderStageEvent(int64_t ts,
ConstBytes blob) {
@@ -373,23 +374,45 @@
}
StringId track_name =
context_->storage->InternString(writer.GetStringView());
- tables::GpuTrackTable::Row track(track_name.id);
+ tables::GpuTrackTable::Row track(track_name);
track.scope = gpu_render_stage_scope_id_;
track_id = context_->track_tracker->InternGpuTrack(track);
gpu_hw_queue_ids_.resize(hw_queue_id + 1);
gpu_hw_queue_ids_[hw_queue_id] = track_id;
}
- StringId stage_name = GetFullStageName(event);
- const auto slice_id = context_->slice_tracker->Scoped(
- ts, track_id, 0 /* cat */, stage_name,
- static_cast<int64_t>(event.duration()), args_callback);
+ auto render_target_name = FindDebugName(VK_OBJECT_TYPE_FRAMEBUFFER, event.render_target_handle());
+ auto render_target_name_id = render_target_name.has_value()
+ ? context_->storage->InternString(
+ render_target_name.value().c_str())
+ : kNullStringId;
+ auto render_pass_name = FindDebugName(VK_OBJECT_TYPE_RENDER_PASS, event.render_pass_handle());
+ auto render_pass_name_id = render_pass_name.has_value()
+ ? context_->storage->InternString(
+ render_pass_name.value().c_str())
+ : kNullStringId;
+ auto command_buffer_name = FindDebugName(VK_OBJECT_TYPE_COMMAND_BUFFER, event.command_buffer_handle());
+ auto command_buffer_name_id = command_buffer_name.has_value()
+ ? context_->storage->InternString(
+ command_buffer_name.value().c_str())
+ : kNullStringId;
- context_->storage->mutable_gpu_slice_table()->Insert(
- tables::GpuSliceTable::Row(
- slice_id.value(), static_cast<int64_t>(event.context()),
- static_cast<int64_t>(event.render_target_handle()),
- base::nullopt /*frame_id*/, event.submission_id(), hw_queue_id));
+ tables::GpuSliceTable::Row row;
+ row.ts = ts;
+ row.track_id = track_id.value;
+ row.name = GetFullStageName(event);
+ row.dur = static_cast<int64_t>(event.duration());
+ row.context_id = static_cast<int64_t>(event.context());
+ row.render_target = static_cast<int64_t>(event.render_target_handle());
+ row.render_target_name = render_target_name_id;
+ row.render_pass = static_cast<int64_t>(event.render_pass_handle());
+ row.render_pass_name = render_pass_name_id;
+ row.command_buffer = static_cast<int64_t>(event.command_buffer_handle());
+ row.command_buffer_name = command_buffer_name_id;
+ row.submission_id = event.submission_id();
+ row.hw_queue_id = hw_queue_id;
+
+ context_->slice_tracker->ScopedGpu(row, args_callback);
}
}
@@ -452,23 +475,23 @@
const uint32_t frame_number =
event.has_frame_number() ? event.frame_number() : 0;
- tables::GpuTrackTable::Row track(track_name_id.id);
+ tables::GpuTrackTable::Row track(track_name_id);
track.scope = graphics_event_scope_id_;
TrackId track_id = context_->track_tracker->InternGpuTrack(track);
- auto scoped_callback = [this,
- layer_name_id](ArgsTracker::BoundInserter* inserter) {
- inserter->AddArg(layer_name_key_id_, Variadic::String(layer_name_id));
- };
- auto opt_slice_id =
- context_->slice_tracker->Scoped(timestamp, track_id, 0 /* cat */,
- event_name_id, duration, scoped_callback);
+ {
+ auto scoped_callback =
+ [this, layer_name_id](ArgsTracker::BoundInserter* inserter) {
+ inserter->AddArg(layer_name_key_id_, Variadic::String(layer_name_id));
+ };
- if (opt_slice_id) {
tables::GpuSliceTable::Row row;
- row.slice_id = opt_slice_id.value();
+ row.ts = timestamp;
+ row.track_id = track_id.value;
+ row.name = event_name_id;
+ row.dur = duration;
row.frame_id = frame_number;
- context_->storage->mutable_gpu_slice_table()->Insert(row);
+ context_->slice_tracker->ScopedGpu(row, scoped_callback);
}
/* Displayed Frame track */
@@ -476,7 +499,7 @@
if (previous_timestamp_ == 0) {
const StringId present_track_name_id =
context_->storage->InternString("Displayed Frame");
- tables::GpuTrackTable::Row present_track(present_track_name_id.id);
+ tables::GpuTrackTable::Row present_track(present_track_name_id);
present_track.scope = graphics_event_scope_id_;
present_track_id_ =
context_->track_tracker->InternGpuTrack(present_track);
@@ -508,17 +531,18 @@
Variadic::String(present_frame_layer_name_id));
};
// End the current slice that's being tracked.
- const auto present_slice_id_end =
- context_->slice_tracker->End(timestamp, present_track_id_, 0,
- present_event_name_id_, args_callback);
+ const auto opt_slice_id = context_->slice_tracker->EndGpu(
+ timestamp, present_track_id_, args_callback);
- if (present_slice_id_end) {
+ if (opt_slice_id) {
// The slice could have had additional buffers in it, so we need to
// update the name.
- context_->storage->mutable_slice_table()->mutable_name()->Set(
- present_slice_id_end.value(),
- context_->storage->InternString(
- present_frame_name_.GetStringView()));
+ auto* slice_table = context_->storage->mutable_slice_table();
+
+ uint32_t row_idx = *slice_table->id().IndexOf(*opt_slice_id);
+ StringId frame_name_id = context_->storage->InternString(
+ present_frame_name_.GetStringView());
+ slice_table->mutable_name()->Set(row_idx, frame_name_id);
}
present_frame_layer_name_.reset();
@@ -531,15 +555,13 @@
present_frame_layer_name_.AppendString(event.layer_name());
present_event_name_id_ =
context_->storage->InternString(present_frame_name_.GetStringView());
- const auto present_slice_id = context_->slice_tracker->Begin(
- timestamp, present_track_id_, 0 /* cat */, present_event_name_id_);
- if (present_slice_id) {
- tables::GpuSliceTable::Row row;
- row.slice_id = present_slice_id.value();
- row.frame_id = frame_number;
- context_->storage->mutable_gpu_slice_table()->Insert(row);
- }
+ tables::GpuSliceTable::Row row;
+ row.ts = timestamp;
+ row.track_id = present_track_id_.value;
+ row.name = present_event_name_id_;
+ row.frame_id = frame_number;
+ context_->slice_tracker->BeginGpu(row);
}
}
}
@@ -555,6 +577,8 @@
case VulkanMemoryEvent::SOURCE_DRIVER:
allocation_scope = static_cast<VulkanMemoryEvent::AllocationScope>(
event.allocation_scope());
+ if (allocation_scope == VulkanMemoryEvent::SCOPE_UNSPECIFIED)
+ return;
switch (event.operation()) {
case VulkanMemoryEvent::OP_CREATE:
vulkan_driver_memory_counters_[allocation_scope] +=
@@ -689,12 +713,10 @@
vulkan_memory_event);
auto* allocs = context_->storage->mutable_vulkan_memory_allocations_table();
- auto id = allocs->Insert(vulkan_memory_event_row);
- uint32_t row = *allocs->id().IndexOf(id);
+ VulkanAllocId id = allocs->Insert(vulkan_memory_event_row);
if (vulkan_memory_event.has_annotations()) {
- ArgsTracker::BoundInserter inserter(context_->args_tracker.get(),
- TableId::kVulkanMemoryAllocation, row);
+ auto inserter = context_->args_tracker->AddArgsTo(id);
for (auto it = vulkan_memory_event.annotations(); it; ++it) {
protos::pbzero::VulkanMemoryEventAnnotation::Decoder annotation(*it);
@@ -715,7 +737,7 @@
sequence_state,
static_cast<uint64_t>(annotation.string_iid()));
- inserter.AddArg(key_id, Variadic::String(string_id.id));
+ inserter.AddArg(key_id, Variadic::String(string_id));
}
}
}
@@ -724,7 +746,7 @@
void GraphicsEventParser::ParseGpuLog(int64_t ts, ConstBytes blob) {
protos::pbzero::GpuLog::Decoder event(blob.data, blob.size);
- tables::GpuTrackTable::Row track(gpu_log_track_name_id_.id);
+ tables::GpuTrackTable::Row track(gpu_log_track_name_id_);
track.scope = gpu_log_scope_id_;
TrackId track_id = context_->track_tracker->InternGpuTrack(track);
@@ -746,15 +768,16 @@
severity < log_severity_ids_.size()
? log_severity_ids_[static_cast<size_t>(event.severity())]
: log_severity_ids_[log_severity_ids_.size() - 1];
- const auto slice_id = context_->slice_tracker->Scoped(
- ts, track_id, 0 /* cat */, severity_id, 0 /* duration */, args_callback);
tables::GpuSliceTable::Row row;
- row.slice_id = slice_id.value();
- context_->storage->mutable_gpu_slice_table()->Insert(row);
+ row.ts = ts;
+ row.track_id = track_id.value;
+ row.name = severity_id;
+ row.dur = 0;
+ context_->slice_tracker->ScopedGpu(row, args_callback);
}
-void GraphicsEventParser::ParseVulkanApiEvent(ConstBytes blob) {
+void GraphicsEventParser::ParseVulkanApiEvent(int64_t ts, ConstBytes blob) {
protos::pbzero::VulkanApiEvent::Decoder vk_event(blob.data, blob.size);
if (vk_event.has_vk_debug_utils_object_name()) {
protos::pbzero::VulkanApiEvent_VkDebugUtilsObjectName::Decoder event(
@@ -762,6 +785,32 @@
debug_marker_names_[event.object_type()][event.object()] =
event.object_name().ToStdString();
}
+ if (vk_event.has_vk_queue_submit()) {
+ protos::pbzero::VulkanApiEvent_VkQueueSubmit::Decoder event(
+ vk_event.vk_queue_submit());
+ // Once flow table is implemented, we can create a nice UI that link the
+ // vkQueueSubmit to GpuRenderStageEvent. For now, just add it as in a GPU
+ // track so that they can appear close to the render stage slices.
+ tables::GpuTrackTable::Row track(vk_event_track_id_);
+ track.scope = vk_event_scope_id_;
+ TrackId track_id = context_->track_tracker->InternGpuTrack(track);
+ tables::GpuSliceTable::Row row;
+ row.ts = ts;
+ row.dur = static_cast<int64_t>(event.duration_ns());
+ row.track_id = track_id.value;
+ row.name = vk_queue_submit_id_;
+ if (event.has_vk_command_buffers()) {
+ row.command_buffer = static_cast<int64_t>(*event.vk_command_buffers());
+ }
+ row.submission_id = event.submission_id();
+ auto args_callback = [this, &event](ArgsTracker::BoundInserter* inserter) {
+ inserter->AddArg(context_->storage->InternString("pid"),
+ Variadic::Integer(event.pid()));
+ inserter->AddArg(context_->storage->InternString("tid"),
+ Variadic::Integer(event.tid()));
+ };
+ context_->slice_tracker->ScopedGpu(row, args_callback);
+ }
}
} // namespace trace_processor
diff --git a/src/trace_processor/importers/proto/graphics_event_parser.h b/src/trace_processor/importers/proto/graphics_event_parser.h
index 73b8991..10bf5e5 100644
--- a/src/trace_processor/importers/proto/graphics_event_parser.h
+++ b/src/trace_processor/importers/proto/graphics_event_parser.h
@@ -22,6 +22,7 @@
#include "perfetto/ext/base/optional.h"
#include "perfetto/protozero/field.h"
#include "protos/perfetto/trace/gpu/gpu_render_stage_event.pbzero.h"
+#include "src/trace_processor/args_tracker.h"
#include "src/trace_processor/importers/proto/proto_incremental_state.h"
#include "src/trace_processor/importers/proto/vulkan_memory_tracker.h"
#include "src/trace_processor/trace_storage.h"
@@ -66,14 +67,16 @@
void UpdateVulkanMemoryAllocationCounters(UniquePid,
const VulkanMemoryEvent::Decoder&);
- void ParseVulkanApiEvent(ConstBytes);
+ void ParseVulkanApiEvent(int64_t, ConstBytes);
private:
const StringId GetFullStageName(
- const protos::pbzero::GpuRenderStageEvent_Decoder& event);
+ const protos::pbzero::GpuRenderStageEvent_Decoder& event) const;
void InsertGpuTrack(
const protos::pbzero::
GpuRenderStageEvent_Specifications_Description_Decoder& hw_queue);
+ base::Optional<std::string> FindDebugName(int32_t vk_object_type,
+ uint64_t vk_handle) const;
TraceProcessorContext* const context_;
VulkanMemoryTracker vulkan_memory_tracker_;
@@ -115,10 +118,15 @@
const StringId log_message_id_;
std::array<StringId, 7> log_severity_ids_;
// For Vulkan events.
+ // For VulkanApiEvent.VkDebugUtilsObjectName.
// Map of vk handle -> vk object name.
using DebugMarkerMap = std::unordered_map<uint64_t, std::string>;
// Map of VkObjectType -> DebugMarkerMap.
std::unordered_map<int32_t, DebugMarkerMap> debug_marker_names_;
+ // For VulkanApiEvent.VkQueueSubmit.
+ StringId vk_event_track_id_;
+ StringId vk_event_scope_id_;
+ StringId vk_queue_submit_id_;
};
} // namespace trace_processor
} // namespace perfetto
diff --git a/src/trace_processor/importers/proto/heap_graph_module.cc b/src/trace_processor/importers/proto/heap_graph_module.cc
index 49d2f02..8da6932 100644
--- a/src/trace_processor/importers/proto/heap_graph_module.cc
+++ b/src/trace_processor/importers/proto/heap_graph_module.cc
@@ -92,7 +92,7 @@
using perfetto::protos::pbzero::TracePacket;
HeapGraphModule::HeapGraphModule(TraceProcessorContext* context)
- : context_(context), heap_graph_tracker_(context) {
+ : context_(context) {
RegisterForField(TracePacket::kHeapGraphFieldNumber, context);
RegisterForField(TracePacket::kDeobfuscationMappingFieldNumber, context);
}
@@ -115,10 +115,11 @@
void HeapGraphModule::ParseHeapGraph(uint32_t seq_id,
int64_t ts,
protozero::ConstBytes blob) {
+ auto* heap_graph_tracker = HeapGraphTracker::GetOrCreate(context_);
protos::pbzero::HeapGraph::Decoder heap_graph(blob.data, blob.size);
UniquePid upid = context_->process_tracker->GetOrCreateProcess(
static_cast<uint32_t>(heap_graph.pid()));
- heap_graph_tracker_.SetPacketIndex(seq_id, heap_graph.index());
+ heap_graph_tracker->SetPacketIndex(seq_id, heap_graph.index());
for (auto it = heap_graph.objects(); it; ++it) {
protos::pbzero::HeapGraphObject::Decoder object(*it);
HeapGraphTracker::SourceObject obj;
@@ -156,14 +157,14 @@
ref.owned_object_id = object_ids[i];
obj.references.emplace_back(std::move(ref));
}
- heap_graph_tracker_.AddObject(seq_id, upid, ts, std::move(obj));
+ heap_graph_tracker->AddObject(seq_id, upid, ts, std::move(obj));
}
for (auto it = heap_graph.type_names(); it; ++it) {
protos::pbzero::InternedString::Decoder entry(*it);
const char* str = reinterpret_cast<const char*>(entry.str().data);
auto str_view = base::StringView(str, entry.str().size);
- heap_graph_tracker_.AddInternedTypeName(
+ heap_graph_tracker->AddInternedTypeName(
seq_id, entry.iid(), context_->storage->InternString(str_view));
}
for (auto it = heap_graph.field_names(); it; ++it) {
@@ -171,7 +172,7 @@
const char* str = reinterpret_cast<const char*>(entry.str().data);
auto str_view = base::StringView(str, entry.str().size);
- heap_graph_tracker_.AddInternedFieldName(
+ heap_graph_tracker->AddInternedFieldName(
seq_id, entry.iid(), context_->storage->InternString(str_view));
}
for (auto it = heap_graph.roots(); it; ++it) {
@@ -191,15 +192,16 @@
stats::heap_graph_malformed_packet, static_cast<int>(upid));
break;
}
- heap_graph_tracker_.AddRoot(seq_id, upid, ts, std::move(src_root));
+ heap_graph_tracker->AddRoot(seq_id, upid, ts, std::move(src_root));
}
if (!heap_graph.continued()) {
- heap_graph_tracker_.FinalizeProfile(seq_id);
+ heap_graph_tracker->FinalizeProfile(seq_id);
}
}
void HeapGraphModule::ParseDeobfuscationMapping(protozero::ConstBytes blob) {
// TODO(fmayer): Support multiple profiles in the same trace.
+ auto* heap_graph_tracker = HeapGraphTracker::GetOrCreate(context_);
protos::pbzero::DeobfuscationMapping::Decoder deobfuscation_mapping(
blob.data, blob.size);
for (auto class_it = deobfuscation_mapping.obfuscated_classes(); class_it;
@@ -212,15 +214,25 @@
cls.obfuscated_name().ToStdString().c_str());
} else {
const std::vector<int64_t>* cls_objects =
- heap_graph_tracker_.RowsForType(*obfuscated_class_name_id);
+ heap_graph_tracker->RowsForType(*obfuscated_class_name_id);
if (cls_objects) {
- auto interned_deobfuscated_name =
- context_->storage->InternString(cls.deobfuscated_name());
for (int64_t row : *cls_objects) {
+ const base::StringView obfuscated_type_name =
+ context_->storage->GetString(
+ context_->storage->mutable_heap_graph_object_table()
+ ->type_name()[static_cast<uint32_t>(row)]);
+ size_t array_count = NumberOfArrays(obfuscated_type_name);
+ std::string arrayed_deobfuscated_name =
+ cls.deobfuscated_name().ToStdString();
+ for (size_t i = 0; i < array_count; ++i)
+ arrayed_deobfuscated_name += "[]";
+ const StringId arrayed_deobfuscated_name_id =
+ context_->storage->InternString(
+ base::StringView(arrayed_deobfuscated_name));
context_->storage->mutable_heap_graph_object_table()
->mutable_deobfuscated_type_name()
- ->Set(static_cast<uint32_t>(row), interned_deobfuscated_name);
+ ->Set(static_cast<uint32_t>(row), arrayed_deobfuscated_name_id);
}
} else {
PERFETTO_DLOG("Class %s not found",
@@ -245,7 +257,7 @@
}
const std::vector<int64_t>* field_references =
- heap_graph_tracker_.RowsForField(*obfuscated_field_name_id);
+ heap_graph_tracker->RowsForField(*obfuscated_field_name_id);
if (field_references) {
auto interned_deobfuscated_name = context_->storage->InternString(
base::StringView(merged_deobfuscated));
diff --git a/src/trace_processor/importers/proto/heap_graph_module.h b/src/trace_processor/importers/proto/heap_graph_module.h
index 492ba60..2fde80e 100644
--- a/src/trace_processor/importers/proto/heap_graph_module.h
+++ b/src/trace_processor/importers/proto/heap_graph_module.h
@@ -40,7 +40,6 @@
void ParseDeobfuscationMapping(protozero::ConstBytes);
TraceProcessorContext* context_;
- HeapGraphTracker heap_graph_tracker_;
};
} // namespace trace_processor
diff --git a/src/trace_processor/importers/proto/heap_graph_tracker.cc b/src/trace_processor/importers/proto/heap_graph_tracker.cc
index 0f9ae9a..e2c1fa2 100644
--- a/src/trace_processor/importers/proto/heap_graph_tracker.cc
+++ b/src/trace_processor/importers/proto/heap_graph_tracker.cc
@@ -19,6 +19,23 @@
namespace perfetto {
namespace trace_processor {
+size_t NumberOfArrays(base::StringView type) {
+ if (type.size() < 2)
+ return 0;
+
+ size_t arrays = 0;
+ while (type.size() >= 2 * (arrays + 1) &&
+ memcmp(type.end() - 2 * (arrays + 1), "[]", 2) == 0) {
+ arrays++;
+ }
+
+ return arrays;
+}
+
+base::StringView NormalizeTypeName(base::StringView type) {
+ return base::StringView(type.data(), type.size() - NumberOfArrays(type) * 2);
+}
+
HeapGraphTracker::HeapGraphTracker(TraceProcessorContext* context)
: context_(context) {}
@@ -87,10 +104,24 @@
void HeapGraphTracker::SetPacketIndex(uint32_t seq_id, uint64_t index) {
SequenceState& sequence_state = GetOrCreateSequence(seq_id);
- if (sequence_state.prev_index != 0 &&
- sequence_state.prev_index + 1 != index) {
- PERFETTO_ELOG("Missing packets between %" PRIu64 " and %" PRIu64,
- sequence_state.prev_index, index);
+ bool dropped_packet = false;
+ // perfetto_hprof starts counting at index = 0.
+ if (!sequence_state.prev_index && index != 0) {
+ dropped_packet = true;
+ }
+
+ if (sequence_state.prev_index && *sequence_state.prev_index + 1 != index) {
+ dropped_packet = true;
+ }
+
+ if (dropped_packet) {
+ if (sequence_state.prev_index) {
+ PERFETTO_ELOG("Missing packets between %" PRIu64 " and %" PRIu64,
+ *sequence_state.prev_index, index);
+ } else {
+ PERFETTO_ELOG("Invalid first packet index %" PRIu64 " (!= 0)", index);
+ }
+
context_->storage->IncrementIndexedStats(
stats::heap_graph_missing_packet,
static_cast<int>(sequence_state.current_upid));
@@ -119,9 +150,12 @@
/*root_type=*/base::nullopt});
int64_t row = context_->storage->heap_graph_object_table().row_count() - 1;
sequence_state.object_id_to_row.emplace(obj.object_id, row);
- class_to_rows_[type_name].emplace_back(row);
+ base::StringView normalized_type =
+ NormalizeTypeName(context_->storage->GetString(type_name));
+ class_to_rows_[context_->storage->InternString(normalized_type)]
+ .emplace_back(row);
sequence_state.walker.AddNode(row, obj.self_size,
- static_cast<int32_t>(type_name.id));
+ static_cast<int32_t>(type_name.raw_id()));
}
for (const SourceObject& obj : sequence_state.current_objects) {
@@ -187,49 +221,66 @@
}
}
- auto* mapping_table =
- context_->storage->mutable_stack_profile_mapping_table();
-
- tables::StackProfileMappingTable::Row mapping_row{};
- mapping_row.name = context_->storage->InternString("JAVA");
- MappingId mapping_id = mapping_table->Insert(mapping_row);
-
- uint32_t mapping_idx = *mapping_table->id().IndexOf(mapping_id);
-
auto paths = sequence_state.walker.FindPathsFromRoot();
- for (const auto& p : paths.children)
- WriteFlamegraph(sequence_state, p.second, -1, 0, mapping_idx);
+ walkers_.emplace(
+ std::make_pair(sequence_state.current_upid, sequence_state.current_ts),
+ std::move(sequence_state.walker));
sequence_state_.erase(seq_id);
}
-void HeapGraphTracker::WriteFlamegraph(
- const SequenceState& sequence_state,
- const HeapGraphWalker::PathFromRoot& path,
- int32_t parent_id,
- uint32_t depth,
- uint32_t mapping_row) {
- tables::StackProfileFrameTable::Row row{};
- row.name = StringId(static_cast<uint32_t>(path.class_name));
- row.mapping = mapping_row;
+std::unique_ptr<tables::ExperimentalFlamegraphNodesTable>
+HeapGraphTracker::BuildFlamegraph(const int64_t current_ts,
+ const UniquePid current_upid) {
+ auto it = walkers_.find(std::make_pair(current_upid, current_ts));
+ if (it == walkers_.end())
+ return nullptr;
- auto id = context_->storage->mutable_stack_profile_frame_table()->Insert(row);
- int32_t frame_id = static_cast<int32_t>(id.value);
+ std::unique_ptr<tables::ExperimentalFlamegraphNodesTable> tbl(
+ new tables::ExperimentalFlamegraphNodesTable(
+ context_->storage->mutable_string_pool(), nullptr));
- auto* callsites = context_->storage->mutable_stack_profile_callsite_table();
- auto callsite_id = callsites->Insert({depth, parent_id, frame_id});
- parent_id = static_cast<int32_t>(callsite_id.value);
- depth++;
+ HeapGraphWalker::PathFromRoot init_path = it->second.FindPathsFromRoot();
+ auto profile_type = context_->storage->InternString("graph");
+ auto java_mapping = context_->storage->InternString("JAVA");
- tables::HeapProfileAllocationTable::Row alloc_row{
- sequence_state.current_ts, sequence_state.current_upid, parent_id,
- static_cast<int64_t>(path.count), static_cast<int64_t>(path.size)};
- // TODO(fmayer): Maybe add a separate table for heap graph flamegraphs.
- context_->storage->mutable_heap_profile_allocation_table()->Insert(alloc_row);
- for (const auto& p : path.children) {
- const HeapGraphWalker::PathFromRoot& child = p.second;
- WriteFlamegraph(sequence_state, child, parent_id, depth, mapping_row);
+ std::vector<int32_t> node_to_cumulative_size(init_path.nodes.size());
+ std::vector<int32_t> node_to_cumulative_count(init_path.nodes.size());
+ // i > 0 is to skip the artifical root node.
+ for (size_t i = init_path.nodes.size() - 1; i > 0; --i) {
+ const HeapGraphWalker::PathFromRoot::Node& node = init_path.nodes[i];
+
+ node_to_cumulative_size[i] += node.size;
+ node_to_cumulative_count[i] += node.count;
+ node_to_cumulative_size[node.parent_id] += node_to_cumulative_size[i];
+ node_to_cumulative_count[node.parent_id] += node_to_cumulative_count[i];
}
+
+ std::vector<uint32_t> node_to_row_idx(init_path.nodes.size());
+ // i = 1 is to skip the artifical root node.
+ for (size_t i = 1; i < init_path.nodes.size(); ++i) {
+ const HeapGraphWalker::PathFromRoot::Node& node = init_path.nodes[i];
+ PERFETTO_CHECK(node.parent_id < i);
+ base::Optional<uint32_t> parent_id;
+ if (node.parent_id != 0)
+ parent_id = node_to_row_idx[node.parent_id];
+ const uint32_t depth = node.depth;
+
+ tables::ExperimentalFlamegraphNodesTable::Row alloc_row{
+ current_ts, current_upid, profile_type, depth,
+ StringId::Raw(static_cast<uint32_t>(node.class_name)), java_mapping,
+ static_cast<int64_t>(node.count),
+ static_cast<int64_t>(node_to_cumulative_count[i]),
+ static_cast<int64_t>(node.size),
+ static_cast<int64_t>(node_to_cumulative_size[i]),
+ // For java dumps, set alloc_count == count, etc.
+ static_cast<int64_t>(node.count),
+ static_cast<int64_t>(node_to_cumulative_count[i]),
+ static_cast<int64_t>(node.size),
+ static_cast<int64_t>(node_to_cumulative_size[i]), parent_id};
+ node_to_row_idx[i] = *tbl->id().IndexOf(tbl->Insert(alloc_row));
+ }
+ return tbl;
}
void HeapGraphTracker::MarkReachable(int64_t row) {
diff --git a/src/trace_processor/importers/proto/heap_graph_tracker.h b/src/trace_processor/importers/proto/heap_graph_tracker.h
index 56c9e7f..0699311 100644
--- a/src/trace_processor/importers/proto/heap_graph_tracker.h
+++ b/src/trace_processor/importers/proto/heap_graph_tracker.h
@@ -32,7 +32,10 @@
class TraceProcessorContext;
-class HeapGraphTracker : public HeapGraphWalker::Delegate {
+size_t NumberOfArrays(base::StringView type);
+base::StringView NormalizeTypeName(base::StringView type);
+
+class HeapGraphTracker : public HeapGraphWalker::Delegate, public Destructible {
public:
struct SourceObject {
// All ids in this are in the trace iid space, not in the trace processor
@@ -54,6 +57,13 @@
explicit HeapGraphTracker(TraceProcessorContext* context);
+ static HeapGraphTracker* GetOrCreate(TraceProcessorContext* context) {
+ if (!context->heap_graph_tracker) {
+ context->heap_graph_tracker.reset(new HeapGraphTracker(context));
+ }
+ return static_cast<HeapGraphTracker*>(context->heap_graph_tracker.get());
+ }
+
void AddRoot(uint32_t seq_id, UniquePid upid, int64_t ts, SourceRoot root);
void AddObject(uint32_t seq_id, UniquePid upid, int64_t ts, SourceObject obj);
void AddInternedTypeName(uint32_t seq_id,
@@ -86,6 +96,10 @@
return &it->second;
}
+ std::unique_ptr<tables::ExperimentalFlamegraphNodesTable> BuildFlamegraph(
+ const int64_t current_ts,
+ const UniquePid current_upid);
+
private:
struct SequenceState {
SequenceState(HeapGraphTracker* tracker) : walker(tracker) {}
@@ -97,21 +111,17 @@
std::map<uint64_t, StringPool::Id> interned_type_names;
std::map<uint64_t, StringPool::Id> interned_field_names;
std::map<uint64_t, int64_t> object_id_to_row;
- uint64_t prev_index = 0;
+ base::Optional<uint64_t> prev_index;
HeapGraphWalker walker;
};
SequenceState& GetOrCreateSequence(uint32_t seq_id);
bool SetPidAndTimestamp(SequenceState* seq, UniquePid upid, int64_t ts);
- void WriteFlamegraph(const SequenceState& sequence_state,
- const HeapGraphWalker::PathFromRoot& path,
- int32_t parent_id,
- uint32_t depth,
- uint32_t mapping_row);
TraceProcessorContext* const context_;
std::map<uint32_t, SequenceState> sequence_state_;
+ std::map<std::pair<UniquePid, int64_t /* ts */>, HeapGraphWalker> walkers_;
std::map<StringPool::Id, std::vector<int64_t>> class_to_rows_;
std::map<StringPool::Id, std::vector<int64_t>> field_to_rows_;
diff --git a/src/trace_processor/importers/proto/heap_graph_tracker_unittest.cc b/src/trace_processor/importers/proto/heap_graph_tracker_unittest.cc
new file mode 100644
index 0000000..aa4e64d
--- /dev/null
+++ b/src/trace_processor/importers/proto/heap_graph_tracker_unittest.cc
@@ -0,0 +1,183 @@
+/*
+ * Copyright (C) 2020 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.
+ */
+
+#include "src/trace_processor/importers/proto/heap_graph_tracker.h"
+
+#include "perfetto/base/logging.h"
+#include "test/gtest_and_gmock.h"
+
+namespace perfetto {
+namespace trace_processor {
+namespace {
+
+using ::testing::UnorderedElementsAre;
+
+TEST(HeapGraphTrackerTest, BuildFlamegraph) {
+ // 4@A 5@B
+ // \ /
+ // 2@Y 3@Y
+ // \ /
+ // 1@X
+
+ constexpr uint64_t kSeqId = 1;
+ constexpr UniquePid kPid = 1;
+ constexpr int64_t kTimestamp = 1;
+
+ TraceProcessorContext context;
+ context.storage.reset(new TraceStorage());
+
+ HeapGraphTracker tracker(&context);
+
+ constexpr uint64_t kField = 1;
+
+ constexpr uint64_t kX = 1;
+ constexpr uint64_t kY = 2;
+ constexpr uint64_t kA = 3;
+ constexpr uint64_t kB = 4;
+
+ StringPool::Id field = context.storage->InternString("foo");
+ StringPool::Id x = context.storage->InternString("X");
+ StringPool::Id y = context.storage->InternString("Y");
+ StringPool::Id a = context.storage->InternString("A");
+ StringPool::Id b = context.storage->InternString("B");
+
+ tracker.AddInternedFieldName(kSeqId, kField, field);
+
+ tracker.AddInternedTypeName(kSeqId, kX, x);
+ tracker.AddInternedTypeName(kSeqId, kY, y);
+ tracker.AddInternedTypeName(kSeqId, kA, a);
+ tracker.AddInternedTypeName(kSeqId, kB, b);
+
+ {
+ HeapGraphTracker::SourceObject obj;
+ obj.object_id = 1;
+ obj.self_size = 1;
+ obj.type_id = kX;
+ HeapGraphTracker::SourceObject::Reference ref;
+ ref.field_name_id = kField;
+ ref.owned_object_id = 2;
+ obj.references.emplace_back(std::move(ref));
+
+ ref.field_name_id = kField;
+ ref.owned_object_id = 3;
+ obj.references.emplace_back(std::move(ref));
+
+ tracker.AddObject(kSeqId, kPid, kTimestamp, std::move(obj));
+ }
+
+ {
+ HeapGraphTracker::SourceObject obj;
+ obj.object_id = 2;
+ obj.self_size = 2;
+ obj.type_id = kY;
+ tracker.AddObject(kSeqId, kPid, kTimestamp, std::move(obj));
+ }
+
+ {
+ HeapGraphTracker::SourceObject obj;
+ obj.object_id = 3;
+ obj.self_size = 3;
+ obj.type_id = kY;
+ HeapGraphTracker::SourceObject::Reference ref;
+ ref.field_name_id = kField;
+ ref.owned_object_id = 4;
+ obj.references.emplace_back(std::move(ref));
+
+ ref.field_name_id = kField;
+ ref.owned_object_id = 5;
+ obj.references.emplace_back(std::move(ref));
+
+ tracker.AddObject(kSeqId, kPid, kTimestamp, std::move(obj));
+ }
+
+ {
+ HeapGraphTracker::SourceObject obj;
+ obj.object_id = 4;
+ obj.self_size = 4;
+ obj.type_id = kA;
+ tracker.AddObject(kSeqId, kPid, kTimestamp, std::move(obj));
+ }
+
+ {
+ HeapGraphTracker::SourceObject obj;
+ obj.object_id = 5;
+ obj.self_size = 5;
+ obj.type_id = kB;
+ tracker.AddObject(kSeqId, kPid, kTimestamp, std::move(obj));
+ }
+
+ HeapGraphTracker::SourceRoot root;
+ root.root_type = context.storage->InternString("ROOT");
+ root.object_ids.emplace_back(1);
+ tracker.AddRoot(kSeqId, kPid, kTimestamp, root);
+
+ tracker.FinalizeProfile(kSeqId);
+ std::unique_ptr<tables::ExperimentalFlamegraphNodesTable> flame =
+ tracker.BuildFlamegraph(kPid, kTimestamp);
+ ASSERT_NE(flame, nullptr);
+
+ auto cumulative_sizes = flame->cumulative_size().ToVectorForTesting();
+ EXPECT_THAT(cumulative_sizes, UnorderedElementsAre(15, 4, 14, 5));
+
+ auto cumulative_counts = flame->cumulative_count().ToVectorForTesting();
+ EXPECT_THAT(cumulative_counts, UnorderedElementsAre(5, 4, 1, 1));
+
+ auto sizes = flame->size().ToVectorForTesting();
+ EXPECT_THAT(sizes, UnorderedElementsAre(1, 5, 4, 5));
+
+ auto counts = flame->count().ToVectorForTesting();
+ EXPECT_THAT(counts, UnorderedElementsAre(1, 2, 1, 1));
+}
+
+static const char kArray[] = "X[]";
+static const char kDoubleArray[] = "X[][]";
+static const char kNoArray[] = "X";
+static const char kLongNoArray[] = "ABCDE";
+
+TEST(HeapGraphTrackerTest, NormalizeTypeName) {
+ // sizeof(...) - 1 below to get rid of the null-byte.
+ EXPECT_EQ(NormalizeTypeName(base::StringView(kArray, sizeof(kArray) - 1))
+ .ToStdString(),
+ "X");
+ EXPECT_EQ(NormalizeTypeName(
+ base::StringView(kDoubleArray, sizeof(kDoubleArray) - 1))
+ .ToStdString(),
+ "X");
+ EXPECT_EQ(NormalizeTypeName(base::StringView(kNoArray, sizeof(kNoArray) - 1))
+ .ToStdString(),
+ "X");
+ EXPECT_EQ(NormalizeTypeName(
+ base::StringView(kLongNoArray, sizeof(kLongNoArray) - 1))
+ .ToStdString(),
+ "ABCDE");
+}
+
+TEST(HeapGraphTrackerTest, NumberOfArray) {
+ // sizeof(...) - 1 below to get rid of the null-byte.
+ EXPECT_EQ(NumberOfArrays(base::StringView(kArray, sizeof(kArray) - 1)), 1u);
+ EXPECT_EQ(
+ NumberOfArrays(base::StringView(kDoubleArray, sizeof(kDoubleArray) - 1)),
+ 2u);
+ EXPECT_EQ(NumberOfArrays(base::StringView(kNoArray, sizeof(kNoArray) - 1)),
+ 0u);
+ EXPECT_EQ(
+ NumberOfArrays(base::StringView(kLongNoArray, sizeof(kLongNoArray) - 1)),
+ 0u);
+}
+
+} // namespace
+} // namespace trace_processor
+} // namespace perfetto
diff --git a/src/trace_processor/importers/proto/heap_graph_walker.cc b/src/trace_processor/importers/proto/heap_graph_walker.cc
index 90fd398..c7ba842 100644
--- a/src/trace_processor/importers/proto/heap_graph_walker.cc
+++ b/src/trace_processor/importers/proto/heap_graph_walker.cc
@@ -324,27 +324,70 @@
}
HeapGraphWalker::PathFromRoot HeapGraphWalker::FindPathsFromRoot() {
+ PathFromRoot path;
for (Node* root : roots_)
- FindPathFromRoot(root, &path_);
+ FindPathFromRoot(root, &path);
for (Node& node : nodes_)
node.find_paths_from_root_visited = false;
- return std::move(path_);
+ return path;
}
// TODO(fmayer): Teach this to handle field names.
-void HeapGraphWalker::FindPathFromRoot(Node* n, PathFromRoot* parent) {
- PathFromRoot& cur = parent->children[n->class_name];
- cur.size += n->self_size;
- cur.count++;
- cur.parent = parent;
- cur.class_name = n->class_name;
- for (Node* child : n->children) {
- if (child->distance_to_root == n->distance_to_root + 1 &&
- !child->find_paths_from_root_visited) {
- // Mark as visited in case there is another path with the same distance
- // from a root.
- child->find_paths_from_root_visited = true;
- FindPathFromRoot(child, &cur);
+void HeapGraphWalker::FindPathFromRoot(Node* first_node, PathFromRoot* path) {
+ // We have long retention chains (e.g. from LinkedList). If we use the stack
+ // here, we risk running out of stack space. This is why we use a vector to
+ // simulate the stack.
+ struct StackElem {
+ Node* node; // Node in the original graph.
+ size_t parent_id; // id of parent node in the result tree.
+ size_t i; // Index of the next child of this node to handle.
+ uint32_t depth; // Depth in the resulting tree
+ // (including artifical root).
+ };
+
+ std::vector<StackElem> stack{{first_node, PathFromRoot::kRoot, 0, 0}};
+
+ while (!stack.empty()) {
+ Node* n = stack.back().node;
+ size_t parent_id = stack.back().parent_id;
+ uint32_t depth = stack.back().depth;
+ size_t& i = stack.back().i;
+
+ auto it = path->nodes[parent_id].children.find(n->class_name);
+ if (it == path->nodes[parent_id].children.end()) {
+ size_t id = path->nodes.size();
+ path->nodes.emplace_back(PathFromRoot::Node{});
+ std::tie(it, std::ignore) =
+ path->nodes[parent_id].children.emplace(n->class_name, id);
+ path->nodes.back().class_name = n->class_name;
+ path->nodes.back().depth = depth;
+ path->nodes.back().parent_id = parent_id;
+ }
+ size_t id = it->second;
+ PathFromRoot::Node* output_tree_node = &path->nodes[id];
+
+ if (i == 0) {
+ // This is the first time we are looking at this node, so add its
+ // size to the relevant node in the resulting tree.
+ output_tree_node->size += n->self_size;
+ output_tree_node->count++;
+ }
+ // Otherwise we have already handled this node and just need to get its
+ // i-th child.
+ if (!n->children.empty()) {
+ Node* child = n->children[i];
+ if (++i == n->children.size())
+ stack.pop_back();
+
+ if (child->distance_to_root == n->distance_to_root + 1 &&
+ !child->find_paths_from_root_visited) {
+ // Mark as visited in case there is another path with the same distance
+ // from a root.
+ child->find_paths_from_root_visited = true;
+ stack.emplace_back(StackElem{child, id, 0, depth + 1});
+ }
+ } else {
+ stack.pop_back();
}
}
}
diff --git a/src/trace_processor/importers/proto/heap_graph_walker.h b/src/trace_processor/importers/proto/heap_graph_walker.h
index 4ec3dc8..052320b 100644
--- a/src/trace_processor/importers/proto/heap_graph_walker.h
+++ b/src/trace_processor/importers/proto/heap_graph_walker.h
@@ -97,12 +97,20 @@
class HeapGraphWalker {
public:
+ using ClassNameId = int32_t;
+
struct PathFromRoot {
- uint64_t size = 0;
- uint64_t count = 0;
- int32_t class_name = -1;
- std::map<int32_t, PathFromRoot> children;
- PathFromRoot* parent = nullptr;
+ static constexpr size_t kRoot = 0;
+ struct Node {
+ uint32_t depth = 0;
+ // Invariant: parent_id < id of this node.
+ size_t parent_id = 0;
+ uint64_t size = 0;
+ uint64_t count = 0;
+ ClassNameId class_name = -1;
+ std::map<ClassNameId, size_t> children;
+ };
+ std::vector<Node> nodes{Node{}};
};
class Delegate {
@@ -118,7 +126,7 @@
void AddEdge(int64_t owner_row, int64_t owned_row);
void AddNode(int64_t row, uint64_t size) { AddNode(row, size, -1); }
- void AddNode(int64_t row, uint64_t size, int32_t class_name);
+ void AddNode(int64_t row, uint64_t size, ClassNameId class_name);
// Mark a a node as root. This marks all the nodes reachable from it as
// reachable.
@@ -170,14 +178,13 @@
void FoundSCC(Node*);
int64_t RetainedSize(const Component&);
- void FindPathFromRoot(Node* n, PathFromRoot* parent);
+ void FindPathFromRoot(Node* n, PathFromRoot* path);
std::vector<Component> components_;
std::vector<Node*> node_stack_;
uint64_t next_node_index_ = 1;
std::vector<Node> nodes_;
- PathFromRoot path_;
std::vector<Node*> roots_;
Delegate* delegate_;
diff --git a/src/trace_processor/importers/proto/heap_graph_walker_unittest.cc b/src/trace_processor/importers/proto/heap_graph_walker_unittest.cc
index 4b1b586..9326133 100644
--- a/src/trace_processor/importers/proto/heap_graph_walker_unittest.cc
+++ b/src/trace_processor/importers/proto/heap_graph_walker_unittest.cc
@@ -584,14 +584,21 @@
}
bool HasPath(const HeapGraphWalker::PathFromRoot& path,
- std::vector<int32_t> class_names) {
+ const HeapGraphWalker::PathFromRoot::Node& node,
+ std::vector<HeapGraphWalker::ClassNameId> class_names) {
if (class_names.empty())
return true;
- auto it = path.children.find(class_names[0]);
- if (it == path.children.end())
+ auto it = node.children.find(class_names[0]);
+ if (it == node.children.end())
return false;
class_names.erase(class_names.begin());
- return HasPath(it->second, class_names);
+ return HasPath(path, path.nodes[it->second], std::move(class_names));
+}
+
+bool HasPath(const HeapGraphWalker::PathFromRoot& path,
+ std::vector<int32_t> class_names) {
+ return HasPath(path, path.nodes[HeapGraphWalker::PathFromRoot::kRoot],
+ std::move(class_names));
}
// 1 |
@@ -601,7 +608,7 @@
// ^ |
// | |
// 4R |
-TEST(HeapGraphWalkeTest, ShortestPath) {
+TEST(HeapGraphWalkerTest, ShortestPath) {
HeapGraphWalkerTestDelegate delegate;
HeapGraphWalker walker(&delegate);
walker.AddNode(1, 1, 1);
@@ -630,7 +637,7 @@
// ^ |
// | |
// 4R |
-TEST(HeapGraphWalkeTest, ShortestPathMultipleRoots) {
+TEST(HeapGraphWalkerTest, ShortestPathMultipleRoots) {
HeapGraphWalkerTestDelegate delegate;
HeapGraphWalker walker(&delegate);
walker.AddNode(1, 1, 1);
diff --git a/src/trace_processor/importers/proto/packet_sequence_state.h b/src/trace_processor/importers/proto/packet_sequence_state.h
index 903f99d..81ec6e0 100644
--- a/src/trace_processor/importers/proto/packet_sequence_state.h
+++ b/src/trace_processor/importers/proto/packet_sequence_state.h
@@ -47,7 +47,7 @@
public:
InternedMessageView(TraceBlobView msg) : message_(std::move(msg)) {}
- InternedMessageView(InternedMessageView&&) noexcept = default;
+ InternedMessageView(InternedMessageView&&) = default;
InternedMessageView& operator=(InternedMessageView&&) = default;
// Allow copy by cloning the TraceBlobView. This is required for
diff --git a/src/trace_processor/importers/proto/proto_trace_parser.cc b/src/trace_processor/importers/proto/proto_trace_parser.cc
index 9fe74c8..5b36057 100644
--- a/src/trace_processor/importers/proto/proto_trace_parser.cc
+++ b/src/trace_processor/importers/proto/proto_trace_parser.cc
@@ -43,7 +43,7 @@
#include "src/trace_processor/timestamped_trace_piece.h"
#include "src/trace_processor/trace_processor_context.h"
#include "src/trace_processor/track_tracker.h"
-#include "src/trace_processor/variadic.h"
+#include "src/trace_processor/types/variadic.h"
#include "protos/perfetto/common/trace_stats.pbzero.h"
#include "protos/perfetto/config/trace_config.pbzero.h"
@@ -174,7 +174,8 @@
context->storage->InternString("chrome_event.legacy_user_trace")) {
// TODO(140860736): Once we support null values for
// stack_profile_frame.symbol_set_id remove this hack
- context_->storage->mutable_symbol_table()->Insert({0, 0, 0, 0});
+ context_->storage->mutable_symbol_table()->Insert(
+ {0, kNullStringId, kNullStringId, 0});
}
ProtoTraceParser::~ProtoTraceParser() = default;
@@ -381,6 +382,9 @@
int pid = static_cast<int>(entry.pid());
+ if (entry.disconnected())
+ context_->storage->IncrementIndexedStats(
+ stats::heapprofd_client_disconnected, pid);
if (entry.buffer_corrupted())
context_->storage->IncrementIndexedStats(
stats::heapprofd_buffer_corrupted, pid);
@@ -444,18 +448,19 @@
break;
}
- auto maybe_callstack_id =
- stack_profile_tracker.FindCallstack(*callstack_it, &intern_lookup);
+ auto maybe_callstack_id = stack_profile_tracker.FindOrInsertCallstack(
+ *callstack_it, &intern_lookup);
if (!maybe_callstack_id) {
context_->storage->IncrementStats(stats::stackprofile_parser_error);
PERFETTO_ELOG("StreamingProfilePacket referencing invalid callstack!");
continue;
}
- int64_t callstack_id = *maybe_callstack_id;
+ uint32_t callstack_id = maybe_callstack_id->value;
tables::CpuProfileStackSampleTable::Row sample_row{
- sequence_state->state()->IncrementAndGetTrackEventTimeNs(*timestamp_it),
+ sequence_state->state()->IncrementAndGetTrackEventTimeNs(*timestamp_it *
+ 1000),
callstack_id, utid};
storage->mutable_cpu_profile_stack_sample_table()->Insert(sample_row);
}
@@ -515,8 +520,9 @@
protos::pbzero::ChromeEventBundle::Decoder bundle(blob.data, blob.size);
ArgsTracker args(context_);
if (bundle.has_metadata()) {
- uint32_t row = storage->mutable_raw_events()->AddRawEvent(
- ts, raw_chrome_metadata_event_id_, 0, 0);
+ RawId id = storage->mutable_raw_table()->Insert(
+ {ts, raw_chrome_metadata_event_id_, 0, 0});
+ auto inserter = args.AddArgsTo(id);
// Metadata is proxied via a special event in the raw table to JSON export.
for (auto it = bundle.metadata(); it; ++it) {
@@ -534,14 +540,15 @@
value = Variadic::Json(storage->InternString(metadata.json_value()));
} else {
context_->storage->IncrementStats(stats::empty_chrome_metadata);
+ continue;
}
- args.AddArg(TableId::kRawEvents, row, name_id, name_id, value);
+ args.AddArgsTo(id).AddArg(name_id, value);
}
}
if (bundle.has_legacy_ftrace_output()) {
- uint32_t row = storage->mutable_raw_events()->AddRawEvent(
- ts, raw_chrome_legacy_system_trace_event_id_, 0, 0);
+ RawId id = storage->mutable_raw_table()->Insert(
+ {ts, raw_chrome_legacy_system_trace_event_id_, 0, 0});
std::string data;
for (auto it = bundle.legacy_ftrace_output(); it; ++it) {
@@ -549,7 +556,7 @@
}
Variadic value =
Variadic::String(storage->InternString(base::StringView(data)));
- args.AddArg(TableId::kRawEvents, row, data_name_id_, data_name_id_, value);
+ args.AddArgsTo(id).AddArg(data_name_id_, value);
}
if (bundle.has_legacy_json_trace()) {
@@ -559,12 +566,11 @@
protos::pbzero::ChromeLegacyJsonTrace::USER_TRACE) {
continue;
}
- uint32_t row = storage->mutable_raw_events()->AddRawEvent(
- ts, raw_chrome_legacy_user_trace_event_id_, 0, 0);
+ RawId id = storage->mutable_raw_table()->Insert(
+ {ts, raw_chrome_legacy_user_trace_event_id_, 0, 0});
Variadic value =
Variadic::String(storage->InternString(legacy_trace.data()));
- args.AddArg(TableId::kRawEvents, row, data_name_id_, data_name_id_,
- value);
+ args.AddArgsTo(id).AddArg(data_name_id_, value);
}
}
}
@@ -574,7 +580,7 @@
auto utid = context_->process_tracker->GetOrCreateThread(event.thread_id());
StringId cat_id = metatrace_id_;
- StringId name_id = 0;
+ StringId name_id = kNullStringId;
char fallback[64];
if (event.has_event_id()) {
@@ -626,12 +632,19 @@
void ProtoTraceParser::ParseModuleSymbols(ConstBytes blob) {
protos::pbzero::ModuleSymbols::Decoder module_symbols(blob.data, blob.size);
- std::string hex_build_id = base::ToHex(module_symbols.build_id().data,
- module_symbols.build_id().size);
- auto mapping_rows = context_->storage->FindMappingRow(
- context_->storage->InternString(module_symbols.path()),
- context_->storage->InternString(base::StringView(hex_build_id)));
- if (mapping_rows.empty()) {
+ StringId build_id;
+ // TODO(b/148109467): Remove workaround once all active Chrome versions
+ // write raw bytes instead of a string as build_id.
+ if (module_symbols.build_id().size == 33) {
+ build_id = context_->storage->InternString(module_symbols.build_id());
+ } else {
+ build_id = context_->storage->InternString(base::StringView(base::ToHex(
+ module_symbols.build_id().data, module_symbols.build_id().size)));
+ }
+
+ auto mapping_ids = context_->storage->FindMappingRow(
+ context_->storage->InternString(module_symbols.path()), build_id);
+ if (mapping_ids.empty()) {
context_->storage->IncrementStats(stats::stackprofile_invalid_mapping_id);
return;
}
@@ -640,16 +653,14 @@
uint32_t symbol_set_id = context_->storage->symbol_table().row_count();
bool frame_found = false;
- for (int64_t mapping_row : mapping_rows) {
- std::vector<int64_t> frame_rows = context_->storage->FindFrameRow(
- static_cast<size_t>(mapping_row), address_symbols.address());
+ for (MappingId mapping_id : mapping_ids) {
+ std::vector<FrameId> frame_ids = context_->storage->FindFrameIds(
+ mapping_id, address_symbols.address());
- for (const int64_t frame_row : frame_rows) {
- PERFETTO_DCHECK(frame_row >= 0);
-
- uint32_t row_idx = static_cast<uint32_t>(frame_row);
+ for (const FrameId frame_id : frame_ids) {
auto* frames = context_->storage->mutable_stack_profile_frame_table();
- frames->mutable_symbol_set_id()->Set(row_idx, symbol_set_id);
+ uint32_t frame_row = *frames->id().IndexOf(frame_id);
+ frames->mutable_symbol_set_id()->Set(frame_row, symbol_set_id);
frame_found = true;
}
}
diff --git a/src/trace_processor/importers/proto/proto_trace_parser_unittest.cc b/src/trace_processor/importers/proto/proto_trace_parser_unittest.cc
index f90418d..d490f9a 100644
--- a/src/trace_processor/importers/proto/proto_trace_parser_unittest.cc
+++ b/src/trace_processor/importers/proto/proto_trace_parser_unittest.cc
@@ -58,6 +58,7 @@
#include "protos/perfetto/trace/trace_packet.pbzero.h"
#include "protos/perfetto/trace/track_event/debug_annotation.pbzero.h"
#include "protos/perfetto/trace/track_event/log_message.pbzero.h"
+#include "protos/perfetto/trace/track_event/process_descriptor.pbzero.h"
#include "protos/perfetto/trace/track_event/source_location.pbzero.h"
#include "protos/perfetto/trace/track_event/task_execution.pbzero.h"
#include "protos/perfetto/trace/track_event/thread_descriptor.pbzero.h"
@@ -79,6 +80,7 @@
using ::testing::NiceMock;
using ::testing::Pointwise;
using ::testing::Return;
+using ::testing::ReturnRef;
using ::testing::UnorderedElementsAreArray;
namespace {
@@ -149,42 +151,20 @@
MOCK_METHOD2(UpdateThread, UniqueTid(uint32_t tid, uint32_t tgid));
MOCK_METHOD1(GetOrCreateProcess, UniquePid(uint32_t pid));
-};
-
-// Mock trace storage that behaves like the real implementation, but allows for
-// the interactions with string interning/lookup to be overridden/inspected.
-class MockTraceStorage : public TraceStorage {
- public:
- MockTraceStorage() : TraceStorage() {
- ON_CALL(*this, InternString(_))
- .WillByDefault(Invoke([this](base::StringView str) {
- return TraceStorage::InternString(str);
- }));
-
- ON_CALL(*this, GetString(_)).WillByDefault(Invoke([this](StringId id) {
- return TraceStorage::GetString(id);
- }));
-
- ON_CALL(*this, GetThread(_))
- .WillByDefault(Invoke(this, &MockTraceStorage::GetThreadImpl));
- }
-
- const Thread& GetThreadImpl(UniqueTid utid) {
- return TraceStorage::GetThread(utid);
- }
-
- MOCK_METHOD1(InternString, StringId(base::StringView));
- MOCK_CONST_METHOD1(GetString, NullTermStringView(StringId));
-
- MOCK_CONST_METHOD1(GetThread, const Thread&(UniqueTid));
+ MOCK_METHOD2(SetProcessNameIfUnset,
+ void(UniquePid upid, StringId process_name_id));
};
class MockBoundInserter : public ArgsTracker::BoundInserter {
public:
- MockBoundInserter()
- : ArgsTracker::BoundInserter(nullptr, TableId::kSched, 0u) {}
+ MockBoundInserter() : ArgsTracker::BoundInserter(nullptr, nullptr, 0u) {
+ ON_CALL(*this, AddArg(_, _, _)).WillByDefault(ReturnRef(*this));
+ }
- MOCK_METHOD3(AddArg, void(StringId flat_key, StringId key, Variadic v));
+ MOCK_METHOD3(AddArg,
+ ArgsTracker::BoundInserter&(StringId flat_key,
+ StringId key,
+ Variadic v));
};
class MockSliceTracker : public SliceTracker {
@@ -215,9 +195,10 @@
class ProtoTraceParserTest : public ::testing::Test {
public:
ProtoTraceParserTest() {
- storage_ = new NiceMock<MockTraceStorage>();
+ storage_ = new TraceStorage();
context_.storage.reset(storage_);
context_.track_tracker.reset(new TrackTracker(&context_));
+ context_.global_args_tracker.reset(new GlobalArgsTracker(&context_));
context_.args_tracker.reset(new ArgsTracker(&context_));
context_.metadata_tracker.reset(new MetadataTracker(&context_));
event_ = new MockEventTracker(&context_);
@@ -260,22 +241,19 @@
}
bool HasArg(ArgSetId set_id, StringId key_id, Variadic value) {
- const auto& args = storage_->args();
- auto rows =
- std::equal_range(args.set_ids().begin(), args.set_ids().end(), set_id);
- for (; rows.first != rows.second; rows.first++) {
- size_t index = static_cast<size_t>(
- std::distance(args.set_ids().begin(), rows.first));
- if (args.keys()[index] == key_id) {
- EXPECT_EQ(args.flat_keys()[index], key_id);
- EXPECT_EQ(args.arg_values()[index], value);
- if (args.flat_keys()[index] == key_id &&
- args.arg_values()[index] == value) {
- return true;
+ const auto& args = storage_->arg_table();
+ RowMap rm = args.FilterToRowMap({args.arg_set_id().eq(set_id)});
+ bool found = false;
+ for (auto it = rm.IterateRows(); it; it.Next()) {
+ if (args.key()[it.row()] == key_id) {
+ EXPECT_EQ(args.flat_key()[it.row()], key_id);
+ if (storage_->GetArgValue(it.row()) == value) {
+ found = true;
+ break;
}
}
}
- return false;
+ return found;
}
protected:
@@ -288,7 +266,7 @@
MockProcessTracker* process_;
MockSliceTracker* slice_;
ClockTracker* clock_;
- NiceMock<MockTraceStorage>* storage_;
+ TraceStorage* storage_;
};
// TODO(eseckler): Refactor these into a new file for ftrace tests.
@@ -344,24 +322,22 @@
static const char buf_value[] = "This is a print event";
print->set_buf(buf_value);
- EXPECT_CALL(*process_, UpdateThread(123, 123));
+ EXPECT_CALL(*process_, GetOrCreateProcess(123));
Tokenize();
- const auto& raw = context_.storage->raw_events();
- ASSERT_EQ(raw.raw_event_count(), 2u);
- const auto& args = context_.storage->args();
- ASSERT_EQ(args.args_count(), 6u);
- ASSERT_EQ(args.arg_values()[0].int_value, 123);
- ASSERT_STREQ(
- context_.storage->GetString(args.arg_values()[1].string_value).c_str(),
- task_newtask);
- ASSERT_EQ(args.arg_values()[2].int_value, 12);
- ASSERT_EQ(args.arg_values()[3].int_value, 15);
- ASSERT_EQ(args.arg_values()[4].int_value, 20);
- ASSERT_STREQ(
- context_.storage->GetString(args.arg_values()[5].string_value).c_str(),
- buf_value);
+ const auto& raw = context_.storage->raw_table();
+ ASSERT_EQ(raw.row_count(), 2u);
+ const auto& args = context_.storage->arg_table();
+ ASSERT_EQ(args.row_count(), 6u);
+ ASSERT_EQ(args.int_value()[0], 123);
+ ASSERT_STREQ(context_.storage->GetString(args.string_value()[1]).c_str(),
+ task_newtask);
+ ASSERT_EQ(args.int_value()[2], 12);
+ ASSERT_EQ(args.int_value()[3], 15);
+ ASSERT_EQ(args.int_value()[4], 20);
+ ASSERT_STREQ(context_.storage->GetString(args.string_value()[5]).c_str(),
+ buf_value);
// TODO(taylori): Add test ftrace event with all field types
// and test here.
@@ -393,33 +369,31 @@
field->set_name("meta3");
field->set_uint_value(3);
- EXPECT_CALL(*storage_, InternString(base::StringView("Test")));
- EXPECT_CALL(*storage_, InternString(base::StringView("meta1")));
- EXPECT_CALL(*storage_, InternString(base::StringView("value1")));
- EXPECT_CALL(*storage_, InternString(base::StringView("meta2")));
- EXPECT_CALL(*storage_, InternString(base::StringView("meta3")));
-
Tokenize();
- const auto& raw = storage_->raw_events();
+ const auto& raw = storage_->raw_table();
- ASSERT_EQ(raw.raw_event_count(), 1u);
- ASSERT_EQ(raw.timestamps().back(), 100);
- ASSERT_EQ(storage_->GetThread(raw.utids().back()).tid, 10u);
+ ASSERT_EQ(raw.row_count(), 1u);
+ ASSERT_EQ(raw.ts()[raw.row_count() - 1], 100);
+ ASSERT_EQ(storage_->thread_table().tid()[raw.utid()[raw.row_count() - 1]],
+ 10u);
+ ASSERT_EQ(raw.name().GetString(raw.row_count() - 1), "Test");
- auto set_id = raw.arg_set_ids().back();
+ auto set_id = raw.arg_set_id()[raw.row_count() - 1];
- const auto& args = storage_->args();
- auto id_it =
- std::equal_range(args.set_ids().begin(), args.set_ids().end(), set_id);
+ const auto& args = storage_->arg_table();
+ RowMap rm = args.FilterToRowMap({args.arg_set_id().eq(set_id)});
- // Ignore string calls as they are handled by checking InternString calls
- // above.
+ auto row = rm.Get(0);
- auto it = id_it.first;
- auto row = static_cast<size_t>(std::distance(args.set_ids().begin(), it));
- ASSERT_EQ(args.arg_values()[++row].int_value, -2);
- ASSERT_EQ(args.arg_values()[++row].int_value, 3);
+ ASSERT_EQ(args.key().GetString(row), "meta1");
+ ASSERT_EQ(args.string_value().GetString(row++), "value1");
+
+ ASSERT_EQ(args.key().GetString(row), "meta2");
+ ASSERT_EQ(args.int_value()[row++], -2);
+
+ ASSERT_EQ(args.key().GetString(row), "meta3");
+ ASSERT_EQ(args.int_value()[row++], 3);
}
TEST_F(ProtoTraceParserTest, LoadMultipleEvents) {
@@ -641,6 +615,51 @@
Tokenize();
}
+TEST_F(ProtoTraceParserTest, ProcessNameFromProcessDescriptor) {
+ context_.sorter.reset(new TraceSorter(
+ &context_, std::numeric_limits<int64_t>::max() /*window size*/));
+ {
+ auto* packet = trace_.add_packet();
+ packet->set_trusted_packet_sequence_id(1);
+ packet->set_incremental_state_cleared(true);
+ auto* process_desc = packet->set_process_descriptor();
+ process_desc->set_pid(15);
+ process_desc->set_process_name("OldProcessName");
+ }
+ {
+ auto* packet = trace_.add_packet();
+ packet->set_trusted_packet_sequence_id(1);
+ packet->set_incremental_state_cleared(true);
+ auto* process_desc = packet->set_process_descriptor();
+ process_desc->set_pid(15);
+ process_desc->set_process_name("NewProcessName");
+ }
+ {
+ auto* packet = trace_.add_packet();
+ packet->set_trusted_packet_sequence_id(2);
+ packet->set_incremental_state_cleared(true);
+ auto* process_desc = packet->set_process_descriptor();
+ process_desc->set_pid(16);
+ process_desc->set_process_name("DifferentProcessName");
+ }
+
+ EXPECT_CALL(*process_, GetOrCreateProcess(15))
+ .WillRepeatedly(testing::Return(1u));
+ EXPECT_CALL(*process_, GetOrCreateProcess(16)).WillOnce(testing::Return(2u));
+
+ EXPECT_CALL(*process_, SetProcessNameIfUnset(
+ 1u, storage_->InternString("OldProcessName")));
+ // Packet with same thread, but different name should update the name.
+ EXPECT_CALL(*process_, SetProcessNameIfUnset(
+ 1u, storage_->InternString("NewProcessName")));
+ EXPECT_CALL(*process_,
+ SetProcessNameIfUnset(
+ 2u, storage_->InternString("DifferentProcessName")));
+
+ Tokenize();
+ context_.sorter->ExtractEventsForced();
+}
+
TEST_F(ProtoTraceParserTest, ThreadNameFromThreadDescriptor) {
context_.sorter.reset(new TraceSorter(
&context_, std::numeric_limits<int64_t>::max() /*window size*/));
@@ -682,16 +701,14 @@
.WillRepeatedly(testing::Return(1u));
EXPECT_CALL(*process_, UpdateThread(11, 15)).WillOnce(testing::Return(2u));
- EXPECT_CALL(*storage_, InternString(base::StringView("OldThreadName")))
- .WillOnce(Return(1));
- EXPECT_CALL(*process_, SetThreadNameIfUnset(1u, StringId(1)));
+ EXPECT_CALL(*process_, SetThreadNameIfUnset(
+ 1u, storage_->InternString("OldThreadName")));
// Packet with same thread, but different name should update the name.
- EXPECT_CALL(*storage_, InternString(base::StringView("NewThreadName")))
- .WillOnce(Return(2));
- EXPECT_CALL(*process_, SetThreadNameIfUnset(1u, StringId(2)));
- EXPECT_CALL(*storage_, InternString(base::StringView("DifferentThreadName")))
- .WillOnce(Return(3));
- EXPECT_CALL(*process_, SetThreadNameIfUnset(2u, StringId(3)));
+ EXPECT_CALL(*process_, SetThreadNameIfUnset(
+ 1u, storage_->InternString("NewThreadName")));
+ EXPECT_CALL(
+ *process_,
+ SetThreadNameIfUnset(2u, storage_->InternString("DifferentThreadName")));
Tokenize();
context_.sorter->ExtractEventsForced();
@@ -751,14 +768,11 @@
Tokenize();
EXPECT_CALL(*process_, UpdateThread(16, 15))
- .Times(3)
.WillRepeatedly(Return(1));
- TraceStorage::Thread thread(16);
- thread.upid = 1u;
- EXPECT_CALL(*storage_, GetThread(1))
- .Times(3)
- .WillRepeatedly(testing::ReturnRef(thread));
+ tables::ThreadTable::Row row(16);
+ row.upid = 1u;
+ storage_->mutable_thread_table()->Insert(row);
MockBoundInserter inserter;
@@ -834,14 +848,11 @@
Tokenize();
EXPECT_CALL(*process_, UpdateThread(16, 15))
- .Times(3)
.WillRepeatedly(Return(1));
- TraceStorage::Thread thread(16);
- thread.upid = 1u;
- EXPECT_CALL(*storage_, GetThread(1))
- .Times(3)
- .WillRepeatedly(testing::ReturnRef(thread));
+ tables::ThreadTable::Row row(16);
+ row.upid = 1u;
+ storage_->mutable_thread_table()->Insert(row);
MockBoundInserter inserter;
@@ -972,53 +983,42 @@
Tokenize();
EXPECT_CALL(*process_, UpdateThread(16, 15))
- .Times(5)
.WillRepeatedly(Return(1));
- TraceStorage::Thread thread(16);
- thread.upid = 2u;
- EXPECT_CALL(*storage_, GetThread(1))
- .WillRepeatedly(testing::ReturnRef(thread));
+ tables::ThreadTable::Row row(16);
+ row.upid = 2u;
+ storage_->mutable_thread_table()->Insert(row);
constexpr TrackId thread_1_track{0u};
constexpr TrackId process_2_track{1u};
- EXPECT_CALL(*storage_, InternString(base::StringView("cat2,cat3")))
- .WillOnce(Return(1));
- EXPECT_CALL(*storage_, InternString(base::StringView("ev2")))
- .WillOnce(Return(2));
- EXPECT_CALL(*storage_, InternString(base::StringView("cat1")))
- .WillRepeatedly(Return(3));
- EXPECT_CALL(*storage_, InternString(base::StringView("ev1")))
- .WillRepeatedly(Return(4));
+ StringId cat_2_3 = storage_->InternString("cat2,cat3");
+ StringId ev_2 = storage_->InternString("ev2");
+ StringId cat_1 = storage_->InternString("cat1");
+ StringId ev_1 = storage_->InternString("ev1");
InSequence in_sequence; // Below slices should be sorted by timestamp.
MockBoundInserter inserter;
- EXPECT_CALL(*slice_, Scoped(1005000, thread_1_track, StringId(1), StringId(2),
- 23000, _))
+ EXPECT_CALL(*slice_, Scoped(1005000, thread_1_track, cat_2_3, ev_2, 23000, _))
.WillOnce(DoAll(InvokeArgument<5>(&inserter), Return(0u)));
EXPECT_CALL(inserter, AddArg(_, _, Variadic::UnsignedInteger(9999u)));
EXPECT_CALL(inserter, AddArg(_, _, Variadic::Boolean(true)));
EXPECT_CALL(inserter, AddArg(_, _, _));
- EXPECT_CALL(*slice_,
- Begin(1010000, thread_1_track, StringId(3), StringId(4), _))
+ EXPECT_CALL(*slice_, Begin(1010000, thread_1_track, cat_1, ev_1, _))
.WillOnce(DoAll(InvokeArgument<4>(&inserter), Return(1u)));
- EXPECT_CALL(*slice_,
- End(1020000, thread_1_track, StringId(3), StringId(4), _))
+ EXPECT_CALL(*slice_, End(1020000, thread_1_track, cat_1, ev_1, _))
.WillOnce(DoAll(InvokeArgument<4>(&inserter), Return(1u)));
- EXPECT_CALL(*slice_,
- Scoped(1040000, thread_1_track, StringId(3), StringId(4), 0, _))
+ EXPECT_CALL(*slice_, Scoped(1040000, thread_1_track, cat_1, ev_1, 0, _))
.WillOnce(DoAll(InvokeArgument<5>(&inserter), Return(2u)));
- EXPECT_CALL(*slice_,
- Scoped(1050000, process_2_track, StringId(3), StringId(4), 0, _))
+ EXPECT_CALL(*slice_, Scoped(1050000, process_2_track, cat_1, ev_1, 0, _))
.WillOnce(DoAll(InvokeArgument<5>(&inserter), Return(3u)));
- // Second slice should have a legacy_event.original_tid arg.
- EXPECT_CALL(inserter, AddArg(_, _, Variadic::Integer(16)));
+ // Second slice should have a legacy_event.passthrough_utid arg.
+ EXPECT_CALL(inserter, AddArg(_, _, Variadic::UnsignedInteger(1u)));
context_.sorter->ExtractEventsForced();
@@ -1141,44 +1141,32 @@
EXPECT_CALL(*process_, UpdateThread(16, 15)).WillRepeatedly(Return(1));
- TraceStorage::Thread thread(16);
- thread.upid = 1u;
- EXPECT_CALL(*storage_, GetThread(1))
- .WillRepeatedly(testing::ReturnRef(thread));
+ tables::ThreadTable::Row row(16);
+ row.upid = 1u;
+ storage_->mutable_thread_table()->Insert(row);
- EXPECT_CALL(*storage_, InternString(base::StringView("cat1")))
- .WillRepeatedly(Return(1));
- EXPECT_CALL(*storage_, InternString(base::StringView("ev1")))
- .WillRepeatedly(Return(2));
- EXPECT_CALL(*storage_, InternString(base::StringView("ev2")))
- .WillRepeatedly(Return(4));
- EXPECT_CALL(*storage_, InternString(base::StringView("cat2")))
- .WillRepeatedly(Return(3));
- EXPECT_CALL(*storage_, InternString(base::StringView("cat2:scope1")))
- .WillOnce(Return(5));
- EXPECT_CALL(*storage_, GetString(StringId(1))).WillRepeatedly(Return("cat1"));
- EXPECT_CALL(*storage_, GetString(StringId(3))).WillRepeatedly(Return("cat2"));
+ StringId cat_1 = storage_->InternString("cat1");
+ StringId ev_1 = storage_->InternString("ev1");
+ StringId cat_2 = storage_->InternString("cat2");
+ StringId ev_2 = storage_->InternString("ev2");
InSequence in_sequence; // Below slices should be sorted by timestamp.
- EXPECT_CALL(*slice_, Begin(1010000, TrackId{1}, StringId(1), StringId(2), _))
+ EXPECT_CALL(*slice_, Begin(1010000, TrackId{1}, cat_1, ev_1, _))
.WillOnce(Return(0u));
- EXPECT_CALL(*slice_,
- Scoped(1015000, TrackId{1}, StringId(1), StringId(4), 0, _));
- EXPECT_CALL(*slice_,
- Scoped(1018000, TrackId{2}, StringId(3), StringId(4), 0, _));
- EXPECT_CALL(*slice_, End(1020000, TrackId{1}, StringId(1), StringId(2), _))
+ EXPECT_CALL(*slice_, Scoped(1015000, TrackId{1}, cat_1, ev_2, 0, _));
+ EXPECT_CALL(*slice_, Scoped(1018000, TrackId{2}, cat_2, ev_2, 0, _));
+ EXPECT_CALL(*slice_, End(1020000, TrackId{1}, cat_1, ev_1, _))
.WillOnce(Return(0u));
- EXPECT_CALL(*slice_,
- Scoped(1030000, TrackId{3}, StringId(3), StringId(4), 0, _));
+ EXPECT_CALL(*slice_, Scoped(1030000, TrackId{3}, cat_2, ev_2, 0, _));
context_.sorter->ExtractEventsForced();
// First track is for the thread; others are the async event tracks.
EXPECT_EQ(storage_->track_table().row_count(), 4u);
- EXPECT_EQ(storage_->track_table().name()[1], 2u);
- EXPECT_EQ(storage_->track_table().name()[2], 4u);
- EXPECT_EQ(storage_->track_table().name()[3], 4u);
+ EXPECT_EQ(storage_->track_table().name()[1], ev_1);
+ EXPECT_EQ(storage_->track_table().name()[2], ev_2);
+ EXPECT_EQ(storage_->track_table().name()[3], ev_2);
EXPECT_EQ(storage_->process_track_table().row_count(), 3u);
EXPECT_EQ(storage_->process_track_table().upid()[0], 1u);
@@ -1205,6 +1193,7 @@
auto* packet = trace_.add_packet();
packet->set_trusted_packet_sequence_id(1);
packet->set_incremental_state_cleared(true);
+ packet->set_timestamp(1000000);
auto* track_desc = packet->set_track_descriptor();
track_desc->set_uuid(1234);
track_desc->set_name("Thread track 1");
@@ -1215,6 +1204,7 @@
{
auto* packet = trace_.add_packet();
packet->set_trusted_packet_sequence_id(1);
+ packet->set_timestamp(1000000);
auto* track_desc = packet->set_track_descriptor();
track_desc->set_uuid(5678);
track_desc->set_name("Async track 1");
@@ -1268,6 +1258,7 @@
auto* packet = trace_.add_packet();
packet->set_trusted_packet_sequence_id(2);
packet->set_incremental_state_cleared(true);
+ packet->set_timestamp(1000000);
auto* track_desc = packet->set_track_descriptor();
track_desc->set_uuid(4321);
track_desc->set_name("Thread track 2");
@@ -1276,12 +1267,6 @@
thread_desc->set_tid(17);
}
{
- auto* packet = trace_.add_packet();
- packet->set_trusted_packet_sequence_id(2);
- auto* track_desc = packet->set_track_descriptor();
- track_desc->set_uuid(5678); // "Async track 1" defined on sequence 1.
- }
- {
// Async event completed on "Async track 1".
auto* packet = trace_.add_packet();
packet->set_trusted_packet_sequence_id(2);
@@ -1318,69 +1303,50 @@
EXPECT_CALL(*process_, UpdateThread(16, 15)).WillRepeatedly(Return(1));
EXPECT_CALL(*process_, UpdateThread(17, 15)).WillRepeatedly(Return(2));
- TraceStorage::Thread thread1(16);
- thread1.upid = 1u;
- EXPECT_CALL(*storage_, GetThread(1))
- .WillRepeatedly(testing::ReturnRef(thread1));
- TraceStorage::Thread thread2(16);
- thread2.upid = 2u;
- EXPECT_CALL(*storage_, GetThread(2))
- .WillRepeatedly(testing::ReturnRef(thread2));
+ tables::ThreadTable::Row t1(16);
+ t1.upid = 1u;
+ storage_->mutable_thread_table()->Insert(t1);
- EXPECT_CALL(*storage_, InternString(base::StringView("Thread track 1")))
- .WillOnce(Return(10));
- EXPECT_CALL(*storage_, InternString(base::StringView("Async track 1")))
- .WillOnce(Return(11));
- EXPECT_CALL(*storage_, InternString(base::StringView("Thread track 2")))
- .WillOnce(Return(12));
- EXPECT_CALL(*storage_, InternString(base::StringView("")))
- .WillOnce(Return(0));
+ tables::ThreadTable::Row t2(16);
+ t2.upid = 2u;
+ storage_->mutable_thread_table()->Insert(t2);
Tokenize();
- // First track is "Thread track 1"; second is "Async track 1", third is
- // "Thread track 2".
- EXPECT_EQ(storage_->track_table().row_count(), 3u);
- EXPECT_EQ(storage_->track_table().name()[0], 10u); // "Thread track 1"
- EXPECT_EQ(storage_->track_table().name()[1], 11u); // "Async track 1"
- EXPECT_EQ(storage_->track_table().name()[2], 12u); // "Thread track 2"
- EXPECT_EQ(storage_->thread_track_table().row_count(), 2u);
- EXPECT_EQ(storage_->thread_track_table().utid()[0], 1u);
- EXPECT_EQ(storage_->thread_track_table().utid()[1], 2u);
+ StringId cat_1 = storage_->InternString("cat1");
+ StringId ev_1 = storage_->InternString("ev1");
+ StringId cat_2 = storage_->InternString("cat2");
+ StringId ev_2 = storage_->InternString("ev2");
+ StringId cat_3 = storage_->InternString("cat3");
+ StringId ev_3 = storage_->InternString("ev3");
InSequence in_sequence; // Below slices should be sorted by timestamp.
- EXPECT_CALL(*storage_, InternString(base::StringView("cat1")))
- .WillOnce(Return(1));
- EXPECT_CALL(*storage_, InternString(base::StringView("ev1")))
- .WillOnce(Return(2));
- EXPECT_CALL(*slice_, Begin(1010000, TrackId{1}, StringId(1), StringId(2), _))
+ EXPECT_CALL(*slice_, Begin(1010000, TrackId{1}, cat_1, ev_1, _))
.WillOnce(Return(0u));
- EXPECT_CALL(*storage_, InternString(base::StringView("cat2")))
- .WillOnce(Return(3));
- EXPECT_CALL(*storage_, InternString(base::StringView("ev2")))
- .WillOnce(Return(4));
- EXPECT_CALL(*slice_,
- Scoped(1015000, TrackId{0}, StringId(3), StringId(4), 0, _))
+ EXPECT_CALL(*slice_, Scoped(1015000, TrackId{0}, cat_2, ev_2, 0, _))
.WillOnce(Return(1u));
- EXPECT_CALL(*storage_, InternString(base::StringView("cat3")))
- .WillOnce(Return(5));
- EXPECT_CALL(*storage_, InternString(base::StringView("ev3")))
- .WillOnce(Return(6));
- EXPECT_CALL(*slice_,
- Scoped(1016000, TrackId{2}, StringId(5), StringId(6), 0, _))
+ EXPECT_CALL(*slice_, Scoped(1016000, TrackId{3}, cat_3, ev_3, 0, _))
.WillOnce(Return(2u));
- EXPECT_CALL(*slice_, End(1020000, TrackId{1}, StringId(0), StringId(0), _))
+ EXPECT_CALL(*slice_,
+ End(1020000, TrackId{1}, kNullStringId, kNullStringId, _))
.WillOnce(Return(0u));
context_.sorter->ExtractEventsForced();
- // Track tables shouldn't have changed.
- EXPECT_EQ(storage_->track_table().row_count(), 3u);
+ // First track is "Thread track 1"; second is "Async track 1", third is global
+ // default track (parent of async track), fourth is "Thread track 2".
+ EXPECT_EQ(storage_->track_table().row_count(), 4u);
+ EXPECT_EQ(storage_->track_table().name().GetString(0), "Thread track 1");
+ EXPECT_EQ(storage_->track_table().name().GetString(1), "Async track 1");
+ EXPECT_EQ(storage_->track_table().name().GetString(2), "Default Track");
+ EXPECT_EQ(storage_->track_table().name().GetString(3), "Thread track 2");
EXPECT_EQ(storage_->thread_track_table().row_count(), 2u);
+ EXPECT_EQ(storage_->thread_track_table().utid()[0], 1u);
+ EXPECT_EQ(storage_->thread_track_table().utid()[1], 2u);
EXPECT_EQ(storage_->virtual_track_slices().slice_count(), 1u);
EXPECT_EQ(storage_->virtual_track_slices().slice_ids()[0], 0u);
@@ -1547,14 +1513,11 @@
Tokenize();
EXPECT_CALL(*process_, UpdateThread(16, 15))
- .Times(2)
.WillRepeatedly(Return(1));
- TraceStorage::Thread thread(16);
- thread.upid = 1u;
- EXPECT_CALL(*storage_, GetThread(1))
- .Times(2)
- .WillRepeatedly(testing::ReturnRef(thread));
+ tables::ThreadTable::Row row(16);
+ row.upid = 1u;
+ storage_->mutable_thread_table()->Insert(row);
constexpr TrackId track{0u};
InSequence in_sequence; // Below slices should be sorted by timestamp.
@@ -1652,43 +1615,30 @@
Tokenize();
EXPECT_CALL(*process_, UpdateThread(16, 15))
- .Times(2)
.WillRepeatedly(Return(1));
EXPECT_CALL(*process_, UpdateThread(17, 15))
- .Times(2)
.WillRepeatedly(Return(2));
- TraceStorage::Thread thread(16);
- thread.upid = 1u;
- EXPECT_CALL(*storage_, GetThread(1))
- .Times(2)
- .WillRepeatedly(testing::ReturnRef(thread));
+ tables::ThreadTable::Row t1(16);
+ t1.upid = 1u;
+ storage_->mutable_thread_table()->Insert(t1);
- TraceStorage::Thread thread2(17);
- thread2.upid = 1u;
- EXPECT_CALL(*storage_, GetThread(2))
- .Times(2)
- .WillRepeatedly(testing::ReturnRef(thread2));
+ tables::ThreadTable::Row t2(17);
+ t2.upid = 1u;
+ storage_->mutable_thread_table()->Insert(t2);
- EXPECT_CALL(*storage_, InternString(base::StringView("cat1")))
- .WillRepeatedly(Return(1));
- EXPECT_CALL(*storage_, InternString(base::StringView("ev2")))
- .WillRepeatedly(Return(2));
- EXPECT_CALL(*storage_, InternString(base::StringView("ev1")))
- .WillRepeatedly(Return(3));
+ StringId cat_1 = storage_->InternString("cat1");
+ StringId ev_2 = storage_->InternString("ev2");
+ StringId ev_1 = storage_->InternString("ev1");
constexpr TrackId thread_2_track{0u};
constexpr TrackId thread_1_track{1u};
InSequence in_sequence; // Below slices should be sorted by timestamp.
- EXPECT_CALL(*slice_,
- Begin(1005000, thread_2_track, StringId(1), StringId(2), _));
- EXPECT_CALL(*slice_,
- Begin(1010000, thread_1_track, StringId(1), StringId(3), _));
- EXPECT_CALL(*slice_,
- End(1015000, thread_2_track, StringId(1), StringId(2), _));
- EXPECT_CALL(*slice_,
- End(1020000, thread_1_track, StringId(1), StringId(3), _));
+ EXPECT_CALL(*slice_, Begin(1005000, thread_2_track, cat_1, ev_2, _));
+ EXPECT_CALL(*slice_, Begin(1010000, thread_1_track, cat_1, ev_1, _));
+ EXPECT_CALL(*slice_, End(1015000, thread_2_track, cat_1, ev_2, _));
+ EXPECT_CALL(*slice_, End(1020000, thread_1_track, cat_1, ev_1, _));
context_.sorter->ExtractEventsForced();
}
@@ -1820,91 +1770,64 @@
Tokenize();
EXPECT_CALL(*process_, UpdateThread(16, 15))
- .Times(2)
.WillRepeatedly(Return(1));
- TraceStorage::Thread thread(16);
- thread.upid = 1u;
- EXPECT_CALL(*storage_, GetThread(1))
- .Times(2)
- .WillRepeatedly(testing::ReturnRef(thread));
+ tables::ThreadTable::Row row(16);
+ row.upid = 1u;
+ storage_->mutable_thread_table()->Insert(row);
- EXPECT_CALL(*storage_, InternString(base::StringView("cat1")))
- .WillRepeatedly(Return(1));
- EXPECT_CALL(*storage_, InternString(base::StringView("ev1")))
- .WillRepeatedly(Return(2));
- EXPECT_CALL(*storage_, InternString(base::StringView("debug.an1")))
- .WillOnce(Return(3));
- EXPECT_CALL(*storage_, InternString(base::StringView("debug.an2")))
- .WillOnce(Return(4));
- EXPECT_CALL(*storage_, InternString(base::StringView("debug.an2.child1")))
- .WillRepeatedly(Return(5));
- EXPECT_CALL(*storage_, InternString(base::StringView("debug.an2.child2")))
- .WillRepeatedly(Return(6));
- EXPECT_CALL(*storage_, InternString(base::StringView("debug.an2.child2[0]")))
- .WillOnce(Return(7));
- EXPECT_CALL(*storage_, InternString(base::StringView("child21")))
- .WillOnce(Return(8));
- EXPECT_CALL(*storage_, InternString(base::StringView("debug.an2.child2[1]")))
- .WillOnce(Return(9));
- EXPECT_CALL(*storage_, InternString(base::StringView("debug.an2.child2[2]")))
- .WillOnce(Return(10));
- EXPECT_CALL(*storage_, InternString(base::StringView("debug.an3")))
- .WillOnce(Return(11));
- EXPECT_CALL(*storage_, InternString(base::StringView("debug.an4")))
- .WillOnce(Return(12));
- EXPECT_CALL(*storage_, InternString(base::StringView("debug.an5")))
- .WillOnce(Return(13));
- EXPECT_CALL(*storage_, InternString(base::StringView("debug.an6")))
- .WillOnce(Return(14));
- EXPECT_CALL(*storage_, InternString(base::StringView("debug.an7")))
- .WillOnce(Return(15));
- EXPECT_CALL(*storage_, InternString(base::StringView("val7")))
- .WillOnce(Return(16));
- EXPECT_CALL(*storage_, InternString(base::StringView("debug.an8")))
- .WillOnce(Return(17));
- EXPECT_CALL(*storage_, InternString(base::StringView("val8")))
- .WillOnce(Return(18));
- EXPECT_CALL(*storage_, InternString(base::StringView("debug.an8_foo")))
- .WillOnce(Return(19));
-
- EXPECT_CALL(*storage_, GetString(StringId(4))).WillOnce(Return("debug.an2"));
+ StringId cat_1 = storage_->InternString("cat1");
+ StringId ev_1 = storage_->InternString("ev1");
+ StringId debug_an_1 = storage_->InternString("debug.an1");
+ StringId debug_an_2_child_1 = storage_->InternString("debug.an2.child1");
+ StringId debug_an_2_child_2 = storage_->InternString("debug.an2.child2");
+ StringId debug_an_2_child_2_0 = storage_->InternString("debug.an2.child2[0]");
+ StringId child21 = storage_->InternString("child21");
+ StringId debug_an_2_child_2_1 = storage_->InternString("debug.an2.child2[1]");
+ StringId debug_an_2_child_2_2 = storage_->InternString("debug.an2.child2[2]");
+ StringId debug_an_3 = storage_->InternString("debug.an3");
+ StringId debug_an_4 = storage_->InternString("debug.an4");
+ StringId debug_an_5 = storage_->InternString("debug.an5");
+ StringId debug_an_6 = storage_->InternString("debug.an6");
+ StringId debug_an_7 = storage_->InternString("debug.an7");
+ StringId val_7 = storage_->InternString("val7");
+ StringId debug_an_8 = storage_->InternString("debug.an8");
+ StringId val_8 = storage_->InternString("val8");
+ StringId debug_an_8_foo = storage_->InternString("debug.an8_foo");
constexpr TrackId track{0u};
InSequence in_sequence; // Below slices should be sorted by timestamp.
- EXPECT_CALL(*slice_, Begin(1010000, track, StringId(1), StringId(2), _))
+ EXPECT_CALL(*slice_, Begin(1010000, track, cat_1, ev_1, _))
.WillOnce(DoAll(InvokeArgument<4>(&inserter), Return(1u)));
EXPECT_CALL(inserter,
- AddArg(StringId(3), StringId(3), Variadic::UnsignedInteger(10u)));
+ AddArg(debug_an_1, debug_an_1, Variadic::UnsignedInteger(10u)));
- EXPECT_CALL(inserter,
- AddArg(StringId(5), StringId(5), Variadic::Boolean(true)));
+ EXPECT_CALL(inserter, AddArg(debug_an_2_child_1, debug_an_2_child_1,
+ Variadic::Boolean(true)));
- EXPECT_CALL(inserter,
- AddArg(StringId(6), StringId(7), Variadic::String(StringId(8))));
+ EXPECT_CALL(inserter, AddArg(debug_an_2_child_2, debug_an_2_child_2_0,
+ Variadic::String(child21)));
- EXPECT_CALL(inserter, AddArg(StringId(6), StringId(9), Variadic::Real(2.2)));
+ EXPECT_CALL(inserter, AddArg(debug_an_2_child_2, debug_an_2_child_2_1,
+ Variadic::Real(2.2)));
- EXPECT_CALL(inserter,
- AddArg(StringId(6), StringId(10), Variadic::Integer(23)));
+ EXPECT_CALL(inserter, AddArg(debug_an_2_child_2, debug_an_2_child_2_2,
+ Variadic::Integer(23)));
- EXPECT_CALL(*slice_, End(1020000, track, StringId(1), StringId(2), _))
+ EXPECT_CALL(*slice_, End(1020000, track, cat_1, ev_1, _))
.WillOnce(DoAll(InvokeArgument<4>(&inserter), Return(1u)));
+ EXPECT_CALL(inserter, AddArg(debug_an_3, debug_an_3, Variadic::Integer(-3)));
EXPECT_CALL(inserter,
- AddArg(StringId(11), StringId(11), Variadic::Integer(-3)));
+ AddArg(debug_an_4, debug_an_4, Variadic::Boolean(true)));
+ EXPECT_CALL(inserter, AddArg(debug_an_5, debug_an_5, Variadic::Real(-5.5)));
+ EXPECT_CALL(inserter, AddArg(debug_an_6, debug_an_6, Variadic::Pointer(20u)));
EXPECT_CALL(inserter,
- AddArg(StringId(12), StringId(12), Variadic::Boolean(true)));
+ AddArg(debug_an_7, debug_an_7, Variadic::String(val_7)));
+ EXPECT_CALL(inserter, AddArg(debug_an_8, debug_an_8, Variadic::Json(val_8)));
EXPECT_CALL(inserter,
- AddArg(StringId(13), StringId(13), Variadic::Real(-5.5)));
- EXPECT_CALL(inserter,
- AddArg(StringId(14), StringId(14), Variadic::Pointer(20u)));
- EXPECT_CALL(inserter,
- AddArg(StringId(15), StringId(15), Variadic::String(16)));
- EXPECT_CALL(inserter, AddArg(StringId(17), StringId(17), Variadic::Json(18)));
- EXPECT_CALL(inserter,
- AddArg(StringId(19), StringId(19), Variadic::Integer(15)));
+ AddArg(debug_an_8_foo, debug_an_8_foo, Variadic::Integer(15)));
context_.sorter->ExtractEventsForced();
}
@@ -1952,28 +1875,26 @@
Tokenize();
- EXPECT_CALL(*process_, UpdateThread(16, 15)).WillOnce(Return(1));
+ EXPECT_CALL(*process_, UpdateThread(16, 15)).WillRepeatedly(Return(1));
- TraceStorage::Thread thread(16);
- thread.upid = 1u;
- EXPECT_CALL(*storage_, GetThread(1)).WillOnce(testing::ReturnRef(thread));
+ tables::ThreadTable::Row row(16);
+ row.upid = 1u;
+ storage_->mutable_thread_table()->Insert(row);
constexpr TrackId track{0u};
+
+ StringId cat_1 = storage_->InternString("cat1");
+ StringId ev_1 = storage_->InternString("ev1");
+ StringId file_1 = storage_->InternString("file1");
+ StringId func_1 = storage_->InternString("func1");
+
InSequence in_sequence; // Below slices should be sorted by timestamp.
MockBoundInserter inserter;
- EXPECT_CALL(*storage_, InternString(base::StringView("cat1")))
- .WillOnce(Return(1));
- EXPECT_CALL(*storage_, InternString(base::StringView("ev1")))
- .WillOnce(Return(2));
- EXPECT_CALL(*slice_, Begin(1010000, track, StringId(1), StringId(2), _))
+ EXPECT_CALL(*slice_, Begin(1010000, track, cat_1, ev_1, _))
.WillOnce(DoAll(InvokeArgument<4>(&inserter), Return(1u)));
- EXPECT_CALL(*storage_, InternString(base::StringView("file1")))
- .WillOnce(Return(3));
- EXPECT_CALL(*storage_, InternString(base::StringView("func1")))
- .WillOnce(Return(4));
- EXPECT_CALL(inserter, AddArg(_, _, Variadic::String(3)));
- EXPECT_CALL(inserter, AddArg(_, _, Variadic::String(4)));
+ EXPECT_CALL(inserter, AddArg(_, _, Variadic::String(file_1)));
+ EXPECT_CALL(inserter, AddArg(_, _, Variadic::String(func_1)));
EXPECT_CALL(inserter, AddArg(_, _, Variadic::UnsignedInteger(42)));
context_.sorter->ExtractEventsForced();
@@ -2031,35 +1952,31 @@
Tokenize();
- EXPECT_CALL(*process_, UpdateThread(16, 15)).WillOnce(Return(1));
+ EXPECT_CALL(*process_, UpdateThread(16, 15)).WillRepeatedly(Return(1));
- TraceStorage::Thread thread(16);
- thread.upid = 1u;
- EXPECT_CALL(*storage_, GetThread(1)).WillOnce(testing::ReturnRef(thread));
+ tables::ThreadTable::Row row(16);
+ row.upid = 1u;
+ storage_->mutable_thread_table()->Insert(row);
+
+ StringId cat_1 = storage_->InternString("cat1");
+ StringId ev_1 = storage_->InternString("ev1");
+ StringId body_1 = storage_->InternString("body1");
constexpr TrackId track{0};
InSequence in_sequence; // Below slices should be sorted by timestamp.
- EXPECT_CALL(*storage_, InternString(base::StringView("cat1")))
- .WillOnce(Return(1));
- EXPECT_CALL(*storage_, InternString(base::StringView("ev1")))
- .WillOnce(Return(2));
-
MockBoundInserter inserter;
- EXPECT_CALL(*slice_, Scoped(1010000, track, StringId(1), StringId(2), 0, _))
+ EXPECT_CALL(*slice_, Scoped(1010000, track, cat_1, ev_1, 0, _))
.WillOnce(DoAll(InvokeArgument<5>(&inserter), Return(1u)));
- EXPECT_CALL(*storage_, InternString(base::StringView("body1")))
- .WillOnce(Return(3));
-
// Call with logMessageBody (body1 in this case).
- EXPECT_CALL(inserter, AddArg(_, _, Variadic::String(StringId(3))));
+ EXPECT_CALL(inserter, AddArg(_, _, Variadic::String(body_1)));
context_.sorter->ExtractEventsForced();
EXPECT_GT(context_.storage->android_log_table().row_count(), 0u);
EXPECT_EQ(context_.storage->android_log_table().ts()[0], 1010000);
- EXPECT_EQ(context_.storage->android_log_table().msg()[0], 3u);
+ EXPECT_EQ(context_.storage->android_log_table().msg()[0], body_1);
}
TEST_F(ProtoTraceParserTest, TrackEventParseLegacyEventIntoRawTable) {
@@ -2116,46 +2033,40 @@
Tokenize();
- EXPECT_CALL(*process_, UpdateThread(16, 15)).WillOnce(Return(1));
+ EXPECT_CALL(*process_, UpdateThread(16, 15)).WillRepeatedly(Return(1));
- TraceStorage::Thread thread(16);
- thread.upid = 1u;
- EXPECT_CALL(*storage_, GetThread(1)).WillOnce(testing::ReturnRef(thread));
+ tables::ThreadTable::Row row(16);
+ row.upid = 1u;
+ storage_->mutable_thread_table()->Insert(row);
- EXPECT_CALL(*storage_, InternString(base::StringView("cat1")))
- .WillOnce(Return(1));
- EXPECT_CALL(*storage_, InternString(base::StringView("ev1")))
- .WillOnce(Return(2));
- EXPECT_CALL(*storage_, InternString(base::StringView("scope1")))
- .Times(1)
- .WillRepeatedly(Return(3));
- EXPECT_CALL(*storage_, InternString(base::StringView("?")))
- .WillOnce(Return(4));
- EXPECT_CALL(*storage_, InternString(base::StringView("debug.an1")))
- .WillOnce(Return(5));
+ StringId cat_1 = storage_->InternString("cat1");
+ StringId ev_1 = storage_->InternString("ev1");
+ StringId scope_1 = storage_->InternString("scope1");
+ StringId question = storage_->InternString("?");
+ StringId debug_an_1 = storage_->InternString("debug.an1");
context_.sorter->ExtractEventsForced();
::testing::Mock::VerifyAndClearExpectations(storage_);
- // Verify raw_events and args contents.
- const auto& raw_events = storage_->raw_events();
- EXPECT_EQ(raw_events.raw_event_count(), 1u);
- EXPECT_EQ(raw_events.timestamps()[0], 1010000);
- EXPECT_EQ(raw_events.name_ids()[0],
+ // Verify raw_table and args contents.
+ const auto& raw_table = storage_->raw_table();
+ EXPECT_EQ(raw_table.row_count(), 1u);
+ EXPECT_EQ(raw_table.ts()[0], 1010000);
+ EXPECT_EQ(raw_table.name()[0],
storage_->InternString("track_event.legacy_event"));
- EXPECT_EQ(raw_events.cpus()[0], 0u);
- EXPECT_EQ(raw_events.utids()[0], 1u);
- EXPECT_EQ(raw_events.arg_set_ids()[0], 1u);
+ EXPECT_EQ(raw_table.cpu()[0], 0u);
+ EXPECT_EQ(raw_table.utid()[0], 1u);
+ EXPECT_EQ(raw_table.arg_set_id()[0], 1u);
- EXPECT_GE(storage_->args().args_count(), 13u);
+ EXPECT_GE(storage_->arg_table().row_count(), 13u);
EXPECT_TRUE(HasArg(1u, storage_->InternString("legacy_event.category"),
- Variadic::String(1u)));
+ Variadic::String(cat_1)));
EXPECT_TRUE(HasArg(1u, storage_->InternString("legacy_event.name"),
- Variadic::String(2u)));
+ Variadic::String(ev_1)));
EXPECT_TRUE(HasArg(1u, storage_->InternString("legacy_event.phase"),
- Variadic::String(4u)));
+ Variadic::String(question)));
EXPECT_TRUE(HasArg(1u, storage_->InternString("legacy_event.duration_ns"),
Variadic::Integer(23000)));
EXPECT_TRUE(HasArg(1u,
@@ -2169,7 +2080,7 @@
EXPECT_TRUE(HasArg(1u, storage_->InternString("legacy_event.global_id"),
Variadic::UnsignedInteger(99u)));
EXPECT_TRUE(HasArg(1u, storage_->InternString("legacy_event.id_scope"),
- Variadic::String(3u)));
+ Variadic::String(scope_1)));
EXPECT_TRUE(HasArg(1u, storage_->InternString("legacy_event.bind_id"),
Variadic::UnsignedInteger(98u)));
EXPECT_TRUE(HasArg(1u,
@@ -2177,7 +2088,7 @@
Variadic::Boolean(true)));
EXPECT_TRUE(HasArg(1u, storage_->InternString("legacy_event.flow_direction"),
Variadic::String(storage_->InternString("inout"))));
- EXPECT_TRUE(HasArg(1u, 5u, Variadic::UnsignedInteger(10u)));
+ EXPECT_TRUE(HasArg(1u, debug_an_1, Variadic::UnsignedInteger(10u)));
}
TEST_F(ProtoTraceParserTest, TrackEventLegacyTimestampsWithClockSnapshot) {
@@ -2210,11 +2121,11 @@
Tokenize();
- EXPECT_CALL(*process_, UpdateThread(16, 15)).WillOnce(Return(1));
+ EXPECT_CALL(*process_, UpdateThread(16, 15)).WillRepeatedly(Return(1));
- TraceStorage::Thread thread(16);
- thread.upid = 1u;
- EXPECT_CALL(*storage_, GetThread(1)).WillOnce(testing::ReturnRef(thread));
+ tables::ThreadTable::Row row(16);
+ row.upid = 1u;
+ storage_->mutable_thread_table()->Insert(row);
constexpr TrackId track{0u};
InSequence in_sequence; // Below slices should be sorted by timestamp.
@@ -2245,8 +2156,8 @@
context_.sorter->ExtractEventsForced();
// Metadata should have created a raw event.
- const auto& raw_events = storage_->raw_events();
- EXPECT_EQ(raw_events.raw_event_count(), 1u);
+ const auto& raw_table = storage_->raw_table();
+ EXPECT_EQ(raw_table.row_count(), 1u);
}
TEST_F(ProtoTraceParserTest, ParseChromeMetadataEventIntoRawTable) {
@@ -2275,14 +2186,14 @@
Tokenize();
context_.sorter->ExtractEventsForced();
- // Verify raw_events and args contents.
- const auto& raw_events = storage_->raw_events();
- EXPECT_EQ(raw_events.raw_event_count(), 1u);
- EXPECT_EQ(raw_events.name_ids()[0],
+ // Verify raw_table and args contents.
+ const auto& raw_table = storage_->raw_table();
+ EXPECT_EQ(raw_table.row_count(), 1u);
+ EXPECT_EQ(raw_table.name()[0],
storage_->InternString("chrome_event.metadata"));
- EXPECT_EQ(raw_events.arg_set_ids()[0], 1u);
+ EXPECT_EQ(raw_table.arg_set_id()[0], 1u);
- EXPECT_EQ(storage_->args().args_count(), 2u);
+ EXPECT_EQ(storage_->arg_table().row_count(), 2u);
EXPECT_TRUE(HasArg(1u, storage_->InternString(kStringName),
Variadic::String(storage_->InternString(kStringValue))));
EXPECT_TRUE(HasArg(1u, storage_->InternString(kIntName),
@@ -2309,14 +2220,14 @@
context_.sorter->ExtractEventsForced();
- // Verify raw_events and args contents.
- const auto& raw_events = storage_->raw_events();
- EXPECT_EQ(raw_events.raw_event_count(), 1u);
- EXPECT_EQ(raw_events.name_ids()[0],
+ // Verify raw_table and args contents.
+ const auto& raw_table = storage_->raw_table();
+ EXPECT_EQ(raw_table.row_count(), 1u);
+ EXPECT_EQ(raw_table.name()[0],
storage_->InternString("chrome_event.legacy_system_trace"));
- EXPECT_EQ(raw_events.arg_set_ids()[0], 1u);
+ EXPECT_EQ(raw_table.arg_set_id()[0], 1u);
- EXPECT_EQ(storage_->args().args_count(), 1u);
+ EXPECT_EQ(storage_->arg_table().row_count(), 1u);
EXPECT_TRUE(HasArg(1u, storage_->InternString("data"),
Variadic::String(storage_->InternString(kFullData))));
}
@@ -2340,14 +2251,14 @@
context_.sorter->ExtractEventsForced();
- // Verify raw_events and args contents.
- const auto& raw_events = storage_->raw_events();
- EXPECT_EQ(raw_events.raw_event_count(), 1u);
- EXPECT_EQ(raw_events.name_ids()[0],
+ // Verify raw_table and args contents.
+ const auto& raw_table = storage_->raw_table();
+ EXPECT_EQ(raw_table.row_count(), 1u);
+ EXPECT_EQ(raw_table.name()[0],
storage_->InternString("chrome_event.legacy_user_trace"));
- EXPECT_EQ(raw_events.arg_set_ids()[0], 1u);
+ EXPECT_EQ(raw_table.arg_set_id()[0], 1u);
- EXPECT_EQ(storage_->args().args_count(), 1u);
+ EXPECT_EQ(storage_->arg_table().row_count(), 1u);
EXPECT_TRUE(
HasArg(1u, storage_->InternString("data"),
Variadic::String(storage_->InternString(kUserTraceEvent))));
@@ -2368,12 +2279,9 @@
Tokenize();
- EXPECT_CALL(*storage_, InternString(base::StringView(kName)))
- .WillOnce(Return(1));
- EXPECT_CALL(*storage_, InternString(base::StringView(kTag1)))
- .WillOnce(Return(2));
- EXPECT_CALL(*storage_, InternString(base::StringView(kTag2)))
- .WillOnce(Return(3));
+ StringId name_1 = storage_->InternString(kName);
+ StringId tag_1 = storage_->InternString(kTag1);
+ StringId tag_2 = storage_->InternString(kTag2);
StringId benchmark_id = *storage_->string_pool().GetId(
metadata::kNames[metadata::benchmark_name]);
@@ -2391,9 +2299,9 @@
meta_entries.emplace_back(std::make_pair(meta_keys[i], meta_values[i]));
}
EXPECT_THAT(meta_entries,
- UnorderedElementsAreArray({std::make_pair(benchmark_id, 1),
- std::make_pair(tags_id, 2),
- std::make_pair(tags_id, 3)}));
+ UnorderedElementsAreArray({std::make_pair(benchmark_id, name_1),
+ std::make_pair(tags_id, tag_1),
+ std::make_pair(tags_id, tag_2)}));
}
TEST_F(ProtoTraceParserTest, AndroidPackagesList) {
@@ -2430,7 +2338,7 @@
// The relevant arg sets have the info about the packages. To simplify test
// structure, make an assumption that metadata storage is filled in in the
// FIFO order of seen packages.
- const auto& args = context_.storage->args();
+ const auto& args = context_.storage->arg_table();
const auto& metadata = context_.storage->metadata_table();
Table package_list = metadata.Filter(
@@ -2443,10 +2351,10 @@
// helper to look up arg values
auto find_arg = [&args, this](ArgSetId set_id, const char* arg_name) {
- for (size_t i = 0; i < args.set_ids().size(); i++) {
- if (args.set_ids()[i] == set_id &&
- args.keys()[i] == storage_->InternString(arg_name))
- return args.arg_values()[i];
+ for (uint32_t i = 0; i < args.row_count(); i++) {
+ if (args.arg_set_id()[i] == set_id &&
+ args.key()[i] == storage_->InternString(arg_name))
+ return storage_->GetArgValue(i);
}
PERFETTO_FATAL("Didn't find expected argument");
};
@@ -2483,6 +2391,11 @@
auto mapping = interned_data->add_mappings();
mapping->set_iid(1);
+ mapping->set_build_id(1);
+
+ auto build_id = interned_data->add_build_ids();
+ build_id->set_iid(1);
+ build_id->set_str("3BBCFBD372448A727265C3E7C4D954F91");
auto frame = interned_data->add_frames();
frame->set_iid(1);
@@ -2525,7 +2438,6 @@
}
EXPECT_CALL(*process_, UpdateThread(16, 15))
- .Times(2)
.WillRepeatedly(Return(1));
Tokenize();
@@ -2534,17 +2446,24 @@
const auto& samples = storage_->cpu_profile_stack_sample_table();
EXPECT_EQ(samples.row_count(), 3u);
- EXPECT_EQ(samples.ts()[0], 1010);
+ EXPECT_EQ(samples.ts()[0], 11000);
EXPECT_EQ(samples.callsite_id()[0], 0);
EXPECT_EQ(samples.utid()[0], 1u);
- EXPECT_EQ(samples.ts()[1], 1025);
+ EXPECT_EQ(samples.ts()[1], 26000);
EXPECT_EQ(samples.callsite_id()[1], 1);
EXPECT_EQ(samples.utid()[1], 1u);
- EXPECT_EQ(samples.ts()[2], 1067);
+ EXPECT_EQ(samples.ts()[2], 68000);
EXPECT_EQ(samples.callsite_id()[2], 0);
EXPECT_EQ(samples.utid()[2], 1u);
+
+ // Breakpad build_ids should not be modified/mangled.
+ ASSERT_STREQ(
+ context_.storage
+ ->GetString(storage_->stack_profile_mapping_table().build_id()[0])
+ .c_str(),
+ "3BBCFBD372448A727265C3E7C4D954F91");
}
} // namespace
diff --git a/src/trace_processor/importers/proto/proto_trace_tokenizer.cc b/src/trace_processor/importers/proto/proto_trace_tokenizer.cc
index b964a2c..ca746b7 100644
--- a/src/trace_processor/importers/proto/proto_trace_tokenizer.cc
+++ b/src/trace_processor/importers/proto/proto_trace_tokenizer.cc
@@ -18,8 +18,7 @@
#include <string>
-#include <zlib.h>
-
+#include "perfetto/base/build_config.h"
#include "perfetto/base/logging.h"
#include "perfetto/ext/base/optional.h"
#include "perfetto/ext/base/string_view.h"
@@ -42,6 +41,10 @@
#include "protos/perfetto/trace/trace.pbzero.h"
#include "protos/perfetto/trace/trace_packet.pbzero.h"
+#if PERFETTO_BUILDFLAG(PERFETTO_ZLIB)
+#include <zlib.h>
+#endif
+
namespace perfetto {
namespace trace_processor {
@@ -53,6 +56,7 @@
constexpr uint8_t kTracePacketTag =
MakeTagLengthDelimited(protos::pbzero::Trace::kPacketFieldNumber);
+#if PERFETTO_BUILDFLAG(PERFETTO_ZLIB)
TraceBlobView Decompress(TraceBlobView input) {
uint8_t out[4096];
std::string s;
@@ -81,6 +85,7 @@
memcpy(output.get(), s.data(), s.size());
return TraceBlobView(std::move(output), 0, s.size());
}
+#endif // PERFETTO_BUILDFLAG(PERFETTO_ZLIB)
} // namespace
@@ -309,6 +314,7 @@
}
if (decoder.has_compressed_packets()) {
+#if PERFETTO_BUILDFLAG(PERFETTO_ZLIB)
protozero::ConstBytes field = decoder.compressed_packets();
const size_t field_off = packet.offset_of(field.data);
TraceBlobView compressed_packets = packet.slice(field_off, field.size);
@@ -334,6 +340,9 @@
}
return util::OkStatus();
+#else
+ return util::Status("Cannot decode compressed packets. Zlib not enabled");
+#endif
}
// If we're not forcing a full sort and this is a write_into_file trace, then
diff --git a/src/trace_processor/importers/proto/system_probes_parser.cc b/src/trace_processor/importers/proto/system_probes_parser.cc
index dd143dd..5ca7ca1 100644
--- a/src/trace_processor/importers/proto/system_probes_parser.cc
+++ b/src/trace_processor/importers/proto/system_probes_parser.cc
@@ -230,8 +230,8 @@
context_->process_tracker->UpdateThread(tid, tgid);
if (thd.has_name()) {
- StringId threadNameId = context_->storage->InternString(thd.name());
- context_->process_tracker->UpdateThreadName(tid, threadNameId);
+ StringId thread_name_id = context_->storage->InternString(thd.name());
+ context_->process_tracker->UpdateThreadName(tid, thread_name_id);
}
}
}
@@ -254,7 +254,7 @@
continue;
}
bool is_counter_field = fld.id() < proc_stats_process_names_.size() &&
- proc_stats_process_names_[fld.id()] != 0;
+ !proc_stats_process_names_[fld.id()].is_null();
if (is_counter_field) {
// Memory counters are in KB, keep values in bytes in the trace
// processor.
diff --git a/src/trace_processor/importers/proto/track_event.descriptor.h b/src/trace_processor/importers/proto/track_event.descriptor.h
index 00c28d8..e0237e6 100644
--- a/src/trace_processor/importers/proto/track_event.descriptor.h
+++ b/src/trace_processor/importers/proto/track_event.descriptor.h
@@ -25,17 +25,17 @@
// This file was autogenerated by tools/gen_binary_descriptors. Do not edit.
// SHA1(tools/gen_binary_descriptors)
-// f242f1ac484bbe7ba4c45e77b56ab588f8015196
+// d6628b15181dba5287e35b56b966b39ea93d42b1
// SHA1(protos/perfetto/trace/track_event/track_event.proto)
-// 9b54f5487bfe8924c589c2c2f8cfee899f019966
+// 1cd2627d7a57ddcf4e61b967cd255011bf3a09d5
// This is the proto TrackEvent encoded as a ProtoFileDescriptor to allow
// for reflection without libprotobuf full/non-lite protos.
namespace perfetto {
-constexpr std::array<uint8_t, 16147> kTrackEventDescriptor{
- {0x0a, 0x9a, 0x08, 0x0a, 0x38, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2f,
+constexpr std::array<uint8_t, 16107> kTrackEventDescriptor{
+ {0x0a, 0x96, 0x08, 0x0a, 0x38, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2f,
0x70, 0x65, 0x72, 0x66, 0x65, 0x74, 0x74, 0x6f, 0x2f, 0x74, 0x72, 0x61,
0x63, 0x65, 0x2f, 0x74, 0x72, 0x61, 0x63, 0x6b, 0x5f, 0x65, 0x76, 0x65,
0x6e, 0x74, 0x2f, 0x64, 0x65, 0x62, 0x75, 0x67, 0x5f, 0x61, 0x6e, 0x6e,
@@ -122,37 +122,36 @@
0x61, 0x6d, 0x65, 0x12, 0x10, 0x0a, 0x03, 0x69, 0x69, 0x64, 0x18, 0x01,
0x20, 0x01, 0x28, 0x04, 0x52, 0x03, 0x69, 0x69, 0x64, 0x12, 0x12, 0x0a,
0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52,
- 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x42, 0x02, 0x48, 0x03, 0x0a, 0xdb, 0x01,
- 0x0a, 0x33, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2f, 0x70, 0x65, 0x72,
- 0x66, 0x65, 0x74, 0x74, 0x6f, 0x2f, 0x74, 0x72, 0x61, 0x63, 0x65, 0x2f,
- 0x74, 0x72, 0x61, 0x63, 0x6b, 0x5f, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x2f,
- 0x6c, 0x6f, 0x67, 0x5f, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x2e,
- 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x0f, 0x70, 0x65, 0x72, 0x66, 0x65,
- 0x74, 0x74, 0x6f, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x22, 0x57,
- 0x0a, 0x0a, 0x4c, 0x6f, 0x67, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65,
- 0x12, 0x2e, 0x0a, 0x13, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x5f, 0x6c,
- 0x6f, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x69, 0x69, 0x64, 0x18,
- 0x01, 0x20, 0x01, 0x28, 0x04, 0x52, 0x11, 0x73, 0x6f, 0x75, 0x72, 0x63,
- 0x65, 0x4c, 0x6f, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x49, 0x69, 0x64,
- 0x12, 0x19, 0x0a, 0x08, 0x62, 0x6f, 0x64, 0x79, 0x5f, 0x69, 0x69, 0x64,
- 0x18, 0x02, 0x20, 0x01, 0x28, 0x04, 0x52, 0x07, 0x62, 0x6f, 0x64, 0x79,
- 0x49, 0x69, 0x64, 0x22, 0x36, 0x0a, 0x0e, 0x4c, 0x6f, 0x67, 0x4d, 0x65,
- 0x73, 0x73, 0x61, 0x67, 0x65, 0x42, 0x6f, 0x64, 0x79, 0x12, 0x10, 0x0a,
- 0x03, 0x69, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x04, 0x52, 0x03,
- 0x69, 0x69, 0x64, 0x12, 0x12, 0x0a, 0x04, 0x62, 0x6f, 0x64, 0x79, 0x18,
- 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x62, 0x6f, 0x64, 0x79, 0x42,
- 0x02, 0x48, 0x03, 0x0a, 0x86, 0x01, 0x0a, 0x36, 0x70, 0x72, 0x6f, 0x74,
- 0x6f, 0x73, 0x2f, 0x70, 0x65, 0x72, 0x66, 0x65, 0x74, 0x74, 0x6f, 0x2f,
- 0x74, 0x72, 0x61, 0x63, 0x65, 0x2f, 0x74, 0x72, 0x61, 0x63, 0x6b, 0x5f,
- 0x65, 0x76, 0x65, 0x6e, 0x74, 0x2f, 0x74, 0x61, 0x73, 0x6b, 0x5f, 0x65,
- 0x78, 0x65, 0x63, 0x75, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x70, 0x72, 0x6f,
- 0x74, 0x6f, 0x12, 0x0f, 0x70, 0x65, 0x72, 0x66, 0x65, 0x74, 0x74, 0x6f,
- 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x22, 0x37, 0x0a, 0x0d, 0x54,
- 0x61, 0x73, 0x6b, 0x45, 0x78, 0x65, 0x63, 0x75, 0x74, 0x69, 0x6f, 0x6e,
- 0x12, 0x26, 0x0a, 0x0f, 0x70, 0x6f, 0x73, 0x74, 0x65, 0x64, 0x5f, 0x66,
- 0x72, 0x6f, 0x6d, 0x5f, 0x69, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28,
- 0x04, 0x52, 0x0d, 0x70, 0x6f, 0x73, 0x74, 0x65, 0x64, 0x46, 0x72, 0x6f,
- 0x6d, 0x49, 0x69, 0x64, 0x42, 0x02, 0x48, 0x03, 0x0a, 0xd6, 0x01, 0x0a,
+ 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x0a, 0xd7, 0x01, 0x0a, 0x33, 0x70, 0x72,
+ 0x6f, 0x74, 0x6f, 0x73, 0x2f, 0x70, 0x65, 0x72, 0x66, 0x65, 0x74, 0x74,
+ 0x6f, 0x2f, 0x74, 0x72, 0x61, 0x63, 0x65, 0x2f, 0x74, 0x72, 0x61, 0x63,
+ 0x6b, 0x5f, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x2f, 0x6c, 0x6f, 0x67, 0x5f,
+ 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74,
+ 0x6f, 0x12, 0x0f, 0x70, 0x65, 0x72, 0x66, 0x65, 0x74, 0x74, 0x6f, 0x2e,
+ 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x22, 0x57, 0x0a, 0x0a, 0x4c, 0x6f,
+ 0x67, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x12, 0x2e, 0x0a, 0x13,
+ 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x5f, 0x6c, 0x6f, 0x63, 0x61, 0x74,
+ 0x69, 0x6f, 0x6e, 0x5f, 0x69, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28,
+ 0x04, 0x52, 0x11, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x4c, 0x6f, 0x63,
+ 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x49, 0x69, 0x64, 0x12, 0x19, 0x0a, 0x08,
+ 0x62, 0x6f, 0x64, 0x79, 0x5f, 0x69, 0x69, 0x64, 0x18, 0x02, 0x20, 0x01,
+ 0x28, 0x04, 0x52, 0x07, 0x62, 0x6f, 0x64, 0x79, 0x49, 0x69, 0x64, 0x22,
+ 0x36, 0x0a, 0x0e, 0x4c, 0x6f, 0x67, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67,
+ 0x65, 0x42, 0x6f, 0x64, 0x79, 0x12, 0x10, 0x0a, 0x03, 0x69, 0x69, 0x64,
+ 0x18, 0x01, 0x20, 0x01, 0x28, 0x04, 0x52, 0x03, 0x69, 0x69, 0x64, 0x12,
+ 0x12, 0x0a, 0x04, 0x62, 0x6f, 0x64, 0x79, 0x18, 0x02, 0x20, 0x01, 0x28,
+ 0x09, 0x52, 0x04, 0x62, 0x6f, 0x64, 0x79, 0x0a, 0x82, 0x01, 0x0a, 0x36,
+ 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2f, 0x70, 0x65, 0x72, 0x66, 0x65,
+ 0x74, 0x74, 0x6f, 0x2f, 0x74, 0x72, 0x61, 0x63, 0x65, 0x2f, 0x74, 0x72,
+ 0x61, 0x63, 0x6b, 0x5f, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x2f, 0x74, 0x61,
+ 0x73, 0x6b, 0x5f, 0x65, 0x78, 0x65, 0x63, 0x75, 0x74, 0x69, 0x6f, 0x6e,
+ 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x0f, 0x70, 0x65, 0x72, 0x66,
+ 0x65, 0x74, 0x74, 0x6f, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x22,
+ 0x37, 0x0a, 0x0d, 0x54, 0x61, 0x73, 0x6b, 0x45, 0x78, 0x65, 0x63, 0x75,
+ 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x26, 0x0a, 0x0f, 0x70, 0x6f, 0x73, 0x74,
+ 0x65, 0x64, 0x5f, 0x66, 0x72, 0x6f, 0x6d, 0x5f, 0x69, 0x69, 0x64, 0x18,
+ 0x01, 0x20, 0x01, 0x28, 0x04, 0x52, 0x0d, 0x70, 0x6f, 0x73, 0x74, 0x65,
+ 0x64, 0x46, 0x72, 0x6f, 0x6d, 0x49, 0x69, 0x64, 0x0a, 0xd2, 0x01, 0x0a,
0x37, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2f, 0x70, 0x65, 0x72, 0x66,
0x65, 0x74, 0x74, 0x6f, 0x2f, 0x74, 0x72, 0x61, 0x63, 0x65, 0x2f, 0x74,
0x72, 0x61, 0x63, 0x6b, 0x5f, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x2f, 0x73,
@@ -170,849 +169,848 @@
0x74, 0x69, 0x6f, 0x6e, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x1f, 0x0a, 0x0b,
0x6c, 0x69, 0x6e, 0x65, 0x5f, 0x6e, 0x75, 0x6d, 0x62, 0x65, 0x72, 0x18,
0x04, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x0a, 0x6c, 0x69, 0x6e, 0x65, 0x4e,
- 0x75, 0x6d, 0x62, 0x65, 0x72, 0x42, 0x02, 0x48, 0x03, 0x0a, 0xb9, 0x4d,
- 0x0a, 0x49, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2f, 0x70, 0x65, 0x72,
- 0x66, 0x65, 0x74, 0x74, 0x6f, 0x2f, 0x74, 0x72, 0x61, 0x63, 0x65, 0x2f,
- 0x74, 0x72, 0x61, 0x63, 0x6b, 0x5f, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x2f,
- 0x63, 0x68, 0x72, 0x6f, 0x6d, 0x65, 0x5f, 0x63, 0x6f, 0x6d, 0x70, 0x6f,
- 0x73, 0x69, 0x74, 0x6f, 0x72, 0x5f, 0x73, 0x63, 0x68, 0x65, 0x64, 0x75,
- 0x6c, 0x65, 0x72, 0x5f, 0x73, 0x74, 0x61, 0x74, 0x65, 0x2e, 0x70, 0x72,
- 0x6f, 0x74, 0x6f, 0x12, 0x0f, 0x70, 0x65, 0x72, 0x66, 0x65, 0x74, 0x74,
- 0x6f, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x1a, 0x37, 0x70, 0x72,
+ 0x75, 0x6d, 0x62, 0x65, 0x72, 0x0a, 0xb5, 0x4d, 0x0a, 0x49, 0x70, 0x72,
0x6f, 0x74, 0x6f, 0x73, 0x2f, 0x70, 0x65, 0x72, 0x66, 0x65, 0x74, 0x74,
0x6f, 0x2f, 0x74, 0x72, 0x61, 0x63, 0x65, 0x2f, 0x74, 0x72, 0x61, 0x63,
- 0x6b, 0x5f, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x2f, 0x73, 0x6f, 0x75, 0x72,
- 0x63, 0x65, 0x5f, 0x6c, 0x6f, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2e,
- 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x22, 0xe6, 0x0b, 0x0a, 0x1e, 0x43, 0x68,
- 0x72, 0x6f, 0x6d, 0x65, 0x43, 0x6f, 0x6d, 0x70, 0x6f, 0x73, 0x69, 0x74,
- 0x6f, 0x72, 0x53, 0x63, 0x68, 0x65, 0x64, 0x75, 0x6c, 0x65, 0x72, 0x53,
- 0x74, 0x61, 0x74, 0x65, 0x12, 0x52, 0x0a, 0x0d, 0x73, 0x74, 0x61, 0x74,
- 0x65, 0x5f, 0x6d, 0x61, 0x63, 0x68, 0x69, 0x6e, 0x65, 0x18, 0x01, 0x20,
- 0x01, 0x28, 0x0b, 0x32, 0x2d, 0x2e, 0x70, 0x65, 0x72, 0x66, 0x65, 0x74,
+ 0x6b, 0x5f, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x2f, 0x63, 0x68, 0x72, 0x6f,
+ 0x6d, 0x65, 0x5f, 0x63, 0x6f, 0x6d, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x6f,
+ 0x72, 0x5f, 0x73, 0x63, 0x68, 0x65, 0x64, 0x75, 0x6c, 0x65, 0x72, 0x5f,
+ 0x73, 0x74, 0x61, 0x74, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12,
+ 0x0f, 0x70, 0x65, 0x72, 0x66, 0x65, 0x74, 0x74, 0x6f, 0x2e, 0x70, 0x72,
+ 0x6f, 0x74, 0x6f, 0x73, 0x1a, 0x37, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73,
+ 0x2f, 0x70, 0x65, 0x72, 0x66, 0x65, 0x74, 0x74, 0x6f, 0x2f, 0x74, 0x72,
+ 0x61, 0x63, 0x65, 0x2f, 0x74, 0x72, 0x61, 0x63, 0x6b, 0x5f, 0x65, 0x76,
+ 0x65, 0x6e, 0x74, 0x2f, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x5f, 0x6c,
+ 0x6f, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x70, 0x72, 0x6f, 0x74,
+ 0x6f, 0x22, 0xe6, 0x0b, 0x0a, 0x1e, 0x43, 0x68, 0x72, 0x6f, 0x6d, 0x65,
+ 0x43, 0x6f, 0x6d, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x6f, 0x72, 0x53, 0x63,
+ 0x68, 0x65, 0x64, 0x75, 0x6c, 0x65, 0x72, 0x53, 0x74, 0x61, 0x74, 0x65,
+ 0x12, 0x52, 0x0a, 0x0d, 0x73, 0x74, 0x61, 0x74, 0x65, 0x5f, 0x6d, 0x61,
+ 0x63, 0x68, 0x69, 0x6e, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32,
+ 0x2d, 0x2e, 0x70, 0x65, 0x72, 0x66, 0x65, 0x74, 0x74, 0x6f, 0x2e, 0x70,
+ 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2e, 0x43, 0x68, 0x72, 0x6f, 0x6d, 0x65,
+ 0x43, 0x6f, 0x6d, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x6f, 0x72, 0x53, 0x74,
+ 0x61, 0x74, 0x65, 0x4d, 0x61, 0x63, 0x68, 0x69, 0x6e, 0x65, 0x52, 0x0c,
+ 0x73, 0x74, 0x61, 0x74, 0x65, 0x4d, 0x61, 0x63, 0x68, 0x69, 0x6e, 0x65,
+ 0x12, 0x3f, 0x0a, 0x1c, 0x6f, 0x62, 0x73, 0x65, 0x72, 0x76, 0x69, 0x6e,
+ 0x67, 0x5f, 0x62, 0x65, 0x67, 0x69, 0x6e, 0x5f, 0x66, 0x72, 0x61, 0x6d,
+ 0x65, 0x5f, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x18, 0x02, 0x20, 0x01,
+ 0x28, 0x08, 0x52, 0x19, 0x6f, 0x62, 0x73, 0x65, 0x72, 0x76, 0x69, 0x6e,
+ 0x67, 0x42, 0x65, 0x67, 0x69, 0x6e, 0x46, 0x72, 0x61, 0x6d, 0x65, 0x53,
+ 0x6f, 0x75, 0x72, 0x63, 0x65, 0x12, 0x42, 0x0a, 0x1e, 0x62, 0x65, 0x67,
+ 0x69, 0x6e, 0x5f, 0x69, 0x6d, 0x70, 0x6c, 0x5f, 0x66, 0x72, 0x61, 0x6d,
+ 0x65, 0x5f, 0x64, 0x65, 0x61, 0x64, 0x6c, 0x69, 0x6e, 0x65, 0x5f, 0x74,
+ 0x61, 0x73, 0x6b, 0x18, 0x03, 0x20, 0x01, 0x28, 0x08, 0x52, 0x1a, 0x62,
+ 0x65, 0x67, 0x69, 0x6e, 0x49, 0x6d, 0x70, 0x6c, 0x46, 0x72, 0x61, 0x6d,
+ 0x65, 0x44, 0x65, 0x61, 0x64, 0x6c, 0x69, 0x6e, 0x65, 0x54, 0x61, 0x73,
+ 0x6b, 0x12, 0x37, 0x0a, 0x18, 0x70, 0x65, 0x6e, 0x64, 0x69, 0x6e, 0x67,
+ 0x5f, 0x62, 0x65, 0x67, 0x69, 0x6e, 0x5f, 0x66, 0x72, 0x61, 0x6d, 0x65,
+ 0x5f, 0x74, 0x61, 0x73, 0x6b, 0x18, 0x04, 0x20, 0x01, 0x28, 0x08, 0x52,
+ 0x15, 0x70, 0x65, 0x6e, 0x64, 0x69, 0x6e, 0x67, 0x42, 0x65, 0x67, 0x69,
+ 0x6e, 0x46, 0x72, 0x61, 0x6d, 0x65, 0x54, 0x61, 0x73, 0x6b, 0x12, 0x5b,
+ 0x0a, 0x2b, 0x73, 0x6b, 0x69, 0x70, 0x70, 0x65, 0x64, 0x5f, 0x6c, 0x61,
+ 0x73, 0x74, 0x5f, 0x66, 0x72, 0x61, 0x6d, 0x65, 0x5f, 0x6d, 0x69, 0x73,
+ 0x73, 0x65, 0x64, 0x5f, 0x65, 0x78, 0x63, 0x65, 0x65, 0x64, 0x65, 0x64,
+ 0x5f, 0x64, 0x65, 0x61, 0x64, 0x6c, 0x69, 0x6e, 0x65, 0x18, 0x05, 0x20,
+ 0x01, 0x28, 0x08, 0x52, 0x26, 0x73, 0x6b, 0x69, 0x70, 0x70, 0x65, 0x64,
+ 0x4c, 0x61, 0x73, 0x74, 0x46, 0x72, 0x61, 0x6d, 0x65, 0x4d, 0x69, 0x73,
+ 0x73, 0x65, 0x64, 0x45, 0x78, 0x63, 0x65, 0x65, 0x64, 0x65, 0x64, 0x44,
+ 0x65, 0x61, 0x64, 0x6c, 0x69, 0x6e, 0x65, 0x12, 0x4d, 0x0a, 0x24, 0x73,
+ 0x6b, 0x69, 0x70, 0x70, 0x65, 0x64, 0x5f, 0x6c, 0x61, 0x73, 0x74, 0x5f,
+ 0x66, 0x72, 0x61, 0x6d, 0x65, 0x5f, 0x74, 0x6f, 0x5f, 0x72, 0x65, 0x64,
+ 0x75, 0x63, 0x65, 0x5f, 0x6c, 0x61, 0x74, 0x65, 0x6e, 0x63, 0x79, 0x18,
+ 0x06, 0x20, 0x01, 0x28, 0x08, 0x52, 0x1f, 0x73, 0x6b, 0x69, 0x70, 0x70,
+ 0x65, 0x64, 0x4c, 0x61, 0x73, 0x74, 0x46, 0x72, 0x61, 0x6d, 0x65, 0x54,
+ 0x6f, 0x52, 0x65, 0x64, 0x75, 0x63, 0x65, 0x4c, 0x61, 0x74, 0x65, 0x6e,
+ 0x63, 0x79, 0x12, 0x55, 0x0a, 0x0d, 0x69, 0x6e, 0x73, 0x69, 0x64, 0x65,
+ 0x5f, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x07, 0x20, 0x01, 0x28,
+ 0x0e, 0x32, 0x30, 0x2e, 0x70, 0x65, 0x72, 0x66, 0x65, 0x74, 0x74, 0x6f,
+ 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2e, 0x43, 0x68, 0x72, 0x6f,
+ 0x6d, 0x65, 0x43, 0x6f, 0x6d, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x6f, 0x72,
+ 0x53, 0x63, 0x68, 0x65, 0x64, 0x75, 0x6c, 0x65, 0x72, 0x41, 0x63, 0x74,
+ 0x69, 0x6f, 0x6e, 0x52, 0x0c, 0x69, 0x6e, 0x73, 0x69, 0x64, 0x65, 0x41,
+ 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x6f, 0x0a, 0x0d, 0x64, 0x65, 0x61,
+ 0x64, 0x6c, 0x69, 0x6e, 0x65, 0x5f, 0x6d, 0x6f, 0x64, 0x65, 0x18, 0x08,
+ 0x20, 0x01, 0x28, 0x0e, 0x32, 0x4a, 0x2e, 0x70, 0x65, 0x72, 0x66, 0x65,
+ 0x74, 0x74, 0x6f, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2e, 0x43,
+ 0x68, 0x72, 0x6f, 0x6d, 0x65, 0x43, 0x6f, 0x6d, 0x70, 0x6f, 0x73, 0x69,
+ 0x74, 0x6f, 0x72, 0x53, 0x63, 0x68, 0x65, 0x64, 0x75, 0x6c, 0x65, 0x72,
+ 0x53, 0x74, 0x61, 0x74, 0x65, 0x2e, 0x42, 0x65, 0x67, 0x69, 0x6e, 0x49,
+ 0x6d, 0x70, 0x6c, 0x46, 0x72, 0x61, 0x6d, 0x65, 0x44, 0x65, 0x61, 0x64,
+ 0x6c, 0x69, 0x6e, 0x65, 0x4d, 0x6f, 0x64, 0x65, 0x52, 0x0c, 0x64, 0x65,
+ 0x61, 0x64, 0x6c, 0x69, 0x6e, 0x65, 0x4d, 0x6f, 0x64, 0x65, 0x12, 0x1f,
+ 0x0a, 0x0b, 0x64, 0x65, 0x61, 0x64, 0x6c, 0x69, 0x6e, 0x65, 0x5f, 0x75,
+ 0x73, 0x18, 0x09, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0a, 0x64, 0x65, 0x61,
+ 0x64, 0x6c, 0x69, 0x6e, 0x65, 0x55, 0x73, 0x12, 0x37, 0x0a, 0x18, 0x64,
+ 0x65, 0x61, 0x64, 0x6c, 0x69, 0x6e, 0x65, 0x5f, 0x73, 0x63, 0x68, 0x65,
+ 0x64, 0x75, 0x6c, 0x65, 0x64, 0x5f, 0x61, 0x74, 0x5f, 0x75, 0x73, 0x18,
+ 0x0a, 0x20, 0x01, 0x28, 0x03, 0x52, 0x15, 0x64, 0x65, 0x61, 0x64, 0x6c,
+ 0x69, 0x6e, 0x65, 0x53, 0x63, 0x68, 0x65, 0x64, 0x75, 0x6c, 0x65, 0x64,
+ 0x41, 0x74, 0x55, 0x73, 0x12, 0x15, 0x0a, 0x06, 0x6e, 0x6f, 0x77, 0x5f,
+ 0x75, 0x73, 0x18, 0x0b, 0x20, 0x01, 0x28, 0x03, 0x52, 0x05, 0x6e, 0x6f,
+ 0x77, 0x55, 0x73, 0x12, 0x36, 0x0a, 0x18, 0x6e, 0x6f, 0x77, 0x5f, 0x74,
+ 0x6f, 0x5f, 0x64, 0x65, 0x61, 0x64, 0x6c, 0x69, 0x6e, 0x65, 0x5f, 0x64,
+ 0x65, 0x6c, 0x74, 0x61, 0x5f, 0x75, 0x73, 0x18, 0x0c, 0x20, 0x01, 0x28,
+ 0x03, 0x52, 0x14, 0x6e, 0x6f, 0x77, 0x54, 0x6f, 0x44, 0x65, 0x61, 0x64,
+ 0x6c, 0x69, 0x6e, 0x65, 0x44, 0x65, 0x6c, 0x74, 0x61, 0x55, 0x73, 0x12,
+ 0x4e, 0x0a, 0x25, 0x6e, 0x6f, 0x77, 0x5f, 0x74, 0x6f, 0x5f, 0x64, 0x65,
+ 0x61, 0x64, 0x6c, 0x69, 0x6e, 0x65, 0x5f, 0x73, 0x63, 0x68, 0x65, 0x64,
+ 0x75, 0x6c, 0x65, 0x64, 0x5f, 0x61, 0x74, 0x5f, 0x64, 0x65, 0x6c, 0x74,
+ 0x61, 0x5f, 0x75, 0x73, 0x18, 0x0d, 0x20, 0x01, 0x28, 0x03, 0x52, 0x1f,
+ 0x6e, 0x6f, 0x77, 0x54, 0x6f, 0x44, 0x65, 0x61, 0x64, 0x6c, 0x69, 0x6e,
+ 0x65, 0x53, 0x63, 0x68, 0x65, 0x64, 0x75, 0x6c, 0x65, 0x64, 0x41, 0x74,
+ 0x44, 0x65, 0x6c, 0x74, 0x61, 0x55, 0x73, 0x12, 0x56, 0x0a, 0x15, 0x62,
+ 0x65, 0x67, 0x69, 0x6e, 0x5f, 0x69, 0x6d, 0x70, 0x6c, 0x5f, 0x66, 0x72,
+ 0x61, 0x6d, 0x65, 0x5f, 0x61, 0x72, 0x67, 0x73, 0x18, 0x0e, 0x20, 0x01,
+ 0x28, 0x0b, 0x32, 0x23, 0x2e, 0x70, 0x65, 0x72, 0x66, 0x65, 0x74, 0x74,
+ 0x6f, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2e, 0x42, 0x65, 0x67,
+ 0x69, 0x6e, 0x49, 0x6d, 0x70, 0x6c, 0x46, 0x72, 0x61, 0x6d, 0x65, 0x41,
+ 0x72, 0x67, 0x73, 0x52, 0x12, 0x62, 0x65, 0x67, 0x69, 0x6e, 0x49, 0x6d,
+ 0x70, 0x6c, 0x46, 0x72, 0x61, 0x6d, 0x65, 0x41, 0x72, 0x67, 0x73, 0x12,
+ 0x65, 0x0a, 0x1a, 0x62, 0x65, 0x67, 0x69, 0x6e, 0x5f, 0x66, 0x72, 0x61,
+ 0x6d, 0x65, 0x5f, 0x6f, 0x62, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x5f,
+ 0x73, 0x74, 0x61, 0x74, 0x65, 0x18, 0x0f, 0x20, 0x01, 0x28, 0x0b, 0x32,
+ 0x28, 0x2e, 0x70, 0x65, 0x72, 0x66, 0x65, 0x74, 0x74, 0x6f, 0x2e, 0x70,
+ 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2e, 0x42, 0x65, 0x67, 0x69, 0x6e, 0x46,
+ 0x72, 0x61, 0x6d, 0x65, 0x4f, 0x62, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72,
+ 0x53, 0x74, 0x61, 0x74, 0x65, 0x52, 0x17, 0x62, 0x65, 0x67, 0x69, 0x6e,
+ 0x46, 0x72, 0x61, 0x6d, 0x65, 0x4f, 0x62, 0x73, 0x65, 0x72, 0x76, 0x65,
+ 0x72, 0x53, 0x74, 0x61, 0x74, 0x65, 0x12, 0x5f, 0x0a, 0x18, 0x62, 0x65,
+ 0x67, 0x69, 0x6e, 0x5f, 0x66, 0x72, 0x61, 0x6d, 0x65, 0x5f, 0x73, 0x6f,
+ 0x75, 0x72, 0x63, 0x65, 0x5f, 0x73, 0x74, 0x61, 0x74, 0x65, 0x18, 0x10,
+ 0x20, 0x01, 0x28, 0x0b, 0x32, 0x26, 0x2e, 0x70, 0x65, 0x72, 0x66, 0x65,
+ 0x74, 0x74, 0x6f, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2e, 0x42,
+ 0x65, 0x67, 0x69, 0x6e, 0x46, 0x72, 0x61, 0x6d, 0x65, 0x53, 0x6f, 0x75,
+ 0x72, 0x63, 0x65, 0x53, 0x74, 0x61, 0x74, 0x65, 0x52, 0x15, 0x62, 0x65,
+ 0x67, 0x69, 0x6e, 0x46, 0x72, 0x61, 0x6d, 0x65, 0x53, 0x6f, 0x75, 0x72,
+ 0x63, 0x65, 0x53, 0x74, 0x61, 0x74, 0x65, 0x12, 0x64, 0x0a, 0x19, 0x63,
+ 0x6f, 0x6d, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x6f, 0x72, 0x5f, 0x74, 0x69,
+ 0x6d, 0x69, 0x6e, 0x67, 0x5f, 0x68, 0x69, 0x73, 0x74, 0x6f, 0x72, 0x79,
+ 0x18, 0x11, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x28, 0x2e, 0x70, 0x65, 0x72,
+ 0x66, 0x65, 0x74, 0x74, 0x6f, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73,
+ 0x2e, 0x43, 0x6f, 0x6d, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x6f, 0x72, 0x54,
+ 0x69, 0x6d, 0x69, 0x6e, 0x67, 0x48, 0x69, 0x73, 0x74, 0x6f, 0x72, 0x79,
+ 0x52, 0x17, 0x63, 0x6f, 0x6d, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x6f, 0x72,
+ 0x54, 0x69, 0x6d, 0x69, 0x6e, 0x67, 0x48, 0x69, 0x73, 0x74, 0x6f, 0x72,
+ 0x79, 0x22, 0xbe, 0x01, 0x0a, 0x1a, 0x42, 0x65, 0x67, 0x69, 0x6e, 0x49,
+ 0x6d, 0x70, 0x6c, 0x46, 0x72, 0x61, 0x6d, 0x65, 0x44, 0x65, 0x61, 0x64,
+ 0x6c, 0x69, 0x6e, 0x65, 0x4d, 0x6f, 0x64, 0x65, 0x12, 0x1d, 0x0a, 0x19,
+ 0x44, 0x45, 0x41, 0x44, 0x4c, 0x49, 0x4e, 0x45, 0x5f, 0x4d, 0x4f, 0x44,
+ 0x45, 0x5f, 0x55, 0x4e, 0x53, 0x50, 0x45, 0x43, 0x49, 0x46, 0x49, 0x45,
+ 0x44, 0x10, 0x00, 0x12, 0x16, 0x0a, 0x12, 0x44, 0x45, 0x41, 0x44, 0x4c,
+ 0x49, 0x4e, 0x45, 0x5f, 0x4d, 0x4f, 0x44, 0x45, 0x5f, 0x4e, 0x4f, 0x4e,
+ 0x45, 0x10, 0x01, 0x12, 0x1b, 0x0a, 0x17, 0x44, 0x45, 0x41, 0x44, 0x4c,
+ 0x49, 0x4e, 0x45, 0x5f, 0x4d, 0x4f, 0x44, 0x45, 0x5f, 0x49, 0x4d, 0x4d,
+ 0x45, 0x44, 0x49, 0x41, 0x54, 0x45, 0x10, 0x02, 0x12, 0x19, 0x0a, 0x15,
+ 0x44, 0x45, 0x41, 0x44, 0x4c, 0x49, 0x4e, 0x45, 0x5f, 0x4d, 0x4f, 0x44,
+ 0x45, 0x5f, 0x52, 0x45, 0x47, 0x55, 0x4c, 0x41, 0x52, 0x10, 0x03, 0x12,
+ 0x16, 0x0a, 0x12, 0x44, 0x45, 0x41, 0x44, 0x4c, 0x49, 0x4e, 0x45, 0x5f,
+ 0x4d, 0x4f, 0x44, 0x45, 0x5f, 0x4c, 0x41, 0x54, 0x45, 0x10, 0x04, 0x12,
+ 0x19, 0x0a, 0x15, 0x44, 0x45, 0x41, 0x44, 0x4c, 0x49, 0x4e, 0x45, 0x5f,
+ 0x4d, 0x4f, 0x44, 0x45, 0x5f, 0x42, 0x4c, 0x4f, 0x43, 0x4b, 0x45, 0x44,
+ 0x10, 0x05, 0x22, 0x86, 0x28, 0x0a, 0x1c, 0x43, 0x68, 0x72, 0x6f, 0x6d,
+ 0x65, 0x43, 0x6f, 0x6d, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x6f, 0x72, 0x53,
+ 0x74, 0x61, 0x74, 0x65, 0x4d, 0x61, 0x63, 0x68, 0x69, 0x6e, 0x65, 0x12,
+ 0x59, 0x0a, 0x0b, 0x6d, 0x61, 0x6a, 0x6f, 0x72, 0x5f, 0x73, 0x74, 0x61,
+ 0x74, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x38, 0x2e, 0x70,
+ 0x65, 0x72, 0x66, 0x65, 0x74, 0x74, 0x6f, 0x2e, 0x70, 0x72, 0x6f, 0x74,
+ 0x6f, 0x73, 0x2e, 0x43, 0x68, 0x72, 0x6f, 0x6d, 0x65, 0x43, 0x6f, 0x6d,
+ 0x70, 0x6f, 0x73, 0x69, 0x74, 0x6f, 0x72, 0x53, 0x74, 0x61, 0x74, 0x65,
+ 0x4d, 0x61, 0x63, 0x68, 0x69, 0x6e, 0x65, 0x2e, 0x4d, 0x61, 0x6a, 0x6f,
+ 0x72, 0x53, 0x74, 0x61, 0x74, 0x65, 0x52, 0x0a, 0x6d, 0x61, 0x6a, 0x6f,
+ 0x72, 0x53, 0x74, 0x61, 0x74, 0x65, 0x12, 0x59, 0x0a, 0x0b, 0x6d, 0x69,
+ 0x6e, 0x6f, 0x72, 0x5f, 0x73, 0x74, 0x61, 0x74, 0x65, 0x18, 0x02, 0x20,
+ 0x01, 0x28, 0x0b, 0x32, 0x38, 0x2e, 0x70, 0x65, 0x72, 0x66, 0x65, 0x74,
0x74, 0x6f, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2e, 0x43, 0x68,
0x72, 0x6f, 0x6d, 0x65, 0x43, 0x6f, 0x6d, 0x70, 0x6f, 0x73, 0x69, 0x74,
0x6f, 0x72, 0x53, 0x74, 0x61, 0x74, 0x65, 0x4d, 0x61, 0x63, 0x68, 0x69,
- 0x6e, 0x65, 0x52, 0x0c, 0x73, 0x74, 0x61, 0x74, 0x65, 0x4d, 0x61, 0x63,
- 0x68, 0x69, 0x6e, 0x65, 0x12, 0x3f, 0x0a, 0x1c, 0x6f, 0x62, 0x73, 0x65,
- 0x72, 0x76, 0x69, 0x6e, 0x67, 0x5f, 0x62, 0x65, 0x67, 0x69, 0x6e, 0x5f,
- 0x66, 0x72, 0x61, 0x6d, 0x65, 0x5f, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65,
- 0x18, 0x02, 0x20, 0x01, 0x28, 0x08, 0x52, 0x19, 0x6f, 0x62, 0x73, 0x65,
- 0x72, 0x76, 0x69, 0x6e, 0x67, 0x42, 0x65, 0x67, 0x69, 0x6e, 0x46, 0x72,
- 0x61, 0x6d, 0x65, 0x53, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x12, 0x42, 0x0a,
- 0x1e, 0x62, 0x65, 0x67, 0x69, 0x6e, 0x5f, 0x69, 0x6d, 0x70, 0x6c, 0x5f,
- 0x66, 0x72, 0x61, 0x6d, 0x65, 0x5f, 0x64, 0x65, 0x61, 0x64, 0x6c, 0x69,
- 0x6e, 0x65, 0x5f, 0x74, 0x61, 0x73, 0x6b, 0x18, 0x03, 0x20, 0x01, 0x28,
- 0x08, 0x52, 0x1a, 0x62, 0x65, 0x67, 0x69, 0x6e, 0x49, 0x6d, 0x70, 0x6c,
- 0x46, 0x72, 0x61, 0x6d, 0x65, 0x44, 0x65, 0x61, 0x64, 0x6c, 0x69, 0x6e,
- 0x65, 0x54, 0x61, 0x73, 0x6b, 0x12, 0x37, 0x0a, 0x18, 0x70, 0x65, 0x6e,
- 0x64, 0x69, 0x6e, 0x67, 0x5f, 0x62, 0x65, 0x67, 0x69, 0x6e, 0x5f, 0x66,
- 0x72, 0x61, 0x6d, 0x65, 0x5f, 0x74, 0x61, 0x73, 0x6b, 0x18, 0x04, 0x20,
- 0x01, 0x28, 0x08, 0x52, 0x15, 0x70, 0x65, 0x6e, 0x64, 0x69, 0x6e, 0x67,
- 0x42, 0x65, 0x67, 0x69, 0x6e, 0x46, 0x72, 0x61, 0x6d, 0x65, 0x54, 0x61,
- 0x73, 0x6b, 0x12, 0x5b, 0x0a, 0x2b, 0x73, 0x6b, 0x69, 0x70, 0x70, 0x65,
- 0x64, 0x5f, 0x6c, 0x61, 0x73, 0x74, 0x5f, 0x66, 0x72, 0x61, 0x6d, 0x65,
- 0x5f, 0x6d, 0x69, 0x73, 0x73, 0x65, 0x64, 0x5f, 0x65, 0x78, 0x63, 0x65,
- 0x65, 0x64, 0x65, 0x64, 0x5f, 0x64, 0x65, 0x61, 0x64, 0x6c, 0x69, 0x6e,
- 0x65, 0x18, 0x05, 0x20, 0x01, 0x28, 0x08, 0x52, 0x26, 0x73, 0x6b, 0x69,
- 0x70, 0x70, 0x65, 0x64, 0x4c, 0x61, 0x73, 0x74, 0x46, 0x72, 0x61, 0x6d,
- 0x65, 0x4d, 0x69, 0x73, 0x73, 0x65, 0x64, 0x45, 0x78, 0x63, 0x65, 0x65,
- 0x64, 0x65, 0x64, 0x44, 0x65, 0x61, 0x64, 0x6c, 0x69, 0x6e, 0x65, 0x12,
- 0x4d, 0x0a, 0x24, 0x73, 0x6b, 0x69, 0x70, 0x70, 0x65, 0x64, 0x5f, 0x6c,
- 0x61, 0x73, 0x74, 0x5f, 0x66, 0x72, 0x61, 0x6d, 0x65, 0x5f, 0x74, 0x6f,
- 0x5f, 0x72, 0x65, 0x64, 0x75, 0x63, 0x65, 0x5f, 0x6c, 0x61, 0x74, 0x65,
- 0x6e, 0x63, 0x79, 0x18, 0x06, 0x20, 0x01, 0x28, 0x08, 0x52, 0x1f, 0x73,
- 0x6b, 0x69, 0x70, 0x70, 0x65, 0x64, 0x4c, 0x61, 0x73, 0x74, 0x46, 0x72,
- 0x61, 0x6d, 0x65, 0x54, 0x6f, 0x52, 0x65, 0x64, 0x75, 0x63, 0x65, 0x4c,
- 0x61, 0x74, 0x65, 0x6e, 0x63, 0x79, 0x12, 0x55, 0x0a, 0x0d, 0x69, 0x6e,
- 0x73, 0x69, 0x64, 0x65, 0x5f, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x18,
- 0x07, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x30, 0x2e, 0x70, 0x65, 0x72, 0x66,
- 0x65, 0x74, 0x74, 0x6f, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2e,
- 0x43, 0x68, 0x72, 0x6f, 0x6d, 0x65, 0x43, 0x6f, 0x6d, 0x70, 0x6f, 0x73,
- 0x69, 0x74, 0x6f, 0x72, 0x53, 0x63, 0x68, 0x65, 0x64, 0x75, 0x6c, 0x65,
- 0x72, 0x41, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x0c, 0x69, 0x6e, 0x73,
- 0x69, 0x64, 0x65, 0x41, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x6f, 0x0a,
- 0x0d, 0x64, 0x65, 0x61, 0x64, 0x6c, 0x69, 0x6e, 0x65, 0x5f, 0x6d, 0x6f,
- 0x64, 0x65, 0x18, 0x08, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x4a, 0x2e, 0x70,
- 0x65, 0x72, 0x66, 0x65, 0x74, 0x74, 0x6f, 0x2e, 0x70, 0x72, 0x6f, 0x74,
- 0x6f, 0x73, 0x2e, 0x43, 0x68, 0x72, 0x6f, 0x6d, 0x65, 0x43, 0x6f, 0x6d,
- 0x70, 0x6f, 0x73, 0x69, 0x74, 0x6f, 0x72, 0x53, 0x63, 0x68, 0x65, 0x64,
- 0x75, 0x6c, 0x65, 0x72, 0x53, 0x74, 0x61, 0x74, 0x65, 0x2e, 0x42, 0x65,
- 0x67, 0x69, 0x6e, 0x49, 0x6d, 0x70, 0x6c, 0x46, 0x72, 0x61, 0x6d, 0x65,
- 0x44, 0x65, 0x61, 0x64, 0x6c, 0x69, 0x6e, 0x65, 0x4d, 0x6f, 0x64, 0x65,
- 0x52, 0x0c, 0x64, 0x65, 0x61, 0x64, 0x6c, 0x69, 0x6e, 0x65, 0x4d, 0x6f,
- 0x64, 0x65, 0x12, 0x1f, 0x0a, 0x0b, 0x64, 0x65, 0x61, 0x64, 0x6c, 0x69,
- 0x6e, 0x65, 0x5f, 0x75, 0x73, 0x18, 0x09, 0x20, 0x01, 0x28, 0x03, 0x52,
- 0x0a, 0x64, 0x65, 0x61, 0x64, 0x6c, 0x69, 0x6e, 0x65, 0x55, 0x73, 0x12,
- 0x37, 0x0a, 0x18, 0x64, 0x65, 0x61, 0x64, 0x6c, 0x69, 0x6e, 0x65, 0x5f,
- 0x73, 0x63, 0x68, 0x65, 0x64, 0x75, 0x6c, 0x65, 0x64, 0x5f, 0x61, 0x74,
- 0x5f, 0x75, 0x73, 0x18, 0x0a, 0x20, 0x01, 0x28, 0x03, 0x52, 0x15, 0x64,
- 0x65, 0x61, 0x64, 0x6c, 0x69, 0x6e, 0x65, 0x53, 0x63, 0x68, 0x65, 0x64,
- 0x75, 0x6c, 0x65, 0x64, 0x41, 0x74, 0x55, 0x73, 0x12, 0x15, 0x0a, 0x06,
- 0x6e, 0x6f, 0x77, 0x5f, 0x75, 0x73, 0x18, 0x0b, 0x20, 0x01, 0x28, 0x03,
- 0x52, 0x05, 0x6e, 0x6f, 0x77, 0x55, 0x73, 0x12, 0x36, 0x0a, 0x18, 0x6e,
- 0x6f, 0x77, 0x5f, 0x74, 0x6f, 0x5f, 0x64, 0x65, 0x61, 0x64, 0x6c, 0x69,
- 0x6e, 0x65, 0x5f, 0x64, 0x65, 0x6c, 0x74, 0x61, 0x5f, 0x75, 0x73, 0x18,
- 0x0c, 0x20, 0x01, 0x28, 0x03, 0x52, 0x14, 0x6e, 0x6f, 0x77, 0x54, 0x6f,
- 0x44, 0x65, 0x61, 0x64, 0x6c, 0x69, 0x6e, 0x65, 0x44, 0x65, 0x6c, 0x74,
- 0x61, 0x55, 0x73, 0x12, 0x4e, 0x0a, 0x25, 0x6e, 0x6f, 0x77, 0x5f, 0x74,
- 0x6f, 0x5f, 0x64, 0x65, 0x61, 0x64, 0x6c, 0x69, 0x6e, 0x65, 0x5f, 0x73,
- 0x63, 0x68, 0x65, 0x64, 0x75, 0x6c, 0x65, 0x64, 0x5f, 0x61, 0x74, 0x5f,
- 0x64, 0x65, 0x6c, 0x74, 0x61, 0x5f, 0x75, 0x73, 0x18, 0x0d, 0x20, 0x01,
- 0x28, 0x03, 0x52, 0x1f, 0x6e, 0x6f, 0x77, 0x54, 0x6f, 0x44, 0x65, 0x61,
- 0x64, 0x6c, 0x69, 0x6e, 0x65, 0x53, 0x63, 0x68, 0x65, 0x64, 0x75, 0x6c,
- 0x65, 0x64, 0x41, 0x74, 0x44, 0x65, 0x6c, 0x74, 0x61, 0x55, 0x73, 0x12,
- 0x56, 0x0a, 0x15, 0x62, 0x65, 0x67, 0x69, 0x6e, 0x5f, 0x69, 0x6d, 0x70,
- 0x6c, 0x5f, 0x66, 0x72, 0x61, 0x6d, 0x65, 0x5f, 0x61, 0x72, 0x67, 0x73,
- 0x18, 0x0e, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x23, 0x2e, 0x70, 0x65, 0x72,
- 0x66, 0x65, 0x74, 0x74, 0x6f, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73,
- 0x2e, 0x42, 0x65, 0x67, 0x69, 0x6e, 0x49, 0x6d, 0x70, 0x6c, 0x46, 0x72,
- 0x61, 0x6d, 0x65, 0x41, 0x72, 0x67, 0x73, 0x52, 0x12, 0x62, 0x65, 0x67,
- 0x69, 0x6e, 0x49, 0x6d, 0x70, 0x6c, 0x46, 0x72, 0x61, 0x6d, 0x65, 0x41,
- 0x72, 0x67, 0x73, 0x12, 0x65, 0x0a, 0x1a, 0x62, 0x65, 0x67, 0x69, 0x6e,
- 0x5f, 0x66, 0x72, 0x61, 0x6d, 0x65, 0x5f, 0x6f, 0x62, 0x73, 0x65, 0x72,
- 0x76, 0x65, 0x72, 0x5f, 0x73, 0x74, 0x61, 0x74, 0x65, 0x18, 0x0f, 0x20,
- 0x01, 0x28, 0x0b, 0x32, 0x28, 0x2e, 0x70, 0x65, 0x72, 0x66, 0x65, 0x74,
- 0x74, 0x6f, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2e, 0x42, 0x65,
- 0x67, 0x69, 0x6e, 0x46, 0x72, 0x61, 0x6d, 0x65, 0x4f, 0x62, 0x73, 0x65,
- 0x72, 0x76, 0x65, 0x72, 0x53, 0x74, 0x61, 0x74, 0x65, 0x52, 0x17, 0x62,
- 0x65, 0x67, 0x69, 0x6e, 0x46, 0x72, 0x61, 0x6d, 0x65, 0x4f, 0x62, 0x73,
- 0x65, 0x72, 0x76, 0x65, 0x72, 0x53, 0x74, 0x61, 0x74, 0x65, 0x12, 0x5f,
- 0x0a, 0x18, 0x62, 0x65, 0x67, 0x69, 0x6e, 0x5f, 0x66, 0x72, 0x61, 0x6d,
- 0x65, 0x5f, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x5f, 0x73, 0x74, 0x61,
- 0x74, 0x65, 0x18, 0x10, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x26, 0x2e, 0x70,
- 0x65, 0x72, 0x66, 0x65, 0x74, 0x74, 0x6f, 0x2e, 0x70, 0x72, 0x6f, 0x74,
- 0x6f, 0x73, 0x2e, 0x42, 0x65, 0x67, 0x69, 0x6e, 0x46, 0x72, 0x61, 0x6d,
- 0x65, 0x53, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x53, 0x74, 0x61, 0x74, 0x65,
- 0x52, 0x15, 0x62, 0x65, 0x67, 0x69, 0x6e, 0x46, 0x72, 0x61, 0x6d, 0x65,
- 0x53, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x53, 0x74, 0x61, 0x74, 0x65, 0x12,
- 0x64, 0x0a, 0x19, 0x63, 0x6f, 0x6d, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x6f,
- 0x72, 0x5f, 0x74, 0x69, 0x6d, 0x69, 0x6e, 0x67, 0x5f, 0x68, 0x69, 0x73,
- 0x74, 0x6f, 0x72, 0x79, 0x18, 0x11, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x28,
- 0x2e, 0x70, 0x65, 0x72, 0x66, 0x65, 0x74, 0x74, 0x6f, 0x2e, 0x70, 0x72,
- 0x6f, 0x74, 0x6f, 0x73, 0x2e, 0x43, 0x6f, 0x6d, 0x70, 0x6f, 0x73, 0x69,
- 0x74, 0x6f, 0x72, 0x54, 0x69, 0x6d, 0x69, 0x6e, 0x67, 0x48, 0x69, 0x73,
- 0x74, 0x6f, 0x72, 0x79, 0x52, 0x17, 0x63, 0x6f, 0x6d, 0x70, 0x6f, 0x73,
- 0x69, 0x74, 0x6f, 0x72, 0x54, 0x69, 0x6d, 0x69, 0x6e, 0x67, 0x48, 0x69,
- 0x73, 0x74, 0x6f, 0x72, 0x79, 0x22, 0xbe, 0x01, 0x0a, 0x1a, 0x42, 0x65,
- 0x67, 0x69, 0x6e, 0x49, 0x6d, 0x70, 0x6c, 0x46, 0x72, 0x61, 0x6d, 0x65,
- 0x44, 0x65, 0x61, 0x64, 0x6c, 0x69, 0x6e, 0x65, 0x4d, 0x6f, 0x64, 0x65,
- 0x12, 0x1d, 0x0a, 0x19, 0x44, 0x45, 0x41, 0x44, 0x4c, 0x49, 0x4e, 0x45,
- 0x5f, 0x4d, 0x4f, 0x44, 0x45, 0x5f, 0x55, 0x4e, 0x53, 0x50, 0x45, 0x43,
- 0x49, 0x46, 0x49, 0x45, 0x44, 0x10, 0x00, 0x12, 0x16, 0x0a, 0x12, 0x44,
- 0x45, 0x41, 0x44, 0x4c, 0x49, 0x4e, 0x45, 0x5f, 0x4d, 0x4f, 0x44, 0x45,
- 0x5f, 0x4e, 0x4f, 0x4e, 0x45, 0x10, 0x01, 0x12, 0x1b, 0x0a, 0x17, 0x44,
- 0x45, 0x41, 0x44, 0x4c, 0x49, 0x4e, 0x45, 0x5f, 0x4d, 0x4f, 0x44, 0x45,
- 0x5f, 0x49, 0x4d, 0x4d, 0x45, 0x44, 0x49, 0x41, 0x54, 0x45, 0x10, 0x02,
- 0x12, 0x19, 0x0a, 0x15, 0x44, 0x45, 0x41, 0x44, 0x4c, 0x49, 0x4e, 0x45,
- 0x5f, 0x4d, 0x4f, 0x44, 0x45, 0x5f, 0x52, 0x45, 0x47, 0x55, 0x4c, 0x41,
- 0x52, 0x10, 0x03, 0x12, 0x16, 0x0a, 0x12, 0x44, 0x45, 0x41, 0x44, 0x4c,
- 0x49, 0x4e, 0x45, 0x5f, 0x4d, 0x4f, 0x44, 0x45, 0x5f, 0x4c, 0x41, 0x54,
- 0x45, 0x10, 0x04, 0x12, 0x19, 0x0a, 0x15, 0x44, 0x45, 0x41, 0x44, 0x4c,
- 0x49, 0x4e, 0x45, 0x5f, 0x4d, 0x4f, 0x44, 0x45, 0x5f, 0x42, 0x4c, 0x4f,
- 0x43, 0x4b, 0x45, 0x44, 0x10, 0x05, 0x22, 0x86, 0x28, 0x0a, 0x1c, 0x43,
- 0x68, 0x72, 0x6f, 0x6d, 0x65, 0x43, 0x6f, 0x6d, 0x70, 0x6f, 0x73, 0x69,
- 0x74, 0x6f, 0x72, 0x53, 0x74, 0x61, 0x74, 0x65, 0x4d, 0x61, 0x63, 0x68,
- 0x69, 0x6e, 0x65, 0x12, 0x59, 0x0a, 0x0b, 0x6d, 0x61, 0x6a, 0x6f, 0x72,
- 0x5f, 0x73, 0x74, 0x61, 0x74, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b,
- 0x32, 0x38, 0x2e, 0x70, 0x65, 0x72, 0x66, 0x65, 0x74, 0x74, 0x6f, 0x2e,
+ 0x6e, 0x65, 0x2e, 0x4d, 0x69, 0x6e, 0x6f, 0x72, 0x53, 0x74, 0x61, 0x74,
+ 0x65, 0x52, 0x0a, 0x6d, 0x69, 0x6e, 0x6f, 0x72, 0x53, 0x74, 0x61, 0x74,
+ 0x65, 0x1a, 0xf9, 0x0a, 0x0a, 0x0a, 0x4d, 0x61, 0x6a, 0x6f, 0x72, 0x53,
+ 0x74, 0x61, 0x74, 0x65, 0x12, 0x51, 0x0a, 0x0b, 0x6e, 0x65, 0x78, 0x74,
+ 0x5f, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x01, 0x20, 0x01, 0x28,
+ 0x0e, 0x32, 0x30, 0x2e, 0x70, 0x65, 0x72, 0x66, 0x65, 0x74, 0x74, 0x6f,
+ 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2e, 0x43, 0x68, 0x72, 0x6f,
+ 0x6d, 0x65, 0x43, 0x6f, 0x6d, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x6f, 0x72,
+ 0x53, 0x63, 0x68, 0x65, 0x64, 0x75, 0x6c, 0x65, 0x72, 0x41, 0x63, 0x74,
+ 0x69, 0x6f, 0x6e, 0x52, 0x0a, 0x6e, 0x65, 0x78, 0x74, 0x41, 0x63, 0x74,
+ 0x69, 0x6f, 0x6e, 0x12, 0x81, 0x01, 0x0a, 0x16, 0x62, 0x65, 0x67, 0x69,
+ 0x6e, 0x5f, 0x69, 0x6d, 0x70, 0x6c, 0x5f, 0x66, 0x72, 0x61, 0x6d, 0x65,
+ 0x5f, 0x73, 0x74, 0x61, 0x74, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0e,
+ 0x32, 0x4c, 0x2e, 0x70, 0x65, 0x72, 0x66, 0x65, 0x74, 0x74, 0x6f, 0x2e,
0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2e, 0x43, 0x68, 0x72, 0x6f, 0x6d,
0x65, 0x43, 0x6f, 0x6d, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x6f, 0x72, 0x53,
0x74, 0x61, 0x74, 0x65, 0x4d, 0x61, 0x63, 0x68, 0x69, 0x6e, 0x65, 0x2e,
- 0x4d, 0x61, 0x6a, 0x6f, 0x72, 0x53, 0x74, 0x61, 0x74, 0x65, 0x52, 0x0a,
- 0x6d, 0x61, 0x6a, 0x6f, 0x72, 0x53, 0x74, 0x61, 0x74, 0x65, 0x12, 0x59,
- 0x0a, 0x0b, 0x6d, 0x69, 0x6e, 0x6f, 0x72, 0x5f, 0x73, 0x74, 0x61, 0x74,
- 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x38, 0x2e, 0x70, 0x65,
+ 0x4d, 0x61, 0x6a, 0x6f, 0x72, 0x53, 0x74, 0x61, 0x74, 0x65, 0x2e, 0x42,
+ 0x65, 0x67, 0x69, 0x6e, 0x49, 0x6d, 0x70, 0x6c, 0x46, 0x72, 0x61, 0x6d,
+ 0x65, 0x53, 0x74, 0x61, 0x74, 0x65, 0x52, 0x13, 0x62, 0x65, 0x67, 0x69,
+ 0x6e, 0x49, 0x6d, 0x70, 0x6c, 0x46, 0x72, 0x61, 0x6d, 0x65, 0x53, 0x74,
+ 0x61, 0x74, 0x65, 0x12, 0x81, 0x01, 0x0a, 0x16, 0x62, 0x65, 0x67, 0x69,
+ 0x6e, 0x5f, 0x6d, 0x61, 0x69, 0x6e, 0x5f, 0x66, 0x72, 0x61, 0x6d, 0x65,
+ 0x5f, 0x73, 0x74, 0x61, 0x74, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0e,
+ 0x32, 0x4c, 0x2e, 0x70, 0x65, 0x72, 0x66, 0x65, 0x74, 0x74, 0x6f, 0x2e,
+ 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2e, 0x43, 0x68, 0x72, 0x6f, 0x6d,
+ 0x65, 0x43, 0x6f, 0x6d, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x6f, 0x72, 0x53,
+ 0x74, 0x61, 0x74, 0x65, 0x4d, 0x61, 0x63, 0x68, 0x69, 0x6e, 0x65, 0x2e,
+ 0x4d, 0x61, 0x6a, 0x6f, 0x72, 0x53, 0x74, 0x61, 0x74, 0x65, 0x2e, 0x42,
+ 0x65, 0x67, 0x69, 0x6e, 0x4d, 0x61, 0x69, 0x6e, 0x46, 0x72, 0x61, 0x6d,
+ 0x65, 0x53, 0x74, 0x61, 0x74, 0x65, 0x52, 0x13, 0x62, 0x65, 0x67, 0x69,
+ 0x6e, 0x4d, 0x61, 0x69, 0x6e, 0x46, 0x72, 0x61, 0x6d, 0x65, 0x53, 0x74,
+ 0x61, 0x74, 0x65, 0x12, 0x8e, 0x01, 0x0a, 0x1b, 0x6c, 0x61, 0x79, 0x65,
+ 0x72, 0x5f, 0x74, 0x72, 0x65, 0x65, 0x5f, 0x66, 0x72, 0x61, 0x6d, 0x65,
+ 0x5f, 0x73, 0x69, 0x6e, 0x6b, 0x5f, 0x73, 0x74, 0x61, 0x74, 0x65, 0x18,
+ 0x04, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x50, 0x2e, 0x70, 0x65, 0x72, 0x66,
+ 0x65, 0x74, 0x74, 0x6f, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2e,
+ 0x43, 0x68, 0x72, 0x6f, 0x6d, 0x65, 0x43, 0x6f, 0x6d, 0x70, 0x6f, 0x73,
+ 0x69, 0x74, 0x6f, 0x72, 0x53, 0x74, 0x61, 0x74, 0x65, 0x4d, 0x61, 0x63,
+ 0x68, 0x69, 0x6e, 0x65, 0x2e, 0x4d, 0x61, 0x6a, 0x6f, 0x72, 0x53, 0x74,
+ 0x61, 0x74, 0x65, 0x2e, 0x4c, 0x61, 0x79, 0x65, 0x72, 0x54, 0x72, 0x65,
+ 0x65, 0x46, 0x72, 0x61, 0x6d, 0x65, 0x53, 0x69, 0x6e, 0x6b, 0x53, 0x74,
+ 0x61, 0x74, 0x65, 0x52, 0x17, 0x6c, 0x61, 0x79, 0x65, 0x72, 0x54, 0x72,
+ 0x65, 0x65, 0x46, 0x72, 0x61, 0x6d, 0x65, 0x53, 0x69, 0x6e, 0x6b, 0x53,
+ 0x74, 0x61, 0x74, 0x65, 0x12, 0x83, 0x01, 0x0a, 0x13, 0x66, 0x6f, 0x72,
+ 0x63, 0x65, 0x64, 0x5f, 0x72, 0x65, 0x64, 0x72, 0x61, 0x77, 0x5f, 0x73,
+ 0x74, 0x61, 0x74, 0x65, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x53,
+ 0x2e, 0x70, 0x65, 0x72, 0x66, 0x65, 0x74, 0x74, 0x6f, 0x2e, 0x70, 0x72,
+ 0x6f, 0x74, 0x6f, 0x73, 0x2e, 0x43, 0x68, 0x72, 0x6f, 0x6d, 0x65, 0x43,
+ 0x6f, 0x6d, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x6f, 0x72, 0x53, 0x74, 0x61,
+ 0x74, 0x65, 0x4d, 0x61, 0x63, 0x68, 0x69, 0x6e, 0x65, 0x2e, 0x4d, 0x61,
+ 0x6a, 0x6f, 0x72, 0x53, 0x74, 0x61, 0x74, 0x65, 0x2e, 0x46, 0x6f, 0x72,
+ 0x63, 0x65, 0x64, 0x52, 0x65, 0x64, 0x72, 0x61, 0x77, 0x4f, 0x6e, 0x54,
+ 0x69, 0x6d, 0x65, 0x6f, 0x75, 0x74, 0x53, 0x74, 0x61, 0x74, 0x65, 0x52,
+ 0x11, 0x66, 0x6f, 0x72, 0x63, 0x65, 0x64, 0x52, 0x65, 0x64, 0x72, 0x61,
+ 0x77, 0x53, 0x74, 0x61, 0x74, 0x65, 0x22, 0xa1, 0x01, 0x0a, 0x13, 0x42,
+ 0x65, 0x67, 0x69, 0x6e, 0x49, 0x6d, 0x70, 0x6c, 0x46, 0x72, 0x61, 0x6d,
+ 0x65, 0x53, 0x74, 0x61, 0x74, 0x65, 0x12, 0x20, 0x0a, 0x1c, 0x42, 0x45,
+ 0x47, 0x49, 0x4e, 0x5f, 0x49, 0x4d, 0x50, 0x4c, 0x5f, 0x46, 0x52, 0x41,
+ 0x4d, 0x45, 0x5f, 0x55, 0x4e, 0x53, 0x50, 0x45, 0x43, 0x49, 0x46, 0x49,
+ 0x45, 0x44, 0x10, 0x00, 0x12, 0x19, 0x0a, 0x15, 0x42, 0x45, 0x47, 0x49,
+ 0x4e, 0x5f, 0x49, 0x4d, 0x50, 0x4c, 0x5f, 0x46, 0x52, 0x41, 0x4d, 0x45,
+ 0x5f, 0x49, 0x44, 0x4c, 0x45, 0x10, 0x01, 0x12, 0x27, 0x0a, 0x23, 0x42,
+ 0x45, 0x47, 0x49, 0x4e, 0x5f, 0x49, 0x4d, 0x50, 0x4c, 0x5f, 0x46, 0x52,
+ 0x41, 0x4d, 0x45, 0x5f, 0x49, 0x4e, 0x53, 0x49, 0x44, 0x45, 0x5f, 0x42,
+ 0x45, 0x47, 0x49, 0x4e, 0x5f, 0x46, 0x52, 0x41, 0x4d, 0x45, 0x10, 0x02,
+ 0x12, 0x24, 0x0a, 0x20, 0x42, 0x45, 0x47, 0x49, 0x4e, 0x5f, 0x49, 0x4d,
+ 0x50, 0x4c, 0x5f, 0x46, 0x52, 0x41, 0x4d, 0x45, 0x5f, 0x49, 0x4e, 0x53,
+ 0x49, 0x44, 0x45, 0x5f, 0x44, 0x45, 0x41, 0x44, 0x4c, 0x49, 0x4e, 0x45,
+ 0x10, 0x03, 0x22, 0x93, 0x01, 0x0a, 0x13, 0x42, 0x65, 0x67, 0x69, 0x6e,
+ 0x4d, 0x61, 0x69, 0x6e, 0x46, 0x72, 0x61, 0x6d, 0x65, 0x53, 0x74, 0x61,
+ 0x74, 0x65, 0x12, 0x20, 0x0a, 0x1c, 0x42, 0x45, 0x47, 0x49, 0x4e, 0x5f,
+ 0x4d, 0x41, 0x49, 0x4e, 0x5f, 0x46, 0x52, 0x41, 0x4d, 0x45, 0x5f, 0x55,
+ 0x4e, 0x53, 0x50, 0x45, 0x43, 0x49, 0x46, 0x49, 0x45, 0x44, 0x10, 0x00,
+ 0x12, 0x19, 0x0a, 0x15, 0x42, 0x45, 0x47, 0x49, 0x4e, 0x5f, 0x4d, 0x41,
+ 0x49, 0x4e, 0x5f, 0x46, 0x52, 0x41, 0x4d, 0x45, 0x5f, 0x49, 0x44, 0x4c,
+ 0x45, 0x10, 0x01, 0x12, 0x19, 0x0a, 0x15, 0x42, 0x45, 0x47, 0x49, 0x4e,
+ 0x5f, 0x4d, 0x41, 0x49, 0x4e, 0x5f, 0x46, 0x52, 0x41, 0x4d, 0x45, 0x5f,
+ 0x53, 0x45, 0x4e, 0x54, 0x10, 0x02, 0x12, 0x24, 0x0a, 0x20, 0x42, 0x45,
+ 0x47, 0x49, 0x4e, 0x5f, 0x4d, 0x41, 0x49, 0x4e, 0x5f, 0x46, 0x52, 0x41,
+ 0x4d, 0x45, 0x5f, 0x52, 0x45, 0x41, 0x44, 0x59, 0x5f, 0x54, 0x4f, 0x5f,
+ 0x43, 0x4f, 0x4d, 0x4d, 0x49, 0x54, 0x10, 0x03, 0x22, 0xf4, 0x01, 0x0a,
+ 0x17, 0x4c, 0x61, 0x79, 0x65, 0x72, 0x54, 0x72, 0x65, 0x65, 0x46, 0x72,
+ 0x61, 0x6d, 0x65, 0x53, 0x69, 0x6e, 0x6b, 0x53, 0x74, 0x61, 0x74, 0x65,
+ 0x12, 0x20, 0x0a, 0x1c, 0x4c, 0x41, 0x59, 0x45, 0x52, 0x5f, 0x54, 0x52,
+ 0x45, 0x45, 0x5f, 0x46, 0x52, 0x41, 0x4d, 0x45, 0x5f, 0x55, 0x4e, 0x53,
+ 0x50, 0x45, 0x43, 0x49, 0x46, 0x49, 0x45, 0x44, 0x10, 0x00, 0x12, 0x19,
+ 0x0a, 0x15, 0x4c, 0x41, 0x59, 0x45, 0x52, 0x5f, 0x54, 0x52, 0x45, 0x45,
+ 0x5f, 0x46, 0x52, 0x41, 0x4d, 0x45, 0x5f, 0x4e, 0x4f, 0x4e, 0x45, 0x10,
+ 0x01, 0x12, 0x1b, 0x0a, 0x17, 0x4c, 0x41, 0x59, 0x45, 0x52, 0x5f, 0x54,
+ 0x52, 0x45, 0x45, 0x5f, 0x46, 0x52, 0x41, 0x4d, 0x45, 0x5f, 0x41, 0x43,
+ 0x54, 0x49, 0x56, 0x45, 0x10, 0x02, 0x12, 0x1d, 0x0a, 0x19, 0x4c, 0x41,
+ 0x59, 0x45, 0x52, 0x5f, 0x54, 0x52, 0x45, 0x45, 0x5f, 0x46, 0x52, 0x41,
+ 0x4d, 0x45, 0x5f, 0x43, 0x52, 0x45, 0x41, 0x54, 0x49, 0x4e, 0x47, 0x10,
+ 0x03, 0x12, 0x2d, 0x0a, 0x29, 0x4c, 0x41, 0x59, 0x45, 0x52, 0x5f, 0x54,
+ 0x52, 0x45, 0x45, 0x5f, 0x46, 0x52, 0x41, 0x4d, 0x45, 0x5f, 0x57, 0x41,
+ 0x49, 0x54, 0x49, 0x4e, 0x47, 0x5f, 0x46, 0x4f, 0x52, 0x5f, 0x46, 0x49,
+ 0x52, 0x53, 0x54, 0x5f, 0x43, 0x4f, 0x4d, 0x4d, 0x49, 0x54, 0x10, 0x04,
+ 0x12, 0x31, 0x0a, 0x2d, 0x4c, 0x41, 0x59, 0x45, 0x52, 0x5f, 0x54, 0x52,
+ 0x45, 0x45, 0x5f, 0x46, 0x52, 0x41, 0x4d, 0x45, 0x5f, 0x57, 0x41, 0x49,
+ 0x54, 0x49, 0x4e, 0x47, 0x5f, 0x46, 0x4f, 0x52, 0x5f, 0x46, 0x49, 0x52,
+ 0x53, 0x54, 0x5f, 0x41, 0x43, 0x54, 0x49, 0x56, 0x41, 0x54, 0x49, 0x4f,
+ 0x4e, 0x10, 0x05, 0x22, 0xc7, 0x01, 0x0a, 0x1a, 0x46, 0x6f, 0x72, 0x63,
+ 0x65, 0x64, 0x52, 0x65, 0x64, 0x72, 0x61, 0x77, 0x4f, 0x6e, 0x54, 0x69,
+ 0x6d, 0x65, 0x6f, 0x75, 0x74, 0x53, 0x74, 0x61, 0x74, 0x65, 0x12, 0x1d,
+ 0x0a, 0x19, 0x46, 0x4f, 0x52, 0x43, 0x45, 0x44, 0x5f, 0x52, 0x45, 0x44,
+ 0x52, 0x41, 0x57, 0x5f, 0x55, 0x4e, 0x53, 0x50, 0x45, 0x43, 0x49, 0x46,
+ 0x49, 0x45, 0x44, 0x10, 0x00, 0x12, 0x16, 0x0a, 0x12, 0x46, 0x4f, 0x52,
+ 0x43, 0x45, 0x44, 0x5f, 0x52, 0x45, 0x44, 0x52, 0x41, 0x57, 0x5f, 0x49,
+ 0x44, 0x4c, 0x45, 0x10, 0x01, 0x12, 0x24, 0x0a, 0x20, 0x46, 0x4f, 0x52,
+ 0x43, 0x45, 0x44, 0x5f, 0x52, 0x45, 0x44, 0x52, 0x41, 0x57, 0x5f, 0x57,
+ 0x41, 0x49, 0x54, 0x49, 0x4e, 0x47, 0x5f, 0x46, 0x4f, 0x52, 0x5f, 0x43,
+ 0x4f, 0x4d, 0x4d, 0x49, 0x54, 0x10, 0x02, 0x12, 0x28, 0x0a, 0x24, 0x46,
+ 0x4f, 0x52, 0x43, 0x45, 0x44, 0x5f, 0x52, 0x45, 0x44, 0x52, 0x41, 0x57,
+ 0x5f, 0x57, 0x41, 0x49, 0x54, 0x49, 0x4e, 0x47, 0x5f, 0x46, 0x4f, 0x52,
+ 0x5f, 0x41, 0x43, 0x54, 0x49, 0x56, 0x41, 0x54, 0x49, 0x4f, 0x4e, 0x10,
+ 0x03, 0x12, 0x22, 0x0a, 0x1e, 0x46, 0x4f, 0x52, 0x43, 0x45, 0x44, 0x5f,
+ 0x52, 0x45, 0x44, 0x52, 0x41, 0x57, 0x5f, 0x57, 0x41, 0x49, 0x54, 0x49,
+ 0x4e, 0x47, 0x5f, 0x46, 0x4f, 0x52, 0x5f, 0x44, 0x52, 0x41, 0x57, 0x10,
+ 0x04, 0x1a, 0xb3, 0x1b, 0x0a, 0x0a, 0x4d, 0x69, 0x6e, 0x6f, 0x72, 0x53,
+ 0x74, 0x61, 0x74, 0x65, 0x12, 0x21, 0x0a, 0x0c, 0x63, 0x6f, 0x6d, 0x6d,
+ 0x69, 0x74, 0x5f, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x18, 0x01, 0x20, 0x01,
+ 0x28, 0x05, 0x52, 0x0b, 0x63, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x43, 0x6f,
+ 0x75, 0x6e, 0x74, 0x12, 0x30, 0x0a, 0x14, 0x63, 0x75, 0x72, 0x72, 0x65,
+ 0x6e, 0x74, 0x5f, 0x66, 0x72, 0x61, 0x6d, 0x65, 0x5f, 0x6e, 0x75, 0x6d,
+ 0x62, 0x65, 0x72, 0x18, 0x02, 0x20, 0x01, 0x28, 0x05, 0x52, 0x12, 0x63,
+ 0x75, 0x72, 0x72, 0x65, 0x6e, 0x74, 0x46, 0x72, 0x61, 0x6d, 0x65, 0x4e,
+ 0x75, 0x6d, 0x62, 0x65, 0x72, 0x12, 0x4a, 0x0a, 0x22, 0x6c, 0x61, 0x73,
+ 0x74, 0x5f, 0x66, 0x72, 0x61, 0x6d, 0x65, 0x5f, 0x6e, 0x75, 0x6d, 0x62,
+ 0x65, 0x72, 0x5f, 0x73, 0x75, 0x62, 0x6d, 0x69, 0x74, 0x5f, 0x70, 0x65,
+ 0x72, 0x66, 0x6f, 0x72, 0x6d, 0x65, 0x64, 0x18, 0x03, 0x20, 0x01, 0x28,
+ 0x05, 0x52, 0x1e, 0x6c, 0x61, 0x73, 0x74, 0x46, 0x72, 0x61, 0x6d, 0x65,
+ 0x4e, 0x75, 0x6d, 0x62, 0x65, 0x72, 0x53, 0x75, 0x62, 0x6d, 0x69, 0x74,
+ 0x50, 0x65, 0x72, 0x66, 0x6f, 0x72, 0x6d, 0x65, 0x64, 0x12, 0x46, 0x0a,
+ 0x20, 0x6c, 0x61, 0x73, 0x74, 0x5f, 0x66, 0x72, 0x61, 0x6d, 0x65, 0x5f,
+ 0x6e, 0x75, 0x6d, 0x62, 0x65, 0x72, 0x5f, 0x64, 0x72, 0x61, 0x77, 0x5f,
+ 0x70, 0x65, 0x72, 0x66, 0x6f, 0x72, 0x6d, 0x65, 0x64, 0x18, 0x04, 0x20,
+ 0x01, 0x28, 0x05, 0x52, 0x1c, 0x6c, 0x61, 0x73, 0x74, 0x46, 0x72, 0x61,
+ 0x6d, 0x65, 0x4e, 0x75, 0x6d, 0x62, 0x65, 0x72, 0x44, 0x72, 0x61, 0x77,
+ 0x50, 0x65, 0x72, 0x66, 0x6f, 0x72, 0x6d, 0x65, 0x64, 0x12, 0x52, 0x0a,
+ 0x27, 0x6c, 0x61, 0x73, 0x74, 0x5f, 0x66, 0x72, 0x61, 0x6d, 0x65, 0x5f,
+ 0x6e, 0x75, 0x6d, 0x62, 0x65, 0x72, 0x5f, 0x62, 0x65, 0x67, 0x69, 0x6e,
+ 0x5f, 0x6d, 0x61, 0x69, 0x6e, 0x5f, 0x66, 0x72, 0x61, 0x6d, 0x65, 0x5f,
+ 0x73, 0x65, 0x6e, 0x74, 0x18, 0x05, 0x20, 0x01, 0x28, 0x05, 0x52, 0x21,
+ 0x6c, 0x61, 0x73, 0x74, 0x46, 0x72, 0x61, 0x6d, 0x65, 0x4e, 0x75, 0x6d,
+ 0x62, 0x65, 0x72, 0x42, 0x65, 0x67, 0x69, 0x6e, 0x4d, 0x61, 0x69, 0x6e,
+ 0x46, 0x72, 0x61, 0x6d, 0x65, 0x53, 0x65, 0x6e, 0x74, 0x12, 0x19, 0x0a,
+ 0x08, 0x64, 0x69, 0x64, 0x5f, 0x64, 0x72, 0x61, 0x77, 0x18, 0x06, 0x20,
+ 0x01, 0x28, 0x08, 0x52, 0x07, 0x64, 0x69, 0x64, 0x44, 0x72, 0x61, 0x77,
+ 0x12, 0x59, 0x0a, 0x2b, 0x64, 0x69, 0x64, 0x5f, 0x73, 0x65, 0x6e, 0x64,
+ 0x5f, 0x62, 0x65, 0x67, 0x69, 0x6e, 0x5f, 0x6d, 0x61, 0x69, 0x6e, 0x5f,
+ 0x66, 0x72, 0x61, 0x6d, 0x65, 0x5f, 0x66, 0x6f, 0x72, 0x5f, 0x63, 0x75,
+ 0x72, 0x72, 0x65, 0x6e, 0x74, 0x5f, 0x66, 0x72, 0x61, 0x6d, 0x65, 0x18,
+ 0x07, 0x20, 0x01, 0x28, 0x08, 0x52, 0x24, 0x64, 0x69, 0x64, 0x53, 0x65,
+ 0x6e, 0x64, 0x42, 0x65, 0x67, 0x69, 0x6e, 0x4d, 0x61, 0x69, 0x6e, 0x46,
+ 0x72, 0x61, 0x6d, 0x65, 0x46, 0x6f, 0x72, 0x43, 0x75, 0x72, 0x72, 0x65,
+ 0x6e, 0x74, 0x46, 0x72, 0x61, 0x6d, 0x65, 0x12, 0x5f, 0x0a, 0x2e, 0x64,
+ 0x69, 0x64, 0x5f, 0x6e, 0x6f, 0x74, 0x69, 0x66, 0x79, 0x5f, 0x62, 0x65,
+ 0x67, 0x69, 0x6e, 0x5f, 0x6d, 0x61, 0x69, 0x6e, 0x5f, 0x66, 0x72, 0x61,
+ 0x6d, 0x65, 0x5f, 0x6e, 0x6f, 0x74, 0x5f, 0x65, 0x78, 0x70, 0x65, 0x63,
+ 0x74, 0x65, 0x64, 0x5f, 0x75, 0x6e, 0x74, 0x69, 0x6c, 0x18, 0x08, 0x20,
+ 0x01, 0x28, 0x08, 0x52, 0x27, 0x64, 0x69, 0x64, 0x4e, 0x6f, 0x74, 0x69,
+ 0x66, 0x79, 0x42, 0x65, 0x67, 0x69, 0x6e, 0x4d, 0x61, 0x69, 0x6e, 0x46,
+ 0x72, 0x61, 0x6d, 0x65, 0x4e, 0x6f, 0x74, 0x45, 0x78, 0x70, 0x65, 0x63,
+ 0x74, 0x65, 0x64, 0x55, 0x6e, 0x74, 0x69, 0x6c, 0x12, 0x5d, 0x0a, 0x2d,
+ 0x64, 0x69, 0x64, 0x5f, 0x6e, 0x6f, 0x74, 0x69, 0x66, 0x79, 0x5f, 0x62,
+ 0x65, 0x67, 0x69, 0x6e, 0x5f, 0x6d, 0x61, 0x69, 0x6e, 0x5f, 0x66, 0x72,
+ 0x61, 0x6d, 0x65, 0x5f, 0x6e, 0x6f, 0x74, 0x5f, 0x65, 0x78, 0x70, 0x65,
+ 0x63, 0x74, 0x65, 0x64, 0x5f, 0x73, 0x6f, 0x6f, 0x6e, 0x18, 0x09, 0x20,
+ 0x01, 0x28, 0x08, 0x52, 0x26, 0x64, 0x69, 0x64, 0x4e, 0x6f, 0x74, 0x69,
+ 0x66, 0x79, 0x42, 0x65, 0x67, 0x69, 0x6e, 0x4d, 0x61, 0x69, 0x6e, 0x46,
+ 0x72, 0x61, 0x6d, 0x65, 0x4e, 0x6f, 0x74, 0x45, 0x78, 0x70, 0x65, 0x63,
+ 0x74, 0x65, 0x64, 0x53, 0x6f, 0x6f, 0x6e, 0x12, 0x4b, 0x0a, 0x23, 0x77,
+ 0x61, 0x6e, 0x74, 0x73, 0x5f, 0x62, 0x65, 0x67, 0x69, 0x6e, 0x5f, 0x6d,
+ 0x61, 0x69, 0x6e, 0x5f, 0x66, 0x72, 0x61, 0x6d, 0x65, 0x5f, 0x6e, 0x6f,
+ 0x74, 0x5f, 0x65, 0x78, 0x70, 0x65, 0x63, 0x74, 0x65, 0x64, 0x18, 0x0a,
+ 0x20, 0x01, 0x28, 0x08, 0x52, 0x1e, 0x77, 0x61, 0x6e, 0x74, 0x73, 0x42,
+ 0x65, 0x67, 0x69, 0x6e, 0x4d, 0x61, 0x69, 0x6e, 0x46, 0x72, 0x61, 0x6d,
+ 0x65, 0x4e, 0x6f, 0x74, 0x45, 0x78, 0x70, 0x65, 0x63, 0x74, 0x65, 0x64,
+ 0x12, 0x35, 0x0a, 0x17, 0x64, 0x69, 0x64, 0x5f, 0x63, 0x6f, 0x6d, 0x6d,
+ 0x69, 0x74, 0x5f, 0x64, 0x75, 0x72, 0x69, 0x6e, 0x67, 0x5f, 0x66, 0x72,
+ 0x61, 0x6d, 0x65, 0x18, 0x0b, 0x20, 0x01, 0x28, 0x08, 0x52, 0x14, 0x64,
+ 0x69, 0x64, 0x43, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x44, 0x75, 0x72, 0x69,
+ 0x6e, 0x67, 0x46, 0x72, 0x61, 0x6d, 0x65, 0x12, 0x4d, 0x0a, 0x24, 0x64,
+ 0x69, 0x64, 0x5f, 0x69, 0x6e, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74,
+ 0x65, 0x5f, 0x6c, 0x61, 0x79, 0x65, 0x72, 0x5f, 0x74, 0x72, 0x65, 0x65,
+ 0x5f, 0x66, 0x72, 0x61, 0x6d, 0x65, 0x5f, 0x73, 0x69, 0x6e, 0x6b, 0x18,
+ 0x0c, 0x20, 0x01, 0x28, 0x08, 0x52, 0x1f, 0x64, 0x69, 0x64, 0x49, 0x6e,
+ 0x76, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x65, 0x4c, 0x61, 0x79, 0x65,
+ 0x72, 0x54, 0x72, 0x65, 0x65, 0x46, 0x72, 0x61, 0x6d, 0x65, 0x53, 0x69,
+ 0x6e, 0x6b, 0x12, 0x48, 0x0a, 0x21, 0x64, 0x69, 0x64, 0x5f, 0x70, 0x65,
+ 0x72, 0x66, 0x6f, 0x72, 0x6d, 0x5f, 0x69, 0x6d, 0x70, 0x6c, 0x5f, 0x73,
+ 0x69, 0x64, 0x65, 0x5f, 0x69, 0x6e, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x61,
+ 0x69, 0x6f, 0x6e, 0x18, 0x0d, 0x20, 0x01, 0x28, 0x08, 0x52, 0x1d, 0x64,
+ 0x69, 0x64, 0x50, 0x65, 0x72, 0x66, 0x6f, 0x72, 0x6d, 0x49, 0x6d, 0x70,
+ 0x6c, 0x53, 0x69, 0x64, 0x65, 0x49, 0x6e, 0x76, 0x61, 0x6c, 0x69, 0x64,
+ 0x61, 0x69, 0x6f, 0x6e, 0x12, 0x2a, 0x0a, 0x11, 0x64, 0x69, 0x64, 0x5f,
+ 0x70, 0x72, 0x65, 0x70, 0x61, 0x72, 0x65, 0x5f, 0x74, 0x69, 0x6c, 0x65,
+ 0x73, 0x18, 0x0e, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0f, 0x64, 0x69, 0x64,
+ 0x50, 0x72, 0x65, 0x70, 0x61, 0x72, 0x65, 0x54, 0x69, 0x6c, 0x65, 0x73,
+ 0x12, 0x4e, 0x0a, 0x23, 0x63, 0x6f, 0x6e, 0x73, 0x65, 0x63, 0x75, 0x74,
+ 0x69, 0x76, 0x65, 0x5f, 0x63, 0x68, 0x65, 0x63, 0x6b, 0x65, 0x72, 0x62,
+ 0x6f, 0x61, 0x72, 0x64, 0x5f, 0x61, 0x6e, 0x69, 0x6d, 0x61, 0x74, 0x69,
+ 0x6f, 0x6e, 0x73, 0x18, 0x0f, 0x20, 0x01, 0x28, 0x05, 0x52, 0x21, 0x63,
+ 0x6f, 0x6e, 0x73, 0x65, 0x63, 0x75, 0x74, 0x69, 0x76, 0x65, 0x43, 0x68,
+ 0x65, 0x63, 0x6b, 0x65, 0x72, 0x62, 0x6f, 0x61, 0x72, 0x64, 0x41, 0x6e,
+ 0x69, 0x6d, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x12, 0x32, 0x0a, 0x15,
+ 0x70, 0x65, 0x6e, 0x64, 0x69, 0x6e, 0x67, 0x5f, 0x73, 0x75, 0x62, 0x6d,
+ 0x69, 0x74, 0x5f, 0x66, 0x72, 0x61, 0x6d, 0x65, 0x73, 0x18, 0x10, 0x20,
+ 0x01, 0x28, 0x05, 0x52, 0x13, 0x70, 0x65, 0x6e, 0x64, 0x69, 0x6e, 0x67,
+ 0x53, 0x75, 0x62, 0x6d, 0x69, 0x74, 0x46, 0x72, 0x61, 0x6d, 0x65, 0x73,
+ 0x12, 0x63, 0x0a, 0x30, 0x73, 0x75, 0x62, 0x6d, 0x69, 0x74, 0x5f, 0x66,
+ 0x72, 0x61, 0x6d, 0x65, 0x73, 0x5f, 0x77, 0x69, 0x74, 0x68, 0x5f, 0x63,
+ 0x75, 0x72, 0x72, 0x65, 0x6e, 0x74, 0x5f, 0x6c, 0x61, 0x79, 0x65, 0x72,
+ 0x5f, 0x74, 0x72, 0x65, 0x65, 0x5f, 0x66, 0x72, 0x61, 0x6d, 0x65, 0x5f,
+ 0x73, 0x69, 0x6e, 0x6b, 0x18, 0x11, 0x20, 0x01, 0x28, 0x05, 0x52, 0x29,
+ 0x73, 0x75, 0x62, 0x6d, 0x69, 0x74, 0x46, 0x72, 0x61, 0x6d, 0x65, 0x73,
+ 0x57, 0x69, 0x74, 0x68, 0x43, 0x75, 0x72, 0x72, 0x65, 0x6e, 0x74, 0x4c,
+ 0x61, 0x79, 0x65, 0x72, 0x54, 0x72, 0x65, 0x65, 0x46, 0x72, 0x61, 0x6d,
+ 0x65, 0x53, 0x69, 0x6e, 0x6b, 0x12, 0x21, 0x0a, 0x0c, 0x6e, 0x65, 0x65,
+ 0x64, 0x73, 0x5f, 0x72, 0x65, 0x64, 0x72, 0x61, 0x77, 0x18, 0x12, 0x20,
+ 0x01, 0x28, 0x08, 0x52, 0x0b, 0x6e, 0x65, 0x65, 0x64, 0x73, 0x52, 0x65,
+ 0x64, 0x72, 0x61, 0x77, 0x12, 0x2e, 0x0a, 0x13, 0x6e, 0x65, 0x65, 0x64,
+ 0x73, 0x5f, 0x70, 0x72, 0x65, 0x70, 0x61, 0x72, 0x65, 0x5f, 0x74, 0x69,
+ 0x6c, 0x65, 0x73, 0x18, 0x13, 0x20, 0x01, 0x28, 0x08, 0x52, 0x11, 0x6e,
+ 0x65, 0x65, 0x64, 0x73, 0x50, 0x72, 0x65, 0x70, 0x61, 0x72, 0x65, 0x54,
+ 0x69, 0x6c, 0x65, 0x73, 0x12, 0x33, 0x0a, 0x16, 0x6e, 0x65, 0x65, 0x64,
+ 0x73, 0x5f, 0x62, 0x65, 0x67, 0x69, 0x6e, 0x5f, 0x6d, 0x61, 0x69, 0x6e,
+ 0x5f, 0x66, 0x72, 0x61, 0x6d, 0x65, 0x18, 0x14, 0x20, 0x01, 0x28, 0x08,
+ 0x52, 0x13, 0x6e, 0x65, 0x65, 0x64, 0x73, 0x42, 0x65, 0x67, 0x69, 0x6e,
+ 0x4d, 0x61, 0x69, 0x6e, 0x46, 0x72, 0x61, 0x6d, 0x65, 0x12, 0x3a, 0x0a,
+ 0x1a, 0x6e, 0x65, 0x65, 0x64, 0x73, 0x5f, 0x6f, 0x6e, 0x65, 0x5f, 0x62,
+ 0x65, 0x67, 0x69, 0x6e, 0x5f, 0x69, 0x6d, 0x70, 0x6c, 0x5f, 0x66, 0x72,
+ 0x61, 0x6d, 0x65, 0x18, 0x15, 0x20, 0x01, 0x28, 0x08, 0x52, 0x16, 0x6e,
+ 0x65, 0x65, 0x64, 0x73, 0x4f, 0x6e, 0x65, 0x42, 0x65, 0x67, 0x69, 0x6e,
+ 0x49, 0x6d, 0x70, 0x6c, 0x46, 0x72, 0x61, 0x6d, 0x65, 0x12, 0x18, 0x0a,
+ 0x07, 0x76, 0x69, 0x73, 0x69, 0x62, 0x6c, 0x65, 0x18, 0x16, 0x20, 0x01,
+ 0x28, 0x08, 0x52, 0x07, 0x76, 0x69, 0x73, 0x69, 0x62, 0x6c, 0x65, 0x12,
+ 0x39, 0x0a, 0x19, 0x62, 0x65, 0x67, 0x69, 0x6e, 0x5f, 0x66, 0x72, 0x61,
+ 0x6d, 0x65, 0x5f, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x5f, 0x70, 0x61,
+ 0x75, 0x73, 0x65, 0x64, 0x18, 0x17, 0x20, 0x01, 0x28, 0x08, 0x52, 0x16,
+ 0x62, 0x65, 0x67, 0x69, 0x6e, 0x46, 0x72, 0x61, 0x6d, 0x65, 0x53, 0x6f,
+ 0x75, 0x72, 0x63, 0x65, 0x50, 0x61, 0x75, 0x73, 0x65, 0x64, 0x12, 0x19,
+ 0x0a, 0x08, 0x63, 0x61, 0x6e, 0x5f, 0x64, 0x72, 0x61, 0x77, 0x18, 0x18,
+ 0x20, 0x01, 0x28, 0x08, 0x52, 0x07, 0x63, 0x61, 0x6e, 0x44, 0x72, 0x61,
+ 0x77, 0x12, 0x2b, 0x0a, 0x11, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63,
+ 0x65, 0x6c, 0x65, 0x73, 0x73, 0x5f, 0x64, 0x72, 0x61, 0x77, 0x18, 0x19,
+ 0x20, 0x01, 0x28, 0x08, 0x52, 0x10, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72,
+ 0x63, 0x65, 0x6c, 0x65, 0x73, 0x73, 0x44, 0x72, 0x61, 0x77, 0x12, 0x28,
+ 0x0a, 0x10, 0x68, 0x61, 0x73, 0x5f, 0x70, 0x65, 0x6e, 0x64, 0x69, 0x6e,
+ 0x67, 0x5f, 0x74, 0x72, 0x65, 0x65, 0x18, 0x1a, 0x20, 0x01, 0x28, 0x08,
+ 0x52, 0x0e, 0x68, 0x61, 0x73, 0x50, 0x65, 0x6e, 0x64, 0x69, 0x6e, 0x67,
+ 0x54, 0x72, 0x65, 0x65, 0x12, 0x4d, 0x0a, 0x24, 0x70, 0x65, 0x6e, 0x64,
+ 0x69, 0x6e, 0x67, 0x5f, 0x74, 0x72, 0x65, 0x65, 0x5f, 0x69, 0x73, 0x5f,
+ 0x72, 0x65, 0x61, 0x64, 0x79, 0x5f, 0x66, 0x6f, 0x72, 0x5f, 0x61, 0x63,
+ 0x74, 0x69, 0x76, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x1b, 0x20, 0x01,
+ 0x28, 0x08, 0x52, 0x1f, 0x70, 0x65, 0x6e, 0x64, 0x69, 0x6e, 0x67, 0x54,
+ 0x72, 0x65, 0x65, 0x49, 0x73, 0x52, 0x65, 0x61, 0x64, 0x79, 0x46, 0x6f,
+ 0x72, 0x41, 0x63, 0x74, 0x69, 0x76, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12,
+ 0x3e, 0x0a, 0x1c, 0x61, 0x63, 0x74, 0x69, 0x76, 0x65, 0x5f, 0x74, 0x72,
+ 0x65, 0x65, 0x5f, 0x6e, 0x65, 0x65, 0x64, 0x73, 0x5f, 0x66, 0x69, 0x72,
+ 0x73, 0x74, 0x5f, 0x64, 0x72, 0x61, 0x77, 0x18, 0x1c, 0x20, 0x01, 0x28,
+ 0x08, 0x52, 0x18, 0x61, 0x63, 0x74, 0x69, 0x76, 0x65, 0x54, 0x72, 0x65,
+ 0x65, 0x4e, 0x65, 0x65, 0x64, 0x73, 0x46, 0x69, 0x72, 0x73, 0x74, 0x44,
+ 0x72, 0x61, 0x77, 0x12, 0x3d, 0x0a, 0x1c, 0x61, 0x63, 0x74, 0x69, 0x76,
+ 0x65, 0x5f, 0x74, 0x72, 0x65, 0x65, 0x5f, 0x69, 0x73, 0x5f, 0x72, 0x65,
+ 0x61, 0x64, 0x79, 0x5f, 0x74, 0x6f, 0x5f, 0x64, 0x72, 0x61, 0x77, 0x18,
+ 0x1d, 0x20, 0x01, 0x28, 0x08, 0x52, 0x17, 0x61, 0x63, 0x74, 0x69, 0x76,
+ 0x65, 0x54, 0x72, 0x65, 0x65, 0x49, 0x73, 0x52, 0x65, 0x61, 0x64, 0x79,
+ 0x54, 0x6f, 0x44, 0x72, 0x61, 0x77, 0x12, 0x6c, 0x0a, 0x35, 0x64, 0x69,
+ 0x64, 0x5f, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x5f, 0x61, 0x6e, 0x64,
+ 0x5f, 0x69, 0x6e, 0x69, 0x74, 0x69, 0x61, 0x6c, 0x69, 0x7a, 0x65, 0x5f,
+ 0x66, 0x69, 0x72, 0x73, 0x74, 0x5f, 0x6c, 0x61, 0x79, 0x65, 0x72, 0x5f,
+ 0x74, 0x72, 0x65, 0x65, 0x5f, 0x66, 0x72, 0x61, 0x6d, 0x65, 0x5f, 0x73,
+ 0x69, 0x6e, 0x6b, 0x18, 0x1e, 0x20, 0x01, 0x28, 0x08, 0x52, 0x2d, 0x64,
+ 0x69, 0x64, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x41, 0x6e, 0x64, 0x49,
+ 0x6e, 0x69, 0x74, 0x69, 0x61, 0x6c, 0x69, 0x7a, 0x65, 0x46, 0x69, 0x72,
+ 0x73, 0x74, 0x4c, 0x61, 0x79, 0x65, 0x72, 0x54, 0x72, 0x65, 0x65, 0x46,
+ 0x72, 0x61, 0x6d, 0x65, 0x53, 0x69, 0x6e, 0x6b, 0x12, 0x6a, 0x0a, 0x0d,
+ 0x74, 0x72, 0x65, 0x65, 0x5f, 0x70, 0x72, 0x69, 0x6f, 0x72, 0x69, 0x74,
+ 0x79, 0x18, 0x1f, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x45, 0x2e, 0x70, 0x65,
0x72, 0x66, 0x65, 0x74, 0x74, 0x6f, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f,
0x73, 0x2e, 0x43, 0x68, 0x72, 0x6f, 0x6d, 0x65, 0x43, 0x6f, 0x6d, 0x70,
0x6f, 0x73, 0x69, 0x74, 0x6f, 0x72, 0x53, 0x74, 0x61, 0x74, 0x65, 0x4d,
0x61, 0x63, 0x68, 0x69, 0x6e, 0x65, 0x2e, 0x4d, 0x69, 0x6e, 0x6f, 0x72,
- 0x53, 0x74, 0x61, 0x74, 0x65, 0x52, 0x0a, 0x6d, 0x69, 0x6e, 0x6f, 0x72,
- 0x53, 0x74, 0x61, 0x74, 0x65, 0x1a, 0xf9, 0x0a, 0x0a, 0x0a, 0x4d, 0x61,
- 0x6a, 0x6f, 0x72, 0x53, 0x74, 0x61, 0x74, 0x65, 0x12, 0x51, 0x0a, 0x0b,
- 0x6e, 0x65, 0x78, 0x74, 0x5f, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x18,
- 0x01, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x30, 0x2e, 0x70, 0x65, 0x72, 0x66,
- 0x65, 0x74, 0x74, 0x6f, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2e,
- 0x43, 0x68, 0x72, 0x6f, 0x6d, 0x65, 0x43, 0x6f, 0x6d, 0x70, 0x6f, 0x73,
- 0x69, 0x74, 0x6f, 0x72, 0x53, 0x63, 0x68, 0x65, 0x64, 0x75, 0x6c, 0x65,
- 0x72, 0x41, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x0a, 0x6e, 0x65, 0x78,
- 0x74, 0x41, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x81, 0x01, 0x0a, 0x16,
- 0x62, 0x65, 0x67, 0x69, 0x6e, 0x5f, 0x69, 0x6d, 0x70, 0x6c, 0x5f, 0x66,
- 0x72, 0x61, 0x6d, 0x65, 0x5f, 0x73, 0x74, 0x61, 0x74, 0x65, 0x18, 0x02,
- 0x20, 0x01, 0x28, 0x0e, 0x32, 0x4c, 0x2e, 0x70, 0x65, 0x72, 0x66, 0x65,
- 0x74, 0x74, 0x6f, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2e, 0x43,
- 0x68, 0x72, 0x6f, 0x6d, 0x65, 0x43, 0x6f, 0x6d, 0x70, 0x6f, 0x73, 0x69,
- 0x74, 0x6f, 0x72, 0x53, 0x74, 0x61, 0x74, 0x65, 0x4d, 0x61, 0x63, 0x68,
- 0x69, 0x6e, 0x65, 0x2e, 0x4d, 0x61, 0x6a, 0x6f, 0x72, 0x53, 0x74, 0x61,
- 0x74, 0x65, 0x2e, 0x42, 0x65, 0x67, 0x69, 0x6e, 0x49, 0x6d, 0x70, 0x6c,
- 0x46, 0x72, 0x61, 0x6d, 0x65, 0x53, 0x74, 0x61, 0x74, 0x65, 0x52, 0x13,
- 0x62, 0x65, 0x67, 0x69, 0x6e, 0x49, 0x6d, 0x70, 0x6c, 0x46, 0x72, 0x61,
- 0x6d, 0x65, 0x53, 0x74, 0x61, 0x74, 0x65, 0x12, 0x81, 0x01, 0x0a, 0x16,
- 0x62, 0x65, 0x67, 0x69, 0x6e, 0x5f, 0x6d, 0x61, 0x69, 0x6e, 0x5f, 0x66,
- 0x72, 0x61, 0x6d, 0x65, 0x5f, 0x73, 0x74, 0x61, 0x74, 0x65, 0x18, 0x03,
- 0x20, 0x01, 0x28, 0x0e, 0x32, 0x4c, 0x2e, 0x70, 0x65, 0x72, 0x66, 0x65,
- 0x74, 0x74, 0x6f, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2e, 0x43,
- 0x68, 0x72, 0x6f, 0x6d, 0x65, 0x43, 0x6f, 0x6d, 0x70, 0x6f, 0x73, 0x69,
- 0x74, 0x6f, 0x72, 0x53, 0x74, 0x61, 0x74, 0x65, 0x4d, 0x61, 0x63, 0x68,
- 0x69, 0x6e, 0x65, 0x2e, 0x4d, 0x61, 0x6a, 0x6f, 0x72, 0x53, 0x74, 0x61,
- 0x74, 0x65, 0x2e, 0x42, 0x65, 0x67, 0x69, 0x6e, 0x4d, 0x61, 0x69, 0x6e,
- 0x46, 0x72, 0x61, 0x6d, 0x65, 0x53, 0x74, 0x61, 0x74, 0x65, 0x52, 0x13,
- 0x62, 0x65, 0x67, 0x69, 0x6e, 0x4d, 0x61, 0x69, 0x6e, 0x46, 0x72, 0x61,
- 0x6d, 0x65, 0x53, 0x74, 0x61, 0x74, 0x65, 0x12, 0x8e, 0x01, 0x0a, 0x1b,
- 0x6c, 0x61, 0x79, 0x65, 0x72, 0x5f, 0x74, 0x72, 0x65, 0x65, 0x5f, 0x66,
- 0x72, 0x61, 0x6d, 0x65, 0x5f, 0x73, 0x69, 0x6e, 0x6b, 0x5f, 0x73, 0x74,
- 0x61, 0x74, 0x65, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x50, 0x2e,
- 0x70, 0x65, 0x72, 0x66, 0x65, 0x74, 0x74, 0x6f, 0x2e, 0x70, 0x72, 0x6f,
- 0x74, 0x6f, 0x73, 0x2e, 0x43, 0x68, 0x72, 0x6f, 0x6d, 0x65, 0x43, 0x6f,
- 0x6d, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x6f, 0x72, 0x53, 0x74, 0x61, 0x74,
- 0x65, 0x4d, 0x61, 0x63, 0x68, 0x69, 0x6e, 0x65, 0x2e, 0x4d, 0x61, 0x6a,
- 0x6f, 0x72, 0x53, 0x74, 0x61, 0x74, 0x65, 0x2e, 0x4c, 0x61, 0x79, 0x65,
- 0x72, 0x54, 0x72, 0x65, 0x65, 0x46, 0x72, 0x61, 0x6d, 0x65, 0x53, 0x69,
- 0x6e, 0x6b, 0x53, 0x74, 0x61, 0x74, 0x65, 0x52, 0x17, 0x6c, 0x61, 0x79,
- 0x65, 0x72, 0x54, 0x72, 0x65, 0x65, 0x46, 0x72, 0x61, 0x6d, 0x65, 0x53,
- 0x69, 0x6e, 0x6b, 0x53, 0x74, 0x61, 0x74, 0x65, 0x12, 0x83, 0x01, 0x0a,
- 0x13, 0x66, 0x6f, 0x72, 0x63, 0x65, 0x64, 0x5f, 0x72, 0x65, 0x64, 0x72,
- 0x61, 0x77, 0x5f, 0x73, 0x74, 0x61, 0x74, 0x65, 0x18, 0x05, 0x20, 0x01,
- 0x28, 0x0e, 0x32, 0x53, 0x2e, 0x70, 0x65, 0x72, 0x66, 0x65, 0x74, 0x74,
+ 0x53, 0x74, 0x61, 0x74, 0x65, 0x2e, 0x54, 0x72, 0x65, 0x65, 0x50, 0x72,
+ 0x69, 0x6f, 0x72, 0x69, 0x74, 0x79, 0x52, 0x0c, 0x74, 0x72, 0x65, 0x65,
+ 0x50, 0x72, 0x69, 0x6f, 0x72, 0x69, 0x74, 0x79, 0x12, 0x7d, 0x0a, 0x14,
+ 0x73, 0x63, 0x72, 0x6f, 0x6c, 0x6c, 0x5f, 0x68, 0x61, 0x6e, 0x64, 0x6c,
+ 0x65, 0x72, 0x5f, 0x73, 0x74, 0x61, 0x74, 0x65, 0x18, 0x20, 0x20, 0x01,
+ 0x28, 0x0e, 0x32, 0x4b, 0x2e, 0x70, 0x65, 0x72, 0x66, 0x65, 0x74, 0x74,
0x6f, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2e, 0x43, 0x68, 0x72,
0x6f, 0x6d, 0x65, 0x43, 0x6f, 0x6d, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x6f,
0x72, 0x53, 0x74, 0x61, 0x74, 0x65, 0x4d, 0x61, 0x63, 0x68, 0x69, 0x6e,
- 0x65, 0x2e, 0x4d, 0x61, 0x6a, 0x6f, 0x72, 0x53, 0x74, 0x61, 0x74, 0x65,
- 0x2e, 0x46, 0x6f, 0x72, 0x63, 0x65, 0x64, 0x52, 0x65, 0x64, 0x72, 0x61,
- 0x77, 0x4f, 0x6e, 0x54, 0x69, 0x6d, 0x65, 0x6f, 0x75, 0x74, 0x53, 0x74,
- 0x61, 0x74, 0x65, 0x52, 0x11, 0x66, 0x6f, 0x72, 0x63, 0x65, 0x64, 0x52,
- 0x65, 0x64, 0x72, 0x61, 0x77, 0x53, 0x74, 0x61, 0x74, 0x65, 0x22, 0xa1,
- 0x01, 0x0a, 0x13, 0x42, 0x65, 0x67, 0x69, 0x6e, 0x49, 0x6d, 0x70, 0x6c,
- 0x46, 0x72, 0x61, 0x6d, 0x65, 0x53, 0x74, 0x61, 0x74, 0x65, 0x12, 0x20,
- 0x0a, 0x1c, 0x42, 0x45, 0x47, 0x49, 0x4e, 0x5f, 0x49, 0x4d, 0x50, 0x4c,
- 0x5f, 0x46, 0x52, 0x41, 0x4d, 0x45, 0x5f, 0x55, 0x4e, 0x53, 0x50, 0x45,
- 0x43, 0x49, 0x46, 0x49, 0x45, 0x44, 0x10, 0x00, 0x12, 0x19, 0x0a, 0x15,
- 0x42, 0x45, 0x47, 0x49, 0x4e, 0x5f, 0x49, 0x4d, 0x50, 0x4c, 0x5f, 0x46,
- 0x52, 0x41, 0x4d, 0x45, 0x5f, 0x49, 0x44, 0x4c, 0x45, 0x10, 0x01, 0x12,
- 0x27, 0x0a, 0x23, 0x42, 0x45, 0x47, 0x49, 0x4e, 0x5f, 0x49, 0x4d, 0x50,
- 0x4c, 0x5f, 0x46, 0x52, 0x41, 0x4d, 0x45, 0x5f, 0x49, 0x4e, 0x53, 0x49,
- 0x44, 0x45, 0x5f, 0x42, 0x45, 0x47, 0x49, 0x4e, 0x5f, 0x46, 0x52, 0x41,
- 0x4d, 0x45, 0x10, 0x02, 0x12, 0x24, 0x0a, 0x20, 0x42, 0x45, 0x47, 0x49,
- 0x4e, 0x5f, 0x49, 0x4d, 0x50, 0x4c, 0x5f, 0x46, 0x52, 0x41, 0x4d, 0x45,
- 0x5f, 0x49, 0x4e, 0x53, 0x49, 0x44, 0x45, 0x5f, 0x44, 0x45, 0x41, 0x44,
- 0x4c, 0x49, 0x4e, 0x45, 0x10, 0x03, 0x22, 0x93, 0x01, 0x0a, 0x13, 0x42,
+ 0x65, 0x2e, 0x4d, 0x69, 0x6e, 0x6f, 0x72, 0x53, 0x74, 0x61, 0x74, 0x65,
+ 0x2e, 0x53, 0x63, 0x72, 0x6f, 0x6c, 0x6c, 0x48, 0x61, 0x6e, 0x64, 0x6c,
+ 0x65, 0x72, 0x53, 0x74, 0x61, 0x74, 0x65, 0x52, 0x12, 0x73, 0x63, 0x72,
+ 0x6f, 0x6c, 0x6c, 0x48, 0x61, 0x6e, 0x64, 0x6c, 0x65, 0x72, 0x53, 0x74,
+ 0x61, 0x74, 0x65, 0x12, 0x5d, 0x0a, 0x2d, 0x63, 0x72, 0x69, 0x74, 0x69,
+ 0x63, 0x61, 0x6c, 0x5f, 0x62, 0x65, 0x67, 0x69, 0x6e, 0x5f, 0x6d, 0x61,
+ 0x69, 0x6e, 0x5f, 0x66, 0x72, 0x61, 0x6d, 0x65, 0x5f, 0x74, 0x6f, 0x5f,
+ 0x61, 0x63, 0x74, 0x69, 0x76, 0x61, 0x74, 0x65, 0x5f, 0x69, 0x73, 0x5f,
+ 0x66, 0x61, 0x73, 0x74, 0x18, 0x21, 0x20, 0x01, 0x28, 0x08, 0x52, 0x26,
+ 0x63, 0x72, 0x69, 0x74, 0x69, 0x63, 0x61, 0x6c, 0x42, 0x65, 0x67, 0x69,
+ 0x6e, 0x4d, 0x61, 0x69, 0x6e, 0x46, 0x72, 0x61, 0x6d, 0x65, 0x54, 0x6f,
+ 0x41, 0x63, 0x74, 0x69, 0x76, 0x61, 0x74, 0x65, 0x49, 0x73, 0x46, 0x61,
+ 0x73, 0x74, 0x12, 0x46, 0x0a, 0x20, 0x6d, 0x61, 0x69, 0x6e, 0x5f, 0x74,
+ 0x68, 0x72, 0x65, 0x61, 0x64, 0x5f, 0x6d, 0x69, 0x73, 0x73, 0x65, 0x64,
+ 0x5f, 0x6c, 0x61, 0x73, 0x74, 0x5f, 0x64, 0x65, 0x61, 0x64, 0x6c, 0x69,
+ 0x6e, 0x65, 0x18, 0x22, 0x20, 0x01, 0x28, 0x08, 0x52, 0x1c, 0x6d, 0x61,
+ 0x69, 0x6e, 0x54, 0x68, 0x72, 0x65, 0x61, 0x64, 0x4d, 0x69, 0x73, 0x73,
+ 0x65, 0x64, 0x4c, 0x61, 0x73, 0x74, 0x44, 0x65, 0x61, 0x64, 0x6c, 0x69,
+ 0x6e, 0x65, 0x12, 0x5b, 0x0a, 0x2c, 0x73, 0x6b, 0x69, 0x70, 0x5f, 0x6e,
+ 0x65, 0x78, 0x74, 0x5f, 0x62, 0x65, 0x67, 0x69, 0x6e, 0x5f, 0x6d, 0x61,
+ 0x69, 0x6e, 0x5f, 0x66, 0x72, 0x61, 0x6d, 0x65, 0x5f, 0x74, 0x6f, 0x5f,
+ 0x72, 0x65, 0x64, 0x75, 0x63, 0x65, 0x5f, 0x6c, 0x61, 0x74, 0x65, 0x6e,
+ 0x63, 0x79, 0x18, 0x23, 0x20, 0x01, 0x28, 0x08, 0x52, 0x25, 0x73, 0x6b,
+ 0x69, 0x70, 0x4e, 0x65, 0x78, 0x74, 0x42, 0x65, 0x67, 0x69, 0x6e, 0x4d,
+ 0x61, 0x69, 0x6e, 0x46, 0x72, 0x61, 0x6d, 0x65, 0x54, 0x6f, 0x52, 0x65,
+ 0x64, 0x75, 0x63, 0x65, 0x4c, 0x61, 0x74, 0x65, 0x6e, 0x63, 0x79, 0x12,
+ 0x37, 0x0a, 0x18, 0x76, 0x69, 0x64, 0x65, 0x6f, 0x5f, 0x6e, 0x65, 0x65,
+ 0x64, 0x73, 0x5f, 0x62, 0x65, 0x67, 0x69, 0x6e, 0x5f, 0x66, 0x72, 0x61,
+ 0x6d, 0x65, 0x73, 0x18, 0x24, 0x20, 0x01, 0x28, 0x08, 0x52, 0x15, 0x76,
+ 0x69, 0x64, 0x65, 0x6f, 0x4e, 0x65, 0x65, 0x64, 0x73, 0x42, 0x65, 0x67,
+ 0x69, 0x6e, 0x46, 0x72, 0x61, 0x6d, 0x65, 0x73, 0x12, 0x33, 0x0a, 0x16,
+ 0x64, 0x65, 0x66, 0x65, 0x72, 0x5f, 0x62, 0x65, 0x67, 0x69, 0x6e, 0x5f,
+ 0x6d, 0x61, 0x69, 0x6e, 0x5f, 0x66, 0x72, 0x61, 0x6d, 0x65, 0x18, 0x25,
+ 0x20, 0x01, 0x28, 0x08, 0x52, 0x13, 0x64, 0x65, 0x66, 0x65, 0x72, 0x42,
0x65, 0x67, 0x69, 0x6e, 0x4d, 0x61, 0x69, 0x6e, 0x46, 0x72, 0x61, 0x6d,
- 0x65, 0x53, 0x74, 0x61, 0x74, 0x65, 0x12, 0x20, 0x0a, 0x1c, 0x42, 0x45,
- 0x47, 0x49, 0x4e, 0x5f, 0x4d, 0x41, 0x49, 0x4e, 0x5f, 0x46, 0x52, 0x41,
- 0x4d, 0x45, 0x5f, 0x55, 0x4e, 0x53, 0x50, 0x45, 0x43, 0x49, 0x46, 0x49,
- 0x45, 0x44, 0x10, 0x00, 0x12, 0x19, 0x0a, 0x15, 0x42, 0x45, 0x47, 0x49,
- 0x4e, 0x5f, 0x4d, 0x41, 0x49, 0x4e, 0x5f, 0x46, 0x52, 0x41, 0x4d, 0x45,
- 0x5f, 0x49, 0x44, 0x4c, 0x45, 0x10, 0x01, 0x12, 0x19, 0x0a, 0x15, 0x42,
- 0x45, 0x47, 0x49, 0x4e, 0x5f, 0x4d, 0x41, 0x49, 0x4e, 0x5f, 0x46, 0x52,
- 0x41, 0x4d, 0x45, 0x5f, 0x53, 0x45, 0x4e, 0x54, 0x10, 0x02, 0x12, 0x24,
- 0x0a, 0x20, 0x42, 0x45, 0x47, 0x49, 0x4e, 0x5f, 0x4d, 0x41, 0x49, 0x4e,
- 0x5f, 0x46, 0x52, 0x41, 0x4d, 0x45, 0x5f, 0x52, 0x45, 0x41, 0x44, 0x59,
- 0x5f, 0x54, 0x4f, 0x5f, 0x43, 0x4f, 0x4d, 0x4d, 0x49, 0x54, 0x10, 0x03,
- 0x22, 0xf4, 0x01, 0x0a, 0x17, 0x4c, 0x61, 0x79, 0x65, 0x72, 0x54, 0x72,
- 0x65, 0x65, 0x46, 0x72, 0x61, 0x6d, 0x65, 0x53, 0x69, 0x6e, 0x6b, 0x53,
- 0x74, 0x61, 0x74, 0x65, 0x12, 0x20, 0x0a, 0x1c, 0x4c, 0x41, 0x59, 0x45,
- 0x52, 0x5f, 0x54, 0x52, 0x45, 0x45, 0x5f, 0x46, 0x52, 0x41, 0x4d, 0x45,
- 0x5f, 0x55, 0x4e, 0x53, 0x50, 0x45, 0x43, 0x49, 0x46, 0x49, 0x45, 0x44,
- 0x10, 0x00, 0x12, 0x19, 0x0a, 0x15, 0x4c, 0x41, 0x59, 0x45, 0x52, 0x5f,
- 0x54, 0x52, 0x45, 0x45, 0x5f, 0x46, 0x52, 0x41, 0x4d, 0x45, 0x5f, 0x4e,
- 0x4f, 0x4e, 0x45, 0x10, 0x01, 0x12, 0x1b, 0x0a, 0x17, 0x4c, 0x41, 0x59,
- 0x45, 0x52, 0x5f, 0x54, 0x52, 0x45, 0x45, 0x5f, 0x46, 0x52, 0x41, 0x4d,
- 0x45, 0x5f, 0x41, 0x43, 0x54, 0x49, 0x56, 0x45, 0x10, 0x02, 0x12, 0x1d,
- 0x0a, 0x19, 0x4c, 0x41, 0x59, 0x45, 0x52, 0x5f, 0x54, 0x52, 0x45, 0x45,
- 0x5f, 0x46, 0x52, 0x41, 0x4d, 0x45, 0x5f, 0x43, 0x52, 0x45, 0x41, 0x54,
- 0x49, 0x4e, 0x47, 0x10, 0x03, 0x12, 0x2d, 0x0a, 0x29, 0x4c, 0x41, 0x59,
- 0x45, 0x52, 0x5f, 0x54, 0x52, 0x45, 0x45, 0x5f, 0x46, 0x52, 0x41, 0x4d,
- 0x45, 0x5f, 0x57, 0x41, 0x49, 0x54, 0x49, 0x4e, 0x47, 0x5f, 0x46, 0x4f,
- 0x52, 0x5f, 0x46, 0x49, 0x52, 0x53, 0x54, 0x5f, 0x43, 0x4f, 0x4d, 0x4d,
- 0x49, 0x54, 0x10, 0x04, 0x12, 0x31, 0x0a, 0x2d, 0x4c, 0x41, 0x59, 0x45,
- 0x52, 0x5f, 0x54, 0x52, 0x45, 0x45, 0x5f, 0x46, 0x52, 0x41, 0x4d, 0x45,
- 0x5f, 0x57, 0x41, 0x49, 0x54, 0x49, 0x4e, 0x47, 0x5f, 0x46, 0x4f, 0x52,
- 0x5f, 0x46, 0x49, 0x52, 0x53, 0x54, 0x5f, 0x41, 0x43, 0x54, 0x49, 0x56,
- 0x41, 0x54, 0x49, 0x4f, 0x4e, 0x10, 0x05, 0x22, 0xc7, 0x01, 0x0a, 0x1a,
- 0x46, 0x6f, 0x72, 0x63, 0x65, 0x64, 0x52, 0x65, 0x64, 0x72, 0x61, 0x77,
- 0x4f, 0x6e, 0x54, 0x69, 0x6d, 0x65, 0x6f, 0x75, 0x74, 0x53, 0x74, 0x61,
- 0x74, 0x65, 0x12, 0x1d, 0x0a, 0x19, 0x46, 0x4f, 0x52, 0x43, 0x45, 0x44,
- 0x5f, 0x52, 0x45, 0x44, 0x52, 0x41, 0x57, 0x5f, 0x55, 0x4e, 0x53, 0x50,
- 0x45, 0x43, 0x49, 0x46, 0x49, 0x45, 0x44, 0x10, 0x00, 0x12, 0x16, 0x0a,
- 0x12, 0x46, 0x4f, 0x52, 0x43, 0x45, 0x44, 0x5f, 0x52, 0x45, 0x44, 0x52,
- 0x41, 0x57, 0x5f, 0x49, 0x44, 0x4c, 0x45, 0x10, 0x01, 0x12, 0x24, 0x0a,
- 0x20, 0x46, 0x4f, 0x52, 0x43, 0x45, 0x44, 0x5f, 0x52, 0x45, 0x44, 0x52,
- 0x41, 0x57, 0x5f, 0x57, 0x41, 0x49, 0x54, 0x49, 0x4e, 0x47, 0x5f, 0x46,
- 0x4f, 0x52, 0x5f, 0x43, 0x4f, 0x4d, 0x4d, 0x49, 0x54, 0x10, 0x02, 0x12,
- 0x28, 0x0a, 0x24, 0x46, 0x4f, 0x52, 0x43, 0x45, 0x44, 0x5f, 0x52, 0x45,
- 0x44, 0x52, 0x41, 0x57, 0x5f, 0x57, 0x41, 0x49, 0x54, 0x49, 0x4e, 0x47,
- 0x5f, 0x46, 0x4f, 0x52, 0x5f, 0x41, 0x43, 0x54, 0x49, 0x56, 0x41, 0x54,
- 0x49, 0x4f, 0x4e, 0x10, 0x03, 0x12, 0x22, 0x0a, 0x1e, 0x46, 0x4f, 0x52,
- 0x43, 0x45, 0x44, 0x5f, 0x52, 0x45, 0x44, 0x52, 0x41, 0x57, 0x5f, 0x57,
- 0x41, 0x49, 0x54, 0x49, 0x4e, 0x47, 0x5f, 0x46, 0x4f, 0x52, 0x5f, 0x44,
- 0x52, 0x41, 0x57, 0x10, 0x04, 0x1a, 0xb3, 0x1b, 0x0a, 0x0a, 0x4d, 0x69,
- 0x6e, 0x6f, 0x72, 0x53, 0x74, 0x61, 0x74, 0x65, 0x12, 0x21, 0x0a, 0x0c,
- 0x63, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x5f, 0x63, 0x6f, 0x75, 0x6e, 0x74,
- 0x18, 0x01, 0x20, 0x01, 0x28, 0x05, 0x52, 0x0b, 0x63, 0x6f, 0x6d, 0x6d,
- 0x69, 0x74, 0x43, 0x6f, 0x75, 0x6e, 0x74, 0x12, 0x30, 0x0a, 0x14, 0x63,
- 0x75, 0x72, 0x72, 0x65, 0x6e, 0x74, 0x5f, 0x66, 0x72, 0x61, 0x6d, 0x65,
- 0x5f, 0x6e, 0x75, 0x6d, 0x62, 0x65, 0x72, 0x18, 0x02, 0x20, 0x01, 0x28,
- 0x05, 0x52, 0x12, 0x63, 0x75, 0x72, 0x72, 0x65, 0x6e, 0x74, 0x46, 0x72,
- 0x61, 0x6d, 0x65, 0x4e, 0x75, 0x6d, 0x62, 0x65, 0x72, 0x12, 0x4a, 0x0a,
- 0x22, 0x6c, 0x61, 0x73, 0x74, 0x5f, 0x66, 0x72, 0x61, 0x6d, 0x65, 0x5f,
- 0x6e, 0x75, 0x6d, 0x62, 0x65, 0x72, 0x5f, 0x73, 0x75, 0x62, 0x6d, 0x69,
- 0x74, 0x5f, 0x70, 0x65, 0x72, 0x66, 0x6f, 0x72, 0x6d, 0x65, 0x64, 0x18,
- 0x03, 0x20, 0x01, 0x28, 0x05, 0x52, 0x1e, 0x6c, 0x61, 0x73, 0x74, 0x46,
- 0x72, 0x61, 0x6d, 0x65, 0x4e, 0x75, 0x6d, 0x62, 0x65, 0x72, 0x53, 0x75,
- 0x62, 0x6d, 0x69, 0x74, 0x50, 0x65, 0x72, 0x66, 0x6f, 0x72, 0x6d, 0x65,
- 0x64, 0x12, 0x46, 0x0a, 0x20, 0x6c, 0x61, 0x73, 0x74, 0x5f, 0x66, 0x72,
- 0x61, 0x6d, 0x65, 0x5f, 0x6e, 0x75, 0x6d, 0x62, 0x65, 0x72, 0x5f, 0x64,
- 0x72, 0x61, 0x77, 0x5f, 0x70, 0x65, 0x72, 0x66, 0x6f, 0x72, 0x6d, 0x65,
- 0x64, 0x18, 0x04, 0x20, 0x01, 0x28, 0x05, 0x52, 0x1c, 0x6c, 0x61, 0x73,
- 0x74, 0x46, 0x72, 0x61, 0x6d, 0x65, 0x4e, 0x75, 0x6d, 0x62, 0x65, 0x72,
- 0x44, 0x72, 0x61, 0x77, 0x50, 0x65, 0x72, 0x66, 0x6f, 0x72, 0x6d, 0x65,
- 0x64, 0x12, 0x52, 0x0a, 0x27, 0x6c, 0x61, 0x73, 0x74, 0x5f, 0x66, 0x72,
- 0x61, 0x6d, 0x65, 0x5f, 0x6e, 0x75, 0x6d, 0x62, 0x65, 0x72, 0x5f, 0x62,
- 0x65, 0x67, 0x69, 0x6e, 0x5f, 0x6d, 0x61, 0x69, 0x6e, 0x5f, 0x66, 0x72,
- 0x61, 0x6d, 0x65, 0x5f, 0x73, 0x65, 0x6e, 0x74, 0x18, 0x05, 0x20, 0x01,
- 0x28, 0x05, 0x52, 0x21, 0x6c, 0x61, 0x73, 0x74, 0x46, 0x72, 0x61, 0x6d,
- 0x65, 0x4e, 0x75, 0x6d, 0x62, 0x65, 0x72, 0x42, 0x65, 0x67, 0x69, 0x6e,
- 0x4d, 0x61, 0x69, 0x6e, 0x46, 0x72, 0x61, 0x6d, 0x65, 0x53, 0x65, 0x6e,
- 0x74, 0x12, 0x19, 0x0a, 0x08, 0x64, 0x69, 0x64, 0x5f, 0x64, 0x72, 0x61,
- 0x77, 0x18, 0x06, 0x20, 0x01, 0x28, 0x08, 0x52, 0x07, 0x64, 0x69, 0x64,
- 0x44, 0x72, 0x61, 0x77, 0x12, 0x59, 0x0a, 0x2b, 0x64, 0x69, 0x64, 0x5f,
- 0x73, 0x65, 0x6e, 0x64, 0x5f, 0x62, 0x65, 0x67, 0x69, 0x6e, 0x5f, 0x6d,
- 0x61, 0x69, 0x6e, 0x5f, 0x66, 0x72, 0x61, 0x6d, 0x65, 0x5f, 0x66, 0x6f,
- 0x72, 0x5f, 0x63, 0x75, 0x72, 0x72, 0x65, 0x6e, 0x74, 0x5f, 0x66, 0x72,
- 0x61, 0x6d, 0x65, 0x18, 0x07, 0x20, 0x01, 0x28, 0x08, 0x52, 0x24, 0x64,
- 0x69, 0x64, 0x53, 0x65, 0x6e, 0x64, 0x42, 0x65, 0x67, 0x69, 0x6e, 0x4d,
- 0x61, 0x69, 0x6e, 0x46, 0x72, 0x61, 0x6d, 0x65, 0x46, 0x6f, 0x72, 0x43,
- 0x75, 0x72, 0x72, 0x65, 0x6e, 0x74, 0x46, 0x72, 0x61, 0x6d, 0x65, 0x12,
- 0x5f, 0x0a, 0x2e, 0x64, 0x69, 0x64, 0x5f, 0x6e, 0x6f, 0x74, 0x69, 0x66,
- 0x79, 0x5f, 0x62, 0x65, 0x67, 0x69, 0x6e, 0x5f, 0x6d, 0x61, 0x69, 0x6e,
- 0x5f, 0x66, 0x72, 0x61, 0x6d, 0x65, 0x5f, 0x6e, 0x6f, 0x74, 0x5f, 0x65,
- 0x78, 0x70, 0x65, 0x63, 0x74, 0x65, 0x64, 0x5f, 0x75, 0x6e, 0x74, 0x69,
- 0x6c, 0x18, 0x08, 0x20, 0x01, 0x28, 0x08, 0x52, 0x27, 0x64, 0x69, 0x64,
- 0x4e, 0x6f, 0x74, 0x69, 0x66, 0x79, 0x42, 0x65, 0x67, 0x69, 0x6e, 0x4d,
- 0x61, 0x69, 0x6e, 0x46, 0x72, 0x61, 0x6d, 0x65, 0x4e, 0x6f, 0x74, 0x45,
- 0x78, 0x70, 0x65, 0x63, 0x74, 0x65, 0x64, 0x55, 0x6e, 0x74, 0x69, 0x6c,
- 0x12, 0x5d, 0x0a, 0x2d, 0x64, 0x69, 0x64, 0x5f, 0x6e, 0x6f, 0x74, 0x69,
- 0x66, 0x79, 0x5f, 0x62, 0x65, 0x67, 0x69, 0x6e, 0x5f, 0x6d, 0x61, 0x69,
- 0x6e, 0x5f, 0x66, 0x72, 0x61, 0x6d, 0x65, 0x5f, 0x6e, 0x6f, 0x74, 0x5f,
- 0x65, 0x78, 0x70, 0x65, 0x63, 0x74, 0x65, 0x64, 0x5f, 0x73, 0x6f, 0x6f,
- 0x6e, 0x18, 0x09, 0x20, 0x01, 0x28, 0x08, 0x52, 0x26, 0x64, 0x69, 0x64,
- 0x4e, 0x6f, 0x74, 0x69, 0x66, 0x79, 0x42, 0x65, 0x67, 0x69, 0x6e, 0x4d,
- 0x61, 0x69, 0x6e, 0x46, 0x72, 0x61, 0x6d, 0x65, 0x4e, 0x6f, 0x74, 0x45,
- 0x78, 0x70, 0x65, 0x63, 0x74, 0x65, 0x64, 0x53, 0x6f, 0x6f, 0x6e, 0x12,
- 0x4b, 0x0a, 0x23, 0x77, 0x61, 0x6e, 0x74, 0x73, 0x5f, 0x62, 0x65, 0x67,
- 0x69, 0x6e, 0x5f, 0x6d, 0x61, 0x69, 0x6e, 0x5f, 0x66, 0x72, 0x61, 0x6d,
- 0x65, 0x5f, 0x6e, 0x6f, 0x74, 0x5f, 0x65, 0x78, 0x70, 0x65, 0x63, 0x74,
- 0x65, 0x64, 0x18, 0x0a, 0x20, 0x01, 0x28, 0x08, 0x52, 0x1e, 0x77, 0x61,
- 0x6e, 0x74, 0x73, 0x42, 0x65, 0x67, 0x69, 0x6e, 0x4d, 0x61, 0x69, 0x6e,
- 0x46, 0x72, 0x61, 0x6d, 0x65, 0x4e, 0x6f, 0x74, 0x45, 0x78, 0x70, 0x65,
- 0x63, 0x74, 0x65, 0x64, 0x12, 0x35, 0x0a, 0x17, 0x64, 0x69, 0x64, 0x5f,
- 0x63, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x5f, 0x64, 0x75, 0x72, 0x69, 0x6e,
- 0x67, 0x5f, 0x66, 0x72, 0x61, 0x6d, 0x65, 0x18, 0x0b, 0x20, 0x01, 0x28,
- 0x08, 0x52, 0x14, 0x64, 0x69, 0x64, 0x43, 0x6f, 0x6d, 0x6d, 0x69, 0x74,
- 0x44, 0x75, 0x72, 0x69, 0x6e, 0x67, 0x46, 0x72, 0x61, 0x6d, 0x65, 0x12,
- 0x4d, 0x0a, 0x24, 0x64, 0x69, 0x64, 0x5f, 0x69, 0x6e, 0x76, 0x61, 0x6c,
- 0x69, 0x64, 0x61, 0x74, 0x65, 0x5f, 0x6c, 0x61, 0x79, 0x65, 0x72, 0x5f,
- 0x74, 0x72, 0x65, 0x65, 0x5f, 0x66, 0x72, 0x61, 0x6d, 0x65, 0x5f, 0x73,
- 0x69, 0x6e, 0x6b, 0x18, 0x0c, 0x20, 0x01, 0x28, 0x08, 0x52, 0x1f, 0x64,
- 0x69, 0x64, 0x49, 0x6e, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x65,
- 0x4c, 0x61, 0x79, 0x65, 0x72, 0x54, 0x72, 0x65, 0x65, 0x46, 0x72, 0x61,
- 0x6d, 0x65, 0x53, 0x69, 0x6e, 0x6b, 0x12, 0x48, 0x0a, 0x21, 0x64, 0x69,
- 0x64, 0x5f, 0x70, 0x65, 0x72, 0x66, 0x6f, 0x72, 0x6d, 0x5f, 0x69, 0x6d,
- 0x70, 0x6c, 0x5f, 0x73, 0x69, 0x64, 0x65, 0x5f, 0x69, 0x6e, 0x76, 0x61,
- 0x6c, 0x69, 0x64, 0x61, 0x69, 0x6f, 0x6e, 0x18, 0x0d, 0x20, 0x01, 0x28,
- 0x08, 0x52, 0x1d, 0x64, 0x69, 0x64, 0x50, 0x65, 0x72, 0x66, 0x6f, 0x72,
- 0x6d, 0x49, 0x6d, 0x70, 0x6c, 0x53, 0x69, 0x64, 0x65, 0x49, 0x6e, 0x76,
- 0x61, 0x6c, 0x69, 0x64, 0x61, 0x69, 0x6f, 0x6e, 0x12, 0x2a, 0x0a, 0x11,
- 0x64, 0x69, 0x64, 0x5f, 0x70, 0x72, 0x65, 0x70, 0x61, 0x72, 0x65, 0x5f,
- 0x74, 0x69, 0x6c, 0x65, 0x73, 0x18, 0x0e, 0x20, 0x01, 0x28, 0x08, 0x52,
- 0x0f, 0x64, 0x69, 0x64, 0x50, 0x72, 0x65, 0x70, 0x61, 0x72, 0x65, 0x54,
- 0x69, 0x6c, 0x65, 0x73, 0x12, 0x4e, 0x0a, 0x23, 0x63, 0x6f, 0x6e, 0x73,
- 0x65, 0x63, 0x75, 0x74, 0x69, 0x76, 0x65, 0x5f, 0x63, 0x68, 0x65, 0x63,
- 0x6b, 0x65, 0x72, 0x62, 0x6f, 0x61, 0x72, 0x64, 0x5f, 0x61, 0x6e, 0x69,
- 0x6d, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x18, 0x0f, 0x20, 0x01, 0x28,
- 0x05, 0x52, 0x21, 0x63, 0x6f, 0x6e, 0x73, 0x65, 0x63, 0x75, 0x74, 0x69,
- 0x76, 0x65, 0x43, 0x68, 0x65, 0x63, 0x6b, 0x65, 0x72, 0x62, 0x6f, 0x61,
- 0x72, 0x64, 0x41, 0x6e, 0x69, 0x6d, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73,
- 0x12, 0x32, 0x0a, 0x15, 0x70, 0x65, 0x6e, 0x64, 0x69, 0x6e, 0x67, 0x5f,
- 0x73, 0x75, 0x62, 0x6d, 0x69, 0x74, 0x5f, 0x66, 0x72, 0x61, 0x6d, 0x65,
- 0x73, 0x18, 0x10, 0x20, 0x01, 0x28, 0x05, 0x52, 0x13, 0x70, 0x65, 0x6e,
- 0x64, 0x69, 0x6e, 0x67, 0x53, 0x75, 0x62, 0x6d, 0x69, 0x74, 0x46, 0x72,
- 0x61, 0x6d, 0x65, 0x73, 0x12, 0x63, 0x0a, 0x30, 0x73, 0x75, 0x62, 0x6d,
- 0x69, 0x74, 0x5f, 0x66, 0x72, 0x61, 0x6d, 0x65, 0x73, 0x5f, 0x77, 0x69,
- 0x74, 0x68, 0x5f, 0x63, 0x75, 0x72, 0x72, 0x65, 0x6e, 0x74, 0x5f, 0x6c,
- 0x61, 0x79, 0x65, 0x72, 0x5f, 0x74, 0x72, 0x65, 0x65, 0x5f, 0x66, 0x72,
- 0x61, 0x6d, 0x65, 0x5f, 0x73, 0x69, 0x6e, 0x6b, 0x18, 0x11, 0x20, 0x01,
- 0x28, 0x05, 0x52, 0x29, 0x73, 0x75, 0x62, 0x6d, 0x69, 0x74, 0x46, 0x72,
- 0x61, 0x6d, 0x65, 0x73, 0x57, 0x69, 0x74, 0x68, 0x43, 0x75, 0x72, 0x72,
- 0x65, 0x6e, 0x74, 0x4c, 0x61, 0x79, 0x65, 0x72, 0x54, 0x72, 0x65, 0x65,
- 0x46, 0x72, 0x61, 0x6d, 0x65, 0x53, 0x69, 0x6e, 0x6b, 0x12, 0x21, 0x0a,
- 0x0c, 0x6e, 0x65, 0x65, 0x64, 0x73, 0x5f, 0x72, 0x65, 0x64, 0x72, 0x61,
- 0x77, 0x18, 0x12, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0b, 0x6e, 0x65, 0x65,
- 0x64, 0x73, 0x52, 0x65, 0x64, 0x72, 0x61, 0x77, 0x12, 0x2e, 0x0a, 0x13,
- 0x6e, 0x65, 0x65, 0x64, 0x73, 0x5f, 0x70, 0x72, 0x65, 0x70, 0x61, 0x72,
- 0x65, 0x5f, 0x74, 0x69, 0x6c, 0x65, 0x73, 0x18, 0x13, 0x20, 0x01, 0x28,
- 0x08, 0x52, 0x11, 0x6e, 0x65, 0x65, 0x64, 0x73, 0x50, 0x72, 0x65, 0x70,
- 0x61, 0x72, 0x65, 0x54, 0x69, 0x6c, 0x65, 0x73, 0x12, 0x33, 0x0a, 0x16,
- 0x6e, 0x65, 0x65, 0x64, 0x73, 0x5f, 0x62, 0x65, 0x67, 0x69, 0x6e, 0x5f,
- 0x6d, 0x61, 0x69, 0x6e, 0x5f, 0x66, 0x72, 0x61, 0x6d, 0x65, 0x18, 0x14,
- 0x20, 0x01, 0x28, 0x08, 0x52, 0x13, 0x6e, 0x65, 0x65, 0x64, 0x73, 0x42,
- 0x65, 0x67, 0x69, 0x6e, 0x4d, 0x61, 0x69, 0x6e, 0x46, 0x72, 0x61, 0x6d,
- 0x65, 0x12, 0x3a, 0x0a, 0x1a, 0x6e, 0x65, 0x65, 0x64, 0x73, 0x5f, 0x6f,
- 0x6e, 0x65, 0x5f, 0x62, 0x65, 0x67, 0x69, 0x6e, 0x5f, 0x69, 0x6d, 0x70,
- 0x6c, 0x5f, 0x66, 0x72, 0x61, 0x6d, 0x65, 0x18, 0x15, 0x20, 0x01, 0x28,
- 0x08, 0x52, 0x16, 0x6e, 0x65, 0x65, 0x64, 0x73, 0x4f, 0x6e, 0x65, 0x42,
- 0x65, 0x67, 0x69, 0x6e, 0x49, 0x6d, 0x70, 0x6c, 0x46, 0x72, 0x61, 0x6d,
- 0x65, 0x12, 0x18, 0x0a, 0x07, 0x76, 0x69, 0x73, 0x69, 0x62, 0x6c, 0x65,
- 0x18, 0x16, 0x20, 0x01, 0x28, 0x08, 0x52, 0x07, 0x76, 0x69, 0x73, 0x69,
- 0x62, 0x6c, 0x65, 0x12, 0x39, 0x0a, 0x19, 0x62, 0x65, 0x67, 0x69, 0x6e,
- 0x5f, 0x66, 0x72, 0x61, 0x6d, 0x65, 0x5f, 0x73, 0x6f, 0x75, 0x72, 0x63,
- 0x65, 0x5f, 0x70, 0x61, 0x75, 0x73, 0x65, 0x64, 0x18, 0x17, 0x20, 0x01,
- 0x28, 0x08, 0x52, 0x16, 0x62, 0x65, 0x67, 0x69, 0x6e, 0x46, 0x72, 0x61,
- 0x6d, 0x65, 0x53, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x50, 0x61, 0x75, 0x73,
- 0x65, 0x64, 0x12, 0x19, 0x0a, 0x08, 0x63, 0x61, 0x6e, 0x5f, 0x64, 0x72,
- 0x61, 0x77, 0x18, 0x18, 0x20, 0x01, 0x28, 0x08, 0x52, 0x07, 0x63, 0x61,
- 0x6e, 0x44, 0x72, 0x61, 0x77, 0x12, 0x2b, 0x0a, 0x11, 0x72, 0x65, 0x73,
- 0x6f, 0x75, 0x72, 0x63, 0x65, 0x6c, 0x65, 0x73, 0x73, 0x5f, 0x64, 0x72,
- 0x61, 0x77, 0x18, 0x19, 0x20, 0x01, 0x28, 0x08, 0x52, 0x10, 0x72, 0x65,
- 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x6c, 0x65, 0x73, 0x73, 0x44, 0x72,
- 0x61, 0x77, 0x12, 0x28, 0x0a, 0x10, 0x68, 0x61, 0x73, 0x5f, 0x70, 0x65,
- 0x6e, 0x64, 0x69, 0x6e, 0x67, 0x5f, 0x74, 0x72, 0x65, 0x65, 0x18, 0x1a,
- 0x20, 0x01, 0x28, 0x08, 0x52, 0x0e, 0x68, 0x61, 0x73, 0x50, 0x65, 0x6e,
- 0x64, 0x69, 0x6e, 0x67, 0x54, 0x72, 0x65, 0x65, 0x12, 0x4d, 0x0a, 0x24,
- 0x70, 0x65, 0x6e, 0x64, 0x69, 0x6e, 0x67, 0x5f, 0x74, 0x72, 0x65, 0x65,
- 0x5f, 0x69, 0x73, 0x5f, 0x72, 0x65, 0x61, 0x64, 0x79, 0x5f, 0x66, 0x6f,
- 0x72, 0x5f, 0x61, 0x63, 0x74, 0x69, 0x76, 0x61, 0x74, 0x69, 0x6f, 0x6e,
- 0x18, 0x1b, 0x20, 0x01, 0x28, 0x08, 0x52, 0x1f, 0x70, 0x65, 0x6e, 0x64,
- 0x69, 0x6e, 0x67, 0x54, 0x72, 0x65, 0x65, 0x49, 0x73, 0x52, 0x65, 0x61,
- 0x64, 0x79, 0x46, 0x6f, 0x72, 0x41, 0x63, 0x74, 0x69, 0x76, 0x61, 0x74,
- 0x69, 0x6f, 0x6e, 0x12, 0x3e, 0x0a, 0x1c, 0x61, 0x63, 0x74, 0x69, 0x76,
- 0x65, 0x5f, 0x74, 0x72, 0x65, 0x65, 0x5f, 0x6e, 0x65, 0x65, 0x64, 0x73,
- 0x5f, 0x66, 0x69, 0x72, 0x73, 0x74, 0x5f, 0x64, 0x72, 0x61, 0x77, 0x18,
- 0x1c, 0x20, 0x01, 0x28, 0x08, 0x52, 0x18, 0x61, 0x63, 0x74, 0x69, 0x76,
- 0x65, 0x54, 0x72, 0x65, 0x65, 0x4e, 0x65, 0x65, 0x64, 0x73, 0x46, 0x69,
- 0x72, 0x73, 0x74, 0x44, 0x72, 0x61, 0x77, 0x12, 0x3d, 0x0a, 0x1c, 0x61,
- 0x63, 0x74, 0x69, 0x76, 0x65, 0x5f, 0x74, 0x72, 0x65, 0x65, 0x5f, 0x69,
- 0x73, 0x5f, 0x72, 0x65, 0x61, 0x64, 0x79, 0x5f, 0x74, 0x6f, 0x5f, 0x64,
- 0x72, 0x61, 0x77, 0x18, 0x1d, 0x20, 0x01, 0x28, 0x08, 0x52, 0x17, 0x61,
- 0x63, 0x74, 0x69, 0x76, 0x65, 0x54, 0x72, 0x65, 0x65, 0x49, 0x73, 0x52,
- 0x65, 0x61, 0x64, 0x79, 0x54, 0x6f, 0x44, 0x72, 0x61, 0x77, 0x12, 0x6c,
- 0x0a, 0x35, 0x64, 0x69, 0x64, 0x5f, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65,
- 0x5f, 0x61, 0x6e, 0x64, 0x5f, 0x69, 0x6e, 0x69, 0x74, 0x69, 0x61, 0x6c,
- 0x69, 0x7a, 0x65, 0x5f, 0x66, 0x69, 0x72, 0x73, 0x74, 0x5f, 0x6c, 0x61,
- 0x79, 0x65, 0x72, 0x5f, 0x74, 0x72, 0x65, 0x65, 0x5f, 0x66, 0x72, 0x61,
- 0x6d, 0x65, 0x5f, 0x73, 0x69, 0x6e, 0x6b, 0x18, 0x1e, 0x20, 0x01, 0x28,
- 0x08, 0x52, 0x2d, 0x64, 0x69, 0x64, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65,
- 0x41, 0x6e, 0x64, 0x49, 0x6e, 0x69, 0x74, 0x69, 0x61, 0x6c, 0x69, 0x7a,
- 0x65, 0x46, 0x69, 0x72, 0x73, 0x74, 0x4c, 0x61, 0x79, 0x65, 0x72, 0x54,
- 0x72, 0x65, 0x65, 0x46, 0x72, 0x61, 0x6d, 0x65, 0x53, 0x69, 0x6e, 0x6b,
- 0x12, 0x6a, 0x0a, 0x0d, 0x74, 0x72, 0x65, 0x65, 0x5f, 0x70, 0x72, 0x69,
- 0x6f, 0x72, 0x69, 0x74, 0x79, 0x18, 0x1f, 0x20, 0x01, 0x28, 0x0e, 0x32,
- 0x45, 0x2e, 0x70, 0x65, 0x72, 0x66, 0x65, 0x74, 0x74, 0x6f, 0x2e, 0x70,
- 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2e, 0x43, 0x68, 0x72, 0x6f, 0x6d, 0x65,
- 0x43, 0x6f, 0x6d, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x6f, 0x72, 0x53, 0x74,
- 0x61, 0x74, 0x65, 0x4d, 0x61, 0x63, 0x68, 0x69, 0x6e, 0x65, 0x2e, 0x4d,
- 0x69, 0x6e, 0x6f, 0x72, 0x53, 0x74, 0x61, 0x74, 0x65, 0x2e, 0x54, 0x72,
- 0x65, 0x65, 0x50, 0x72, 0x69, 0x6f, 0x72, 0x69, 0x74, 0x79, 0x52, 0x0c,
- 0x74, 0x72, 0x65, 0x65, 0x50, 0x72, 0x69, 0x6f, 0x72, 0x69, 0x74, 0x79,
- 0x12, 0x7d, 0x0a, 0x14, 0x73, 0x63, 0x72, 0x6f, 0x6c, 0x6c, 0x5f, 0x68,
- 0x61, 0x6e, 0x64, 0x6c, 0x65, 0x72, 0x5f, 0x73, 0x74, 0x61, 0x74, 0x65,
- 0x18, 0x20, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x4b, 0x2e, 0x70, 0x65, 0x72,
- 0x66, 0x65, 0x74, 0x74, 0x6f, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73,
- 0x2e, 0x43, 0x68, 0x72, 0x6f, 0x6d, 0x65, 0x43, 0x6f, 0x6d, 0x70, 0x6f,
- 0x73, 0x69, 0x74, 0x6f, 0x72, 0x53, 0x74, 0x61, 0x74, 0x65, 0x4d, 0x61,
- 0x63, 0x68, 0x69, 0x6e, 0x65, 0x2e, 0x4d, 0x69, 0x6e, 0x6f, 0x72, 0x53,
- 0x74, 0x61, 0x74, 0x65, 0x2e, 0x53, 0x63, 0x72, 0x6f, 0x6c, 0x6c, 0x48,
- 0x61, 0x6e, 0x64, 0x6c, 0x65, 0x72, 0x53, 0x74, 0x61, 0x74, 0x65, 0x52,
- 0x12, 0x73, 0x63, 0x72, 0x6f, 0x6c, 0x6c, 0x48, 0x61, 0x6e, 0x64, 0x6c,
- 0x65, 0x72, 0x53, 0x74, 0x61, 0x74, 0x65, 0x12, 0x5d, 0x0a, 0x2d, 0x63,
- 0x72, 0x69, 0x74, 0x69, 0x63, 0x61, 0x6c, 0x5f, 0x62, 0x65, 0x67, 0x69,
- 0x6e, 0x5f, 0x6d, 0x61, 0x69, 0x6e, 0x5f, 0x66, 0x72, 0x61, 0x6d, 0x65,
- 0x5f, 0x74, 0x6f, 0x5f, 0x61, 0x63, 0x74, 0x69, 0x76, 0x61, 0x74, 0x65,
- 0x5f, 0x69, 0x73, 0x5f, 0x66, 0x61, 0x73, 0x74, 0x18, 0x21, 0x20, 0x01,
- 0x28, 0x08, 0x52, 0x26, 0x63, 0x72, 0x69, 0x74, 0x69, 0x63, 0x61, 0x6c,
- 0x42, 0x65, 0x67, 0x69, 0x6e, 0x4d, 0x61, 0x69, 0x6e, 0x46, 0x72, 0x61,
- 0x6d, 0x65, 0x54, 0x6f, 0x41, 0x63, 0x74, 0x69, 0x76, 0x61, 0x74, 0x65,
- 0x49, 0x73, 0x46, 0x61, 0x73, 0x74, 0x12, 0x46, 0x0a, 0x20, 0x6d, 0x61,
- 0x69, 0x6e, 0x5f, 0x74, 0x68, 0x72, 0x65, 0x61, 0x64, 0x5f, 0x6d, 0x69,
- 0x73, 0x73, 0x65, 0x64, 0x5f, 0x6c, 0x61, 0x73, 0x74, 0x5f, 0x64, 0x65,
- 0x61, 0x64, 0x6c, 0x69, 0x6e, 0x65, 0x18, 0x22, 0x20, 0x01, 0x28, 0x08,
- 0x52, 0x1c, 0x6d, 0x61, 0x69, 0x6e, 0x54, 0x68, 0x72, 0x65, 0x61, 0x64,
- 0x4d, 0x69, 0x73, 0x73, 0x65, 0x64, 0x4c, 0x61, 0x73, 0x74, 0x44, 0x65,
- 0x61, 0x64, 0x6c, 0x69, 0x6e, 0x65, 0x12, 0x5b, 0x0a, 0x2c, 0x73, 0x6b,
- 0x69, 0x70, 0x5f, 0x6e, 0x65, 0x78, 0x74, 0x5f, 0x62, 0x65, 0x67, 0x69,
- 0x6e, 0x5f, 0x6d, 0x61, 0x69, 0x6e, 0x5f, 0x66, 0x72, 0x61, 0x6d, 0x65,
- 0x5f, 0x74, 0x6f, 0x5f, 0x72, 0x65, 0x64, 0x75, 0x63, 0x65, 0x5f, 0x6c,
- 0x61, 0x74, 0x65, 0x6e, 0x63, 0x79, 0x18, 0x23, 0x20, 0x01, 0x28, 0x08,
- 0x52, 0x25, 0x73, 0x6b, 0x69, 0x70, 0x4e, 0x65, 0x78, 0x74, 0x42, 0x65,
- 0x67, 0x69, 0x6e, 0x4d, 0x61, 0x69, 0x6e, 0x46, 0x72, 0x61, 0x6d, 0x65,
- 0x54, 0x6f, 0x52, 0x65, 0x64, 0x75, 0x63, 0x65, 0x4c, 0x61, 0x74, 0x65,
- 0x6e, 0x63, 0x79, 0x12, 0x37, 0x0a, 0x18, 0x76, 0x69, 0x64, 0x65, 0x6f,
- 0x5f, 0x6e, 0x65, 0x65, 0x64, 0x73, 0x5f, 0x62, 0x65, 0x67, 0x69, 0x6e,
- 0x5f, 0x66, 0x72, 0x61, 0x6d, 0x65, 0x73, 0x18, 0x24, 0x20, 0x01, 0x28,
- 0x08, 0x52, 0x15, 0x76, 0x69, 0x64, 0x65, 0x6f, 0x4e, 0x65, 0x65, 0x64,
- 0x73, 0x42, 0x65, 0x67, 0x69, 0x6e, 0x46, 0x72, 0x61, 0x6d, 0x65, 0x73,
- 0x12, 0x33, 0x0a, 0x16, 0x64, 0x65, 0x66, 0x65, 0x72, 0x5f, 0x62, 0x65,
- 0x67, 0x69, 0x6e, 0x5f, 0x6d, 0x61, 0x69, 0x6e, 0x5f, 0x66, 0x72, 0x61,
- 0x6d, 0x65, 0x18, 0x25, 0x20, 0x01, 0x28, 0x08, 0x52, 0x13, 0x64, 0x65,
- 0x66, 0x65, 0x72, 0x42, 0x65, 0x67, 0x69, 0x6e, 0x4d, 0x61, 0x69, 0x6e,
- 0x46, 0x72, 0x61, 0x6d, 0x65, 0x12, 0x3a, 0x0a, 0x1a, 0x6c, 0x61, 0x73,
- 0x74, 0x5f, 0x63, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x5f, 0x68, 0x61, 0x64,
- 0x5f, 0x6e, 0x6f, 0x5f, 0x75, 0x70, 0x64, 0x61, 0x74, 0x65, 0x73, 0x18,
- 0x26, 0x20, 0x01, 0x28, 0x08, 0x52, 0x16, 0x6c, 0x61, 0x73, 0x74, 0x43,
- 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x48, 0x61, 0x64, 0x4e, 0x6f, 0x55, 0x70,
- 0x64, 0x61, 0x74, 0x65, 0x73, 0x12, 0x32, 0x0a, 0x16, 0x64, 0x69, 0x64,
- 0x5f, 0x64, 0x72, 0x61, 0x77, 0x5f, 0x69, 0x6e, 0x5f, 0x6c, 0x61, 0x73,
- 0x74, 0x5f, 0x66, 0x72, 0x61, 0x6d, 0x65, 0x18, 0x27, 0x20, 0x01, 0x28,
- 0x08, 0x52, 0x12, 0x64, 0x69, 0x64, 0x44, 0x72, 0x61, 0x77, 0x49, 0x6e,
- 0x4c, 0x61, 0x73, 0x74, 0x46, 0x72, 0x61, 0x6d, 0x65, 0x12, 0x36, 0x0a,
- 0x18, 0x64, 0x69, 0x64, 0x5f, 0x73, 0x75, 0x62, 0x6d, 0x69, 0x74, 0x5f,
- 0x69, 0x6e, 0x5f, 0x6c, 0x61, 0x73, 0x74, 0x5f, 0x66, 0x72, 0x61, 0x6d,
- 0x65, 0x18, 0x28, 0x20, 0x01, 0x28, 0x08, 0x52, 0x14, 0x64, 0x69, 0x64,
- 0x53, 0x75, 0x62, 0x6d, 0x69, 0x74, 0x49, 0x6e, 0x4c, 0x61, 0x73, 0x74,
- 0x46, 0x72, 0x61, 0x6d, 0x65, 0x12, 0x3f, 0x0a, 0x1c, 0x6e, 0x65, 0x65,
- 0x64, 0x73, 0x5f, 0x69, 0x6d, 0x70, 0x6c, 0x5f, 0x73, 0x69, 0x64, 0x65,
- 0x5f, 0x69, 0x6e, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x69, 0x6f,
- 0x6e, 0x18, 0x29, 0x20, 0x01, 0x28, 0x08, 0x52, 0x19, 0x6e, 0x65, 0x65,
- 0x64, 0x73, 0x49, 0x6d, 0x70, 0x6c, 0x53, 0x69, 0x64, 0x65, 0x49, 0x6e,
- 0x76, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x47,
- 0x0a, 0x21, 0x63, 0x75, 0x72, 0x72, 0x65, 0x6e, 0x74, 0x5f, 0x70, 0x65,
- 0x6e, 0x64, 0x69, 0x6e, 0x67, 0x5f, 0x74, 0x72, 0x65, 0x65, 0x5f, 0x69,
- 0x73, 0x5f, 0x69, 0x6d, 0x70, 0x6c, 0x5f, 0x73, 0x69, 0x64, 0x65, 0x18,
- 0x2a, 0x20, 0x01, 0x28, 0x08, 0x52, 0x1c, 0x63, 0x75, 0x72, 0x72, 0x65,
- 0x6e, 0x74, 0x50, 0x65, 0x6e, 0x64, 0x69, 0x6e, 0x67, 0x54, 0x72, 0x65,
- 0x65, 0x49, 0x73, 0x49, 0x6d, 0x70, 0x6c, 0x53, 0x69, 0x64, 0x65, 0x12,
- 0x4b, 0x0a, 0x23, 0x70, 0x72, 0x65, 0x76, 0x69, 0x6f, 0x75, 0x73, 0x5f,
- 0x70, 0x65, 0x6e, 0x64, 0x69, 0x6e, 0x67, 0x5f, 0x74, 0x72, 0x65, 0x65,
- 0x5f, 0x77, 0x61, 0x73, 0x5f, 0x69, 0x6d, 0x70, 0x6c, 0x5f, 0x73, 0x69,
- 0x64, 0x65, 0x18, 0x2b, 0x20, 0x01, 0x28, 0x08, 0x52, 0x1e, 0x70, 0x72,
- 0x65, 0x76, 0x69, 0x6f, 0x75, 0x73, 0x50, 0x65, 0x6e, 0x64, 0x69, 0x6e,
- 0x67, 0x54, 0x72, 0x65, 0x65, 0x57, 0x61, 0x73, 0x49, 0x6d, 0x70, 0x6c,
- 0x53, 0x69, 0x64, 0x65, 0x12, 0x5f, 0x0a, 0x2d, 0x70, 0x72, 0x6f, 0x63,
- 0x65, 0x73, 0x73, 0x69, 0x6e, 0x67, 0x5f, 0x61, 0x6e, 0x69, 0x6d, 0x61,
- 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x77, 0x6f, 0x72, 0x6b, 0x6c, 0x65, 0x74,
- 0x73, 0x5f, 0x66, 0x6f, 0x72, 0x5f, 0x61, 0x63, 0x74, 0x69, 0x76, 0x65,
- 0x5f, 0x74, 0x72, 0x65, 0x65, 0x18, 0x2c, 0x20, 0x01, 0x28, 0x08, 0x52,
- 0x28, 0x70, 0x72, 0x6f, 0x63, 0x65, 0x73, 0x73, 0x69, 0x6e, 0x67, 0x41,
- 0x6e, 0x69, 0x6d, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x57, 0x6f, 0x72, 0x6b,
- 0x6c, 0x65, 0x74, 0x73, 0x46, 0x6f, 0x72, 0x41, 0x63, 0x74, 0x69, 0x76,
- 0x65, 0x54, 0x72, 0x65, 0x65, 0x12, 0x61, 0x0a, 0x2e, 0x70, 0x72, 0x6f,
- 0x63, 0x65, 0x73, 0x73, 0x69, 0x6e, 0x67, 0x5f, 0x61, 0x6e, 0x69, 0x6d,
- 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x77, 0x6f, 0x72, 0x6b, 0x6c, 0x65,
- 0x74, 0x73, 0x5f, 0x66, 0x6f, 0x72, 0x5f, 0x70, 0x65, 0x6e, 0x64, 0x69,
- 0x6e, 0x67, 0x5f, 0x74, 0x72, 0x65, 0x65, 0x18, 0x2d, 0x20, 0x01, 0x28,
- 0x08, 0x52, 0x29, 0x70, 0x72, 0x6f, 0x63, 0x65, 0x73, 0x73, 0x69, 0x6e,
- 0x67, 0x41, 0x6e, 0x69, 0x6d, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x57, 0x6f,
- 0x72, 0x6b, 0x6c, 0x65, 0x74, 0x73, 0x46, 0x6f, 0x72, 0x50, 0x65, 0x6e,
- 0x64, 0x69, 0x6e, 0x67, 0x54, 0x72, 0x65, 0x65, 0x12, 0x59, 0x0a, 0x2a,
- 0x70, 0x72, 0x6f, 0x63, 0x65, 0x73, 0x73, 0x69, 0x6e, 0x67, 0x5f, 0x70,
- 0x61, 0x69, 0x6e, 0x74, 0x5f, 0x77, 0x6f, 0x72, 0x6b, 0x6c, 0x65, 0x74,
- 0x73, 0x5f, 0x66, 0x6f, 0x72, 0x5f, 0x70, 0x65, 0x6e, 0x64, 0x69, 0x6e,
- 0x67, 0x5f, 0x74, 0x72, 0x65, 0x65, 0x18, 0x2e, 0x20, 0x01, 0x28, 0x08,
- 0x52, 0x25, 0x70, 0x72, 0x6f, 0x63, 0x65, 0x73, 0x73, 0x69, 0x6e, 0x67,
- 0x50, 0x61, 0x69, 0x6e, 0x74, 0x57, 0x6f, 0x72, 0x6b, 0x6c, 0x65, 0x74,
- 0x73, 0x46, 0x6f, 0x72, 0x50, 0x65, 0x6e, 0x64, 0x69, 0x6e, 0x67, 0x54,
- 0x72, 0x65, 0x65, 0x22, 0xb8, 0x01, 0x0a, 0x0c, 0x54, 0x72, 0x65, 0x65,
- 0x50, 0x72, 0x69, 0x6f, 0x72, 0x69, 0x74, 0x79, 0x12, 0x1d, 0x0a, 0x19,
+ 0x65, 0x12, 0x3a, 0x0a, 0x1a, 0x6c, 0x61, 0x73, 0x74, 0x5f, 0x63, 0x6f,
+ 0x6d, 0x6d, 0x69, 0x74, 0x5f, 0x68, 0x61, 0x64, 0x5f, 0x6e, 0x6f, 0x5f,
+ 0x75, 0x70, 0x64, 0x61, 0x74, 0x65, 0x73, 0x18, 0x26, 0x20, 0x01, 0x28,
+ 0x08, 0x52, 0x16, 0x6c, 0x61, 0x73, 0x74, 0x43, 0x6f, 0x6d, 0x6d, 0x69,
+ 0x74, 0x48, 0x61, 0x64, 0x4e, 0x6f, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65,
+ 0x73, 0x12, 0x32, 0x0a, 0x16, 0x64, 0x69, 0x64, 0x5f, 0x64, 0x72, 0x61,
+ 0x77, 0x5f, 0x69, 0x6e, 0x5f, 0x6c, 0x61, 0x73, 0x74, 0x5f, 0x66, 0x72,
+ 0x61, 0x6d, 0x65, 0x18, 0x27, 0x20, 0x01, 0x28, 0x08, 0x52, 0x12, 0x64,
+ 0x69, 0x64, 0x44, 0x72, 0x61, 0x77, 0x49, 0x6e, 0x4c, 0x61, 0x73, 0x74,
+ 0x46, 0x72, 0x61, 0x6d, 0x65, 0x12, 0x36, 0x0a, 0x18, 0x64, 0x69, 0x64,
+ 0x5f, 0x73, 0x75, 0x62, 0x6d, 0x69, 0x74, 0x5f, 0x69, 0x6e, 0x5f, 0x6c,
+ 0x61, 0x73, 0x74, 0x5f, 0x66, 0x72, 0x61, 0x6d, 0x65, 0x18, 0x28, 0x20,
+ 0x01, 0x28, 0x08, 0x52, 0x14, 0x64, 0x69, 0x64, 0x53, 0x75, 0x62, 0x6d,
+ 0x69, 0x74, 0x49, 0x6e, 0x4c, 0x61, 0x73, 0x74, 0x46, 0x72, 0x61, 0x6d,
+ 0x65, 0x12, 0x3f, 0x0a, 0x1c, 0x6e, 0x65, 0x65, 0x64, 0x73, 0x5f, 0x69,
+ 0x6d, 0x70, 0x6c, 0x5f, 0x73, 0x69, 0x64, 0x65, 0x5f, 0x69, 0x6e, 0x76,
+ 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x29, 0x20,
+ 0x01, 0x28, 0x08, 0x52, 0x19, 0x6e, 0x65, 0x65, 0x64, 0x73, 0x49, 0x6d,
+ 0x70, 0x6c, 0x53, 0x69, 0x64, 0x65, 0x49, 0x6e, 0x76, 0x61, 0x6c, 0x69,
+ 0x64, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x47, 0x0a, 0x21, 0x63, 0x75,
+ 0x72, 0x72, 0x65, 0x6e, 0x74, 0x5f, 0x70, 0x65, 0x6e, 0x64, 0x69, 0x6e,
+ 0x67, 0x5f, 0x74, 0x72, 0x65, 0x65, 0x5f, 0x69, 0x73, 0x5f, 0x69, 0x6d,
+ 0x70, 0x6c, 0x5f, 0x73, 0x69, 0x64, 0x65, 0x18, 0x2a, 0x20, 0x01, 0x28,
+ 0x08, 0x52, 0x1c, 0x63, 0x75, 0x72, 0x72, 0x65, 0x6e, 0x74, 0x50, 0x65,
+ 0x6e, 0x64, 0x69, 0x6e, 0x67, 0x54, 0x72, 0x65, 0x65, 0x49, 0x73, 0x49,
+ 0x6d, 0x70, 0x6c, 0x53, 0x69, 0x64, 0x65, 0x12, 0x4b, 0x0a, 0x23, 0x70,
+ 0x72, 0x65, 0x76, 0x69, 0x6f, 0x75, 0x73, 0x5f, 0x70, 0x65, 0x6e, 0x64,
+ 0x69, 0x6e, 0x67, 0x5f, 0x74, 0x72, 0x65, 0x65, 0x5f, 0x77, 0x61, 0x73,
+ 0x5f, 0x69, 0x6d, 0x70, 0x6c, 0x5f, 0x73, 0x69, 0x64, 0x65, 0x18, 0x2b,
+ 0x20, 0x01, 0x28, 0x08, 0x52, 0x1e, 0x70, 0x72, 0x65, 0x76, 0x69, 0x6f,
+ 0x75, 0x73, 0x50, 0x65, 0x6e, 0x64, 0x69, 0x6e, 0x67, 0x54, 0x72, 0x65,
+ 0x65, 0x57, 0x61, 0x73, 0x49, 0x6d, 0x70, 0x6c, 0x53, 0x69, 0x64, 0x65,
+ 0x12, 0x5f, 0x0a, 0x2d, 0x70, 0x72, 0x6f, 0x63, 0x65, 0x73, 0x73, 0x69,
+ 0x6e, 0x67, 0x5f, 0x61, 0x6e, 0x69, 0x6d, 0x61, 0x74, 0x69, 0x6f, 0x6e,
+ 0x5f, 0x77, 0x6f, 0x72, 0x6b, 0x6c, 0x65, 0x74, 0x73, 0x5f, 0x66, 0x6f,
+ 0x72, 0x5f, 0x61, 0x63, 0x74, 0x69, 0x76, 0x65, 0x5f, 0x74, 0x72, 0x65,
+ 0x65, 0x18, 0x2c, 0x20, 0x01, 0x28, 0x08, 0x52, 0x28, 0x70, 0x72, 0x6f,
+ 0x63, 0x65, 0x73, 0x73, 0x69, 0x6e, 0x67, 0x41, 0x6e, 0x69, 0x6d, 0x61,
+ 0x74, 0x69, 0x6f, 0x6e, 0x57, 0x6f, 0x72, 0x6b, 0x6c, 0x65, 0x74, 0x73,
+ 0x46, 0x6f, 0x72, 0x41, 0x63, 0x74, 0x69, 0x76, 0x65, 0x54, 0x72, 0x65,
+ 0x65, 0x12, 0x61, 0x0a, 0x2e, 0x70, 0x72, 0x6f, 0x63, 0x65, 0x73, 0x73,
+ 0x69, 0x6e, 0x67, 0x5f, 0x61, 0x6e, 0x69, 0x6d, 0x61, 0x74, 0x69, 0x6f,
+ 0x6e, 0x5f, 0x77, 0x6f, 0x72, 0x6b, 0x6c, 0x65, 0x74, 0x73, 0x5f, 0x66,
+ 0x6f, 0x72, 0x5f, 0x70, 0x65, 0x6e, 0x64, 0x69, 0x6e, 0x67, 0x5f, 0x74,
+ 0x72, 0x65, 0x65, 0x18, 0x2d, 0x20, 0x01, 0x28, 0x08, 0x52, 0x29, 0x70,
+ 0x72, 0x6f, 0x63, 0x65, 0x73, 0x73, 0x69, 0x6e, 0x67, 0x41, 0x6e, 0x69,
+ 0x6d, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x57, 0x6f, 0x72, 0x6b, 0x6c, 0x65,
+ 0x74, 0x73, 0x46, 0x6f, 0x72, 0x50, 0x65, 0x6e, 0x64, 0x69, 0x6e, 0x67,
+ 0x54, 0x72, 0x65, 0x65, 0x12, 0x59, 0x0a, 0x2a, 0x70, 0x72, 0x6f, 0x63,
+ 0x65, 0x73, 0x73, 0x69, 0x6e, 0x67, 0x5f, 0x70, 0x61, 0x69, 0x6e, 0x74,
+ 0x5f, 0x77, 0x6f, 0x72, 0x6b, 0x6c, 0x65, 0x74, 0x73, 0x5f, 0x66, 0x6f,
+ 0x72, 0x5f, 0x70, 0x65, 0x6e, 0x64, 0x69, 0x6e, 0x67, 0x5f, 0x74, 0x72,
+ 0x65, 0x65, 0x18, 0x2e, 0x20, 0x01, 0x28, 0x08, 0x52, 0x25, 0x70, 0x72,
+ 0x6f, 0x63, 0x65, 0x73, 0x73, 0x69, 0x6e, 0x67, 0x50, 0x61, 0x69, 0x6e,
+ 0x74, 0x57, 0x6f, 0x72, 0x6b, 0x6c, 0x65, 0x74, 0x73, 0x46, 0x6f, 0x72,
+ 0x50, 0x65, 0x6e, 0x64, 0x69, 0x6e, 0x67, 0x54, 0x72, 0x65, 0x65, 0x22,
+ 0xb8, 0x01, 0x0a, 0x0c, 0x54, 0x72, 0x65, 0x65, 0x50, 0x72, 0x69, 0x6f,
+ 0x72, 0x69, 0x74, 0x79, 0x12, 0x1d, 0x0a, 0x19, 0x54, 0x52, 0x45, 0x45,
+ 0x5f, 0x50, 0x52, 0x49, 0x4f, 0x52, 0x49, 0x54, 0x59, 0x5f, 0x55, 0x4e,
+ 0x53, 0x50, 0x45, 0x43, 0x49, 0x46, 0x49, 0x45, 0x44, 0x10, 0x00, 0x12,
+ 0x2e, 0x0a, 0x2a, 0x54, 0x52, 0x45, 0x45, 0x5f, 0x50, 0x52, 0x49, 0x4f,
+ 0x52, 0x49, 0x54, 0x59, 0x5f, 0x53, 0x41, 0x4d, 0x45, 0x5f, 0x50, 0x52,
+ 0x49, 0x4f, 0x52, 0x49, 0x54, 0x59, 0x5f, 0x46, 0x4f, 0x52, 0x5f, 0x42,
+ 0x4f, 0x54, 0x48, 0x5f, 0x54, 0x52, 0x45, 0x45, 0x53, 0x10, 0x01, 0x12,
+ 0x2b, 0x0a, 0x27, 0x54, 0x52, 0x45, 0x45, 0x5f, 0x50, 0x52, 0x49, 0x4f,
+ 0x52, 0x49, 0x54, 0x59, 0x5f, 0x53, 0x4d, 0x4f, 0x4f, 0x54, 0x48, 0x4e,
+ 0x45, 0x53, 0x53, 0x5f, 0x54, 0x41, 0x4b, 0x45, 0x53, 0x5f, 0x50, 0x52,
+ 0x49, 0x4f, 0x52, 0x49, 0x54, 0x59, 0x10, 0x02, 0x12, 0x2c, 0x0a, 0x28,
0x54, 0x52, 0x45, 0x45, 0x5f, 0x50, 0x52, 0x49, 0x4f, 0x52, 0x49, 0x54,
- 0x59, 0x5f, 0x55, 0x4e, 0x53, 0x50, 0x45, 0x43, 0x49, 0x46, 0x49, 0x45,
- 0x44, 0x10, 0x00, 0x12, 0x2e, 0x0a, 0x2a, 0x54, 0x52, 0x45, 0x45, 0x5f,
- 0x50, 0x52, 0x49, 0x4f, 0x52, 0x49, 0x54, 0x59, 0x5f, 0x53, 0x41, 0x4d,
- 0x45, 0x5f, 0x50, 0x52, 0x49, 0x4f, 0x52, 0x49, 0x54, 0x59, 0x5f, 0x46,
- 0x4f, 0x52, 0x5f, 0x42, 0x4f, 0x54, 0x48, 0x5f, 0x54, 0x52, 0x45, 0x45,
- 0x53, 0x10, 0x01, 0x12, 0x2b, 0x0a, 0x27, 0x54, 0x52, 0x45, 0x45, 0x5f,
- 0x50, 0x52, 0x49, 0x4f, 0x52, 0x49, 0x54, 0x59, 0x5f, 0x53, 0x4d, 0x4f,
- 0x4f, 0x54, 0x48, 0x4e, 0x45, 0x53, 0x53, 0x5f, 0x54, 0x41, 0x4b, 0x45,
- 0x53, 0x5f, 0x50, 0x52, 0x49, 0x4f, 0x52, 0x49, 0x54, 0x59, 0x10, 0x02,
- 0x12, 0x2c, 0x0a, 0x28, 0x54, 0x52, 0x45, 0x45, 0x5f, 0x50, 0x52, 0x49,
- 0x4f, 0x52, 0x49, 0x54, 0x59, 0x5f, 0x4e, 0x45, 0x57, 0x5f, 0x43, 0x4f,
- 0x4e, 0x54, 0x45, 0x4e, 0x54, 0x5f, 0x54, 0x41, 0x4b, 0x45, 0x53, 0x5f,
- 0x50, 0x52, 0x49, 0x4f, 0x52, 0x49, 0x54, 0x59, 0x10, 0x03, 0x22, 0x82,
- 0x01, 0x0a, 0x12, 0x53, 0x63, 0x72, 0x6f, 0x6c, 0x6c, 0x48, 0x61, 0x6e,
- 0x64, 0x6c, 0x65, 0x72, 0x53, 0x74, 0x61, 0x74, 0x65, 0x12, 0x1e, 0x0a,
- 0x1a, 0x53, 0x43, 0x52, 0x4f, 0x4c, 0x4c, 0x5f, 0x48, 0x41, 0x4e, 0x44,
- 0x4c, 0x45, 0x52, 0x5f, 0x55, 0x4e, 0x53, 0x50, 0x45, 0x43, 0x49, 0x46,
- 0x49, 0x45, 0x44, 0x10, 0x00, 0x12, 0x21, 0x0a, 0x1d, 0x53, 0x43, 0x52,
- 0x4f, 0x4c, 0x4c, 0x5f, 0x41, 0x46, 0x46, 0x45, 0x43, 0x54, 0x53, 0x5f,
- 0x53, 0x43, 0x52, 0x4f, 0x4c, 0x4c, 0x5f, 0x48, 0x41, 0x4e, 0x44, 0x4c,
- 0x45, 0x52, 0x10, 0x01, 0x12, 0x29, 0x0a, 0x25, 0x53, 0x43, 0x52, 0x4f,
- 0x4c, 0x4c, 0x5f, 0x44, 0x4f, 0x45, 0x53, 0x5f, 0x4e, 0x4f, 0x54, 0x5f,
- 0x41, 0x46, 0x46, 0x45, 0x43, 0x54, 0x5f, 0x53, 0x43, 0x52, 0x4f, 0x4c,
- 0x4c, 0x5f, 0x48, 0x41, 0x4e, 0x44, 0x4c, 0x45, 0x52, 0x10, 0x02, 0x22,
- 0x8f, 0x05, 0x0a, 0x0e, 0x42, 0x65, 0x67, 0x69, 0x6e, 0x46, 0x72, 0x61,
- 0x6d, 0x65, 0x41, 0x72, 0x67, 0x73, 0x12, 0x46, 0x0a, 0x04, 0x74, 0x79,
- 0x70, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x32, 0x2e, 0x70,
- 0x65, 0x72, 0x66, 0x65, 0x74, 0x74, 0x6f, 0x2e, 0x70, 0x72, 0x6f, 0x74,
- 0x6f, 0x73, 0x2e, 0x42, 0x65, 0x67, 0x69, 0x6e, 0x46, 0x72, 0x61, 0x6d,
- 0x65, 0x41, 0x72, 0x67, 0x73, 0x2e, 0x42, 0x65, 0x67, 0x69, 0x6e, 0x46,
- 0x72, 0x61, 0x6d, 0x65, 0x41, 0x72, 0x67, 0x73, 0x54, 0x79, 0x70, 0x65,
- 0x52, 0x04, 0x74, 0x79, 0x70, 0x65, 0x12, 0x1b, 0x0a, 0x09, 0x73, 0x6f,
- 0x75, 0x72, 0x63, 0x65, 0x5f, 0x69, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28,
- 0x04, 0x52, 0x08, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x49, 0x64, 0x12,
- 0x27, 0x0a, 0x0f, 0x73, 0x65, 0x71, 0x75, 0x65, 0x6e, 0x63, 0x65, 0x5f,
- 0x6e, 0x75, 0x6d, 0x62, 0x65, 0x72, 0x18, 0x03, 0x20, 0x01, 0x28, 0x04,
- 0x52, 0x0e, 0x73, 0x65, 0x71, 0x75, 0x65, 0x6e, 0x63, 0x65, 0x4e, 0x75,
- 0x6d, 0x62, 0x65, 0x72, 0x12, 0x22, 0x0a, 0x0d, 0x66, 0x72, 0x61, 0x6d,
- 0x65, 0x5f, 0x74, 0x69, 0x6d, 0x65, 0x5f, 0x75, 0x73, 0x18, 0x04, 0x20,
- 0x01, 0x28, 0x03, 0x52, 0x0b, 0x66, 0x72, 0x61, 0x6d, 0x65, 0x54, 0x69,
- 0x6d, 0x65, 0x55, 0x73, 0x12, 0x1f, 0x0a, 0x0b, 0x64, 0x65, 0x61, 0x64,
- 0x6c, 0x69, 0x6e, 0x65, 0x5f, 0x75, 0x73, 0x18, 0x05, 0x20, 0x01, 0x28,
- 0x03, 0x52, 0x0a, 0x64, 0x65, 0x61, 0x64, 0x6c, 0x69, 0x6e, 0x65, 0x55,
- 0x73, 0x12, 0x2a, 0x0a, 0x11, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x76, 0x61,
- 0x6c, 0x5f, 0x64, 0x65, 0x6c, 0x74, 0x61, 0x5f, 0x75, 0x73, 0x18, 0x06,
- 0x20, 0x01, 0x28, 0x03, 0x52, 0x0f, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x76,
- 0x61, 0x6c, 0x44, 0x65, 0x6c, 0x74, 0x61, 0x55, 0x73, 0x12, 0x28, 0x0a,
- 0x10, 0x6f, 0x6e, 0x5f, 0x63, 0x72, 0x69, 0x74, 0x69, 0x63, 0x61, 0x6c,
- 0x5f, 0x70, 0x61, 0x74, 0x68, 0x18, 0x07, 0x20, 0x01, 0x28, 0x08, 0x52,
- 0x0e, 0x6f, 0x6e, 0x43, 0x72, 0x69, 0x74, 0x69, 0x63, 0x61, 0x6c, 0x50,
- 0x61, 0x74, 0x68, 0x12, 0x21, 0x0a, 0x0c, 0x61, 0x6e, 0x69, 0x6d, 0x61,
- 0x74, 0x65, 0x5f, 0x6f, 0x6e, 0x6c, 0x79, 0x18, 0x08, 0x20, 0x01, 0x28,
- 0x08, 0x52, 0x0b, 0x61, 0x6e, 0x69, 0x6d, 0x61, 0x74, 0x65, 0x4f, 0x6e,
- 0x6c, 0x79, 0x12, 0x30, 0x0a, 0x13, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65,
- 0x5f, 0x6c, 0x6f, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x69, 0x69,
- 0x64, 0x18, 0x09, 0x20, 0x01, 0x28, 0x04, 0x48, 0x00, 0x52, 0x11, 0x73,
- 0x6f, 0x75, 0x72, 0x63, 0x65, 0x4c, 0x6f, 0x63, 0x61, 0x74, 0x69, 0x6f,
- 0x6e, 0x49, 0x69, 0x64, 0x12, 0x4a, 0x0a, 0x0f, 0x73, 0x6f, 0x75, 0x72,
- 0x63, 0x65, 0x5f, 0x6c, 0x6f, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x18,
- 0x0a, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1f, 0x2e, 0x70, 0x65, 0x72, 0x66,
- 0x65, 0x74, 0x74, 0x6f, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2e,
- 0x53, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x4c, 0x6f, 0x63, 0x61, 0x74, 0x69,
- 0x6f, 0x6e, 0x48, 0x00, 0x52, 0x0e, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65,
- 0x4c, 0x6f, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x22, 0xa2, 0x01, 0x0a,
- 0x12, 0x42, 0x65, 0x67, 0x69, 0x6e, 0x46, 0x72, 0x61, 0x6d, 0x65, 0x41,
- 0x72, 0x67, 0x73, 0x54, 0x79, 0x70, 0x65, 0x12, 0x25, 0x0a, 0x21, 0x42,
- 0x45, 0x47, 0x49, 0x4e, 0x5f, 0x46, 0x52, 0x41, 0x4d, 0x45, 0x5f, 0x41,
- 0x52, 0x47, 0x53, 0x5f, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x55, 0x4e, 0x53,
- 0x50, 0x45, 0x43, 0x49, 0x46, 0x49, 0x45, 0x44, 0x10, 0x00, 0x12, 0x21,
- 0x0a, 0x1d, 0x42, 0x45, 0x47, 0x49, 0x4e, 0x5f, 0x46, 0x52, 0x41, 0x4d,
- 0x45, 0x5f, 0x41, 0x52, 0x47, 0x53, 0x5f, 0x54, 0x59, 0x50, 0x45, 0x5f,
- 0x49, 0x4e, 0x56, 0x41, 0x4c, 0x49, 0x44, 0x10, 0x01, 0x12, 0x20, 0x0a,
- 0x1c, 0x42, 0x45, 0x47, 0x49, 0x4e, 0x5f, 0x46, 0x52, 0x41, 0x4d, 0x45,
- 0x5f, 0x41, 0x52, 0x47, 0x53, 0x5f, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x4e,
- 0x4f, 0x52, 0x4d, 0x41, 0x4c, 0x10, 0x02, 0x12, 0x20, 0x0a, 0x1c, 0x42,
- 0x45, 0x47, 0x49, 0x4e, 0x5f, 0x46, 0x52, 0x41, 0x4d, 0x45, 0x5f, 0x41,
- 0x52, 0x47, 0x53, 0x5f, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x4d, 0x49, 0x53,
- 0x53, 0x45, 0x44, 0x10, 0x03, 0x42, 0x0e, 0x0a, 0x0c, 0x63, 0x72, 0x65,
- 0x61, 0x74, 0x65, 0x64, 0x5f, 0x66, 0x72, 0x6f, 0x6d, 0x22, 0xf5, 0x05,
- 0x0a, 0x12, 0x42, 0x65, 0x67, 0x69, 0x6e, 0x49, 0x6d, 0x70, 0x6c, 0x46,
- 0x72, 0x61, 0x6d, 0x65, 0x41, 0x72, 0x67, 0x73, 0x12, 0x22, 0x0a, 0x0d,
- 0x75, 0x70, 0x64, 0x61, 0x74, 0x65, 0x64, 0x5f, 0x61, 0x74, 0x5f, 0x75,
- 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0b, 0x75, 0x70, 0x64,
- 0x61, 0x74, 0x65, 0x64, 0x41, 0x74, 0x55, 0x73, 0x12, 0x24, 0x0a, 0x0e,
- 0x66, 0x69, 0x6e, 0x69, 0x73, 0x68, 0x65, 0x64, 0x5f, 0x61, 0x74, 0x5f,
- 0x75, 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0c, 0x66, 0x69,
- 0x6e, 0x69, 0x73, 0x68, 0x65, 0x64, 0x41, 0x74, 0x55, 0x73, 0x12, 0x3f,
- 0x0a, 0x05, 0x73, 0x74, 0x61, 0x74, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28,
- 0x0e, 0x32, 0x29, 0x2e, 0x70, 0x65, 0x72, 0x66, 0x65, 0x74, 0x74, 0x6f,
- 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2e, 0x42, 0x65, 0x67, 0x69,
- 0x6e, 0x49, 0x6d, 0x70, 0x6c, 0x46, 0x72, 0x61, 0x6d, 0x65, 0x41, 0x72,
- 0x67, 0x73, 0x2e, 0x53, 0x74, 0x61, 0x74, 0x65, 0x52, 0x05, 0x73, 0x74,
- 0x61, 0x74, 0x65, 0x12, 0x44, 0x0a, 0x0c, 0x63, 0x75, 0x72, 0x72, 0x65,
- 0x6e, 0x74, 0x5f, 0x61, 0x72, 0x67, 0x73, 0x18, 0x04, 0x20, 0x01, 0x28,
- 0x0b, 0x32, 0x1f, 0x2e, 0x70, 0x65, 0x72, 0x66, 0x65, 0x74, 0x74, 0x6f,
- 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2e, 0x42, 0x65, 0x67, 0x69,
- 0x6e, 0x46, 0x72, 0x61, 0x6d, 0x65, 0x41, 0x72, 0x67, 0x73, 0x48, 0x00,
- 0x52, 0x0b, 0x63, 0x75, 0x72, 0x72, 0x65, 0x6e, 0x74, 0x41, 0x72, 0x67,
- 0x73, 0x12, 0x3e, 0x0a, 0x09, 0x6c, 0x61, 0x73, 0x74, 0x5f, 0x61, 0x72,
- 0x67, 0x73, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1f, 0x2e, 0x70,
- 0x65, 0x72, 0x66, 0x65, 0x74, 0x74, 0x6f, 0x2e, 0x70, 0x72, 0x6f, 0x74,
- 0x6f, 0x73, 0x2e, 0x42, 0x65, 0x67, 0x69, 0x6e, 0x46, 0x72, 0x61, 0x6d,
- 0x65, 0x41, 0x72, 0x67, 0x73, 0x48, 0x00, 0x52, 0x08, 0x6c, 0x61, 0x73,
- 0x74, 0x41, 0x72, 0x67, 0x73, 0x12, 0x5c, 0x0a, 0x10, 0x74, 0x69, 0x6d,
- 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x73, 0x5f, 0x69, 0x6e, 0x5f, 0x75,
- 0x73, 0x18, 0x06, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x32, 0x2e, 0x70, 0x65,
- 0x72, 0x66, 0x65, 0x74, 0x74, 0x6f, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f,
- 0x73, 0x2e, 0x42, 0x65, 0x67, 0x69, 0x6e, 0x49, 0x6d, 0x70, 0x6c, 0x46,
- 0x72, 0x61, 0x6d, 0x65, 0x41, 0x72, 0x67, 0x73, 0x2e, 0x54, 0x69, 0x6d,
- 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x73, 0x49, 0x6e, 0x55, 0x73, 0x52,
- 0x0e, 0x74, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x73, 0x49,
- 0x6e, 0x55, 0x73, 0x1a, 0xad, 0x02, 0x0a, 0x0e, 0x54, 0x69, 0x6d, 0x65,
- 0x73, 0x74, 0x61, 0x6d, 0x70, 0x73, 0x49, 0x6e, 0x55, 0x73, 0x12, 0x25,
- 0x0a, 0x0e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x76, 0x61, 0x6c, 0x5f, 0x64,
- 0x65, 0x6c, 0x74, 0x61, 0x18, 0x01, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0d,
- 0x69, 0x6e, 0x74, 0x65, 0x72, 0x76, 0x61, 0x6c, 0x44, 0x65, 0x6c, 0x74,
- 0x61, 0x12, 0x31, 0x0a, 0x15, 0x6e, 0x6f, 0x77, 0x5f, 0x74, 0x6f, 0x5f,
- 0x64, 0x65, 0x61, 0x64, 0x6c, 0x69, 0x6e, 0x65, 0x5f, 0x64, 0x65, 0x6c,
- 0x74, 0x61, 0x18, 0x02, 0x20, 0x01, 0x28, 0x03, 0x52, 0x12, 0x6e, 0x6f,
- 0x77, 0x54, 0x6f, 0x44, 0x65, 0x61, 0x64, 0x6c, 0x69, 0x6e, 0x65, 0x44,
- 0x65, 0x6c, 0x74, 0x61, 0x12, 0x34, 0x0a, 0x17, 0x66, 0x72, 0x61, 0x6d,
- 0x65, 0x5f, 0x74, 0x69, 0x6d, 0x65, 0x5f, 0x74, 0x6f, 0x5f, 0x6e, 0x6f,
- 0x77, 0x5f, 0x64, 0x65, 0x6c, 0x74, 0x61, 0x18, 0x03, 0x20, 0x01, 0x28,
- 0x03, 0x52, 0x13, 0x66, 0x72, 0x61, 0x6d, 0x65, 0x54, 0x69, 0x6d, 0x65,
- 0x54, 0x6f, 0x4e, 0x6f, 0x77, 0x44, 0x65, 0x6c, 0x74, 0x61, 0x12, 0x3e,
- 0x0a, 0x1c, 0x66, 0x72, 0x61, 0x6d, 0x65, 0x5f, 0x74, 0x69, 0x6d, 0x65,
- 0x5f, 0x74, 0x6f, 0x5f, 0x64, 0x65, 0x61, 0x64, 0x6c, 0x69, 0x6e, 0x65,
- 0x5f, 0x64, 0x65, 0x6c, 0x74, 0x61, 0x18, 0x04, 0x20, 0x01, 0x28, 0x03,
- 0x52, 0x18, 0x66, 0x72, 0x61, 0x6d, 0x65, 0x54, 0x69, 0x6d, 0x65, 0x54,
- 0x6f, 0x44, 0x65, 0x61, 0x64, 0x6c, 0x69, 0x6e, 0x65, 0x44, 0x65, 0x6c,
- 0x74, 0x61, 0x12, 0x10, 0x0a, 0x03, 0x6e, 0x6f, 0x77, 0x18, 0x05, 0x20,
- 0x01, 0x28, 0x03, 0x52, 0x03, 0x6e, 0x6f, 0x77, 0x12, 0x1d, 0x0a, 0x0a,
- 0x66, 0x72, 0x61, 0x6d, 0x65, 0x5f, 0x74, 0x69, 0x6d, 0x65, 0x18, 0x06,
- 0x20, 0x01, 0x28, 0x03, 0x52, 0x09, 0x66, 0x72, 0x61, 0x6d, 0x65, 0x54,
- 0x69, 0x6d, 0x65, 0x12, 0x1a, 0x0a, 0x08, 0x64, 0x65, 0x61, 0x64, 0x6c,
- 0x69, 0x6e, 0x65, 0x18, 0x07, 0x20, 0x01, 0x28, 0x03, 0x52, 0x08, 0x64,
- 0x65, 0x61, 0x64, 0x6c, 0x69, 0x6e, 0x65, 0x22, 0x38, 0x0a, 0x05, 0x53,
- 0x74, 0x61, 0x74, 0x65, 0x12, 0x18, 0x0a, 0x14, 0x42, 0x45, 0x47, 0x49,
- 0x4e, 0x5f, 0x46, 0x52, 0x41, 0x4d, 0x45, 0x5f, 0x46, 0x49, 0x4e, 0x49,
- 0x53, 0x48, 0x45, 0x44, 0x10, 0x00, 0x12, 0x15, 0x0a, 0x11, 0x42, 0x45,
- 0x47, 0x49, 0x4e, 0x5f, 0x46, 0x52, 0x41, 0x4d, 0x45, 0x5f, 0x55, 0x53,
- 0x49, 0x4e, 0x47, 0x10, 0x01, 0x42, 0x06, 0x0a, 0x04, 0x61, 0x72, 0x67,
- 0x73, 0x22, 0xa6, 0x01, 0x0a, 0x17, 0x42, 0x65, 0x67, 0x69, 0x6e, 0x46,
- 0x72, 0x61, 0x6d, 0x65, 0x4f, 0x62, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72,
- 0x53, 0x74, 0x61, 0x74, 0x65, 0x12, 0x37, 0x0a, 0x18, 0x64, 0x72, 0x6f,
- 0x70, 0x70, 0x65, 0x64, 0x5f, 0x62, 0x65, 0x67, 0x69, 0x6e, 0x5f, 0x66,
- 0x72, 0x61, 0x6d, 0x65, 0x5f, 0x61, 0x72, 0x67, 0x73, 0x18, 0x01, 0x20,
- 0x01, 0x28, 0x03, 0x52, 0x15, 0x64, 0x72, 0x6f, 0x70, 0x70, 0x65, 0x64,
+ 0x59, 0x5f, 0x4e, 0x45, 0x57, 0x5f, 0x43, 0x4f, 0x4e, 0x54, 0x45, 0x4e,
+ 0x54, 0x5f, 0x54, 0x41, 0x4b, 0x45, 0x53, 0x5f, 0x50, 0x52, 0x49, 0x4f,
+ 0x52, 0x49, 0x54, 0x59, 0x10, 0x03, 0x22, 0x82, 0x01, 0x0a, 0x12, 0x53,
+ 0x63, 0x72, 0x6f, 0x6c, 0x6c, 0x48, 0x61, 0x6e, 0x64, 0x6c, 0x65, 0x72,
+ 0x53, 0x74, 0x61, 0x74, 0x65, 0x12, 0x1e, 0x0a, 0x1a, 0x53, 0x43, 0x52,
+ 0x4f, 0x4c, 0x4c, 0x5f, 0x48, 0x41, 0x4e, 0x44, 0x4c, 0x45, 0x52, 0x5f,
+ 0x55, 0x4e, 0x53, 0x50, 0x45, 0x43, 0x49, 0x46, 0x49, 0x45, 0x44, 0x10,
+ 0x00, 0x12, 0x21, 0x0a, 0x1d, 0x53, 0x43, 0x52, 0x4f, 0x4c, 0x4c, 0x5f,
+ 0x41, 0x46, 0x46, 0x45, 0x43, 0x54, 0x53, 0x5f, 0x53, 0x43, 0x52, 0x4f,
+ 0x4c, 0x4c, 0x5f, 0x48, 0x41, 0x4e, 0x44, 0x4c, 0x45, 0x52, 0x10, 0x01,
+ 0x12, 0x29, 0x0a, 0x25, 0x53, 0x43, 0x52, 0x4f, 0x4c, 0x4c, 0x5f, 0x44,
+ 0x4f, 0x45, 0x53, 0x5f, 0x4e, 0x4f, 0x54, 0x5f, 0x41, 0x46, 0x46, 0x45,
+ 0x43, 0x54, 0x5f, 0x53, 0x43, 0x52, 0x4f, 0x4c, 0x4c, 0x5f, 0x48, 0x41,
+ 0x4e, 0x44, 0x4c, 0x45, 0x52, 0x10, 0x02, 0x22, 0x8f, 0x05, 0x0a, 0x0e,
0x42, 0x65, 0x67, 0x69, 0x6e, 0x46, 0x72, 0x61, 0x6d, 0x65, 0x41, 0x72,
- 0x67, 0x73, 0x12, 0x52, 0x0a, 0x15, 0x6c, 0x61, 0x73, 0x74, 0x5f, 0x62,
- 0x65, 0x67, 0x69, 0x6e, 0x5f, 0x66, 0x72, 0x61, 0x6d, 0x65, 0x5f, 0x61,
- 0x72, 0x67, 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1f, 0x2e,
+ 0x67, 0x73, 0x12, 0x46, 0x0a, 0x04, 0x74, 0x79, 0x70, 0x65, 0x18, 0x01,
+ 0x20, 0x01, 0x28, 0x0e, 0x32, 0x32, 0x2e, 0x70, 0x65, 0x72, 0x66, 0x65,
+ 0x74, 0x74, 0x6f, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2e, 0x42,
+ 0x65, 0x67, 0x69, 0x6e, 0x46, 0x72, 0x61, 0x6d, 0x65, 0x41, 0x72, 0x67,
+ 0x73, 0x2e, 0x42, 0x65, 0x67, 0x69, 0x6e, 0x46, 0x72, 0x61, 0x6d, 0x65,
+ 0x41, 0x72, 0x67, 0x73, 0x54, 0x79, 0x70, 0x65, 0x52, 0x04, 0x74, 0x79,
+ 0x70, 0x65, 0x12, 0x1b, 0x0a, 0x09, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65,
+ 0x5f, 0x69, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x04, 0x52, 0x08, 0x73,
+ 0x6f, 0x75, 0x72, 0x63, 0x65, 0x49, 0x64, 0x12, 0x27, 0x0a, 0x0f, 0x73,
+ 0x65, 0x71, 0x75, 0x65, 0x6e, 0x63, 0x65, 0x5f, 0x6e, 0x75, 0x6d, 0x62,
+ 0x65, 0x72, 0x18, 0x03, 0x20, 0x01, 0x28, 0x04, 0x52, 0x0e, 0x73, 0x65,
+ 0x71, 0x75, 0x65, 0x6e, 0x63, 0x65, 0x4e, 0x75, 0x6d, 0x62, 0x65, 0x72,
+ 0x12, 0x22, 0x0a, 0x0d, 0x66, 0x72, 0x61, 0x6d, 0x65, 0x5f, 0x74, 0x69,
+ 0x6d, 0x65, 0x5f, 0x75, 0x73, 0x18, 0x04, 0x20, 0x01, 0x28, 0x03, 0x52,
+ 0x0b, 0x66, 0x72, 0x61, 0x6d, 0x65, 0x54, 0x69, 0x6d, 0x65, 0x55, 0x73,
+ 0x12, 0x1f, 0x0a, 0x0b, 0x64, 0x65, 0x61, 0x64, 0x6c, 0x69, 0x6e, 0x65,
+ 0x5f, 0x75, 0x73, 0x18, 0x05, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0a, 0x64,
+ 0x65, 0x61, 0x64, 0x6c, 0x69, 0x6e, 0x65, 0x55, 0x73, 0x12, 0x2a, 0x0a,
+ 0x11, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x76, 0x61, 0x6c, 0x5f, 0x64, 0x65,
+ 0x6c, 0x74, 0x61, 0x5f, 0x75, 0x73, 0x18, 0x06, 0x20, 0x01, 0x28, 0x03,
+ 0x52, 0x0f, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x76, 0x61, 0x6c, 0x44, 0x65,
+ 0x6c, 0x74, 0x61, 0x55, 0x73, 0x12, 0x28, 0x0a, 0x10, 0x6f, 0x6e, 0x5f,
+ 0x63, 0x72, 0x69, 0x74, 0x69, 0x63, 0x61, 0x6c, 0x5f, 0x70, 0x61, 0x74,
+ 0x68, 0x18, 0x07, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0e, 0x6f, 0x6e, 0x43,
+ 0x72, 0x69, 0x74, 0x69, 0x63, 0x61, 0x6c, 0x50, 0x61, 0x74, 0x68, 0x12,
+ 0x21, 0x0a, 0x0c, 0x61, 0x6e, 0x69, 0x6d, 0x61, 0x74, 0x65, 0x5f, 0x6f,
+ 0x6e, 0x6c, 0x79, 0x18, 0x08, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0b, 0x61,
+ 0x6e, 0x69, 0x6d, 0x61, 0x74, 0x65, 0x4f, 0x6e, 0x6c, 0x79, 0x12, 0x30,
+ 0x0a, 0x13, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x5f, 0x6c, 0x6f, 0x63,
+ 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x69, 0x69, 0x64, 0x18, 0x09, 0x20,
+ 0x01, 0x28, 0x04, 0x48, 0x00, 0x52, 0x11, 0x73, 0x6f, 0x75, 0x72, 0x63,
+ 0x65, 0x4c, 0x6f, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x49, 0x69, 0x64,
+ 0x12, 0x4a, 0x0a, 0x0f, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x5f, 0x6c,
+ 0x6f, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x0a, 0x20, 0x01, 0x28,
+ 0x0b, 0x32, 0x1f, 0x2e, 0x70, 0x65, 0x72, 0x66, 0x65, 0x74, 0x74, 0x6f,
+ 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2e, 0x53, 0x6f, 0x75, 0x72,
+ 0x63, 0x65, 0x4c, 0x6f, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x48, 0x00,
+ 0x52, 0x0e, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x4c, 0x6f, 0x63, 0x61,
+ 0x74, 0x69, 0x6f, 0x6e, 0x22, 0xa2, 0x01, 0x0a, 0x12, 0x42, 0x65, 0x67,
+ 0x69, 0x6e, 0x46, 0x72, 0x61, 0x6d, 0x65, 0x41, 0x72, 0x67, 0x73, 0x54,
+ 0x79, 0x70, 0x65, 0x12, 0x25, 0x0a, 0x21, 0x42, 0x45, 0x47, 0x49, 0x4e,
+ 0x5f, 0x46, 0x52, 0x41, 0x4d, 0x45, 0x5f, 0x41, 0x52, 0x47, 0x53, 0x5f,
+ 0x54, 0x59, 0x50, 0x45, 0x5f, 0x55, 0x4e, 0x53, 0x50, 0x45, 0x43, 0x49,
+ 0x46, 0x49, 0x45, 0x44, 0x10, 0x00, 0x12, 0x21, 0x0a, 0x1d, 0x42, 0x45,
+ 0x47, 0x49, 0x4e, 0x5f, 0x46, 0x52, 0x41, 0x4d, 0x45, 0x5f, 0x41, 0x52,
+ 0x47, 0x53, 0x5f, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x49, 0x4e, 0x56, 0x41,
+ 0x4c, 0x49, 0x44, 0x10, 0x01, 0x12, 0x20, 0x0a, 0x1c, 0x42, 0x45, 0x47,
+ 0x49, 0x4e, 0x5f, 0x46, 0x52, 0x41, 0x4d, 0x45, 0x5f, 0x41, 0x52, 0x47,
+ 0x53, 0x5f, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x4e, 0x4f, 0x52, 0x4d, 0x41,
+ 0x4c, 0x10, 0x02, 0x12, 0x20, 0x0a, 0x1c, 0x42, 0x45, 0x47, 0x49, 0x4e,
+ 0x5f, 0x46, 0x52, 0x41, 0x4d, 0x45, 0x5f, 0x41, 0x52, 0x47, 0x53, 0x5f,
+ 0x54, 0x59, 0x50, 0x45, 0x5f, 0x4d, 0x49, 0x53, 0x53, 0x45, 0x44, 0x10,
+ 0x03, 0x42, 0x0e, 0x0a, 0x0c, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x64,
+ 0x5f, 0x66, 0x72, 0x6f, 0x6d, 0x22, 0xf5, 0x05, 0x0a, 0x12, 0x42, 0x65,
+ 0x67, 0x69, 0x6e, 0x49, 0x6d, 0x70, 0x6c, 0x46, 0x72, 0x61, 0x6d, 0x65,
+ 0x41, 0x72, 0x67, 0x73, 0x12, 0x22, 0x0a, 0x0d, 0x75, 0x70, 0x64, 0x61,
+ 0x74, 0x65, 0x64, 0x5f, 0x61, 0x74, 0x5f, 0x75, 0x73, 0x18, 0x01, 0x20,
+ 0x01, 0x28, 0x03, 0x52, 0x0b, 0x75, 0x70, 0x64, 0x61, 0x74, 0x65, 0x64,
+ 0x41, 0x74, 0x55, 0x73, 0x12, 0x24, 0x0a, 0x0e, 0x66, 0x69, 0x6e, 0x69,
+ 0x73, 0x68, 0x65, 0x64, 0x5f, 0x61, 0x74, 0x5f, 0x75, 0x73, 0x18, 0x02,
+ 0x20, 0x01, 0x28, 0x03, 0x52, 0x0c, 0x66, 0x69, 0x6e, 0x69, 0x73, 0x68,
+ 0x65, 0x64, 0x41, 0x74, 0x55, 0x73, 0x12, 0x3f, 0x0a, 0x05, 0x73, 0x74,
+ 0x61, 0x74, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x29, 0x2e,
+ 0x70, 0x65, 0x72, 0x66, 0x65, 0x74, 0x74, 0x6f, 0x2e, 0x70, 0x72, 0x6f,
+ 0x74, 0x6f, 0x73, 0x2e, 0x42, 0x65, 0x67, 0x69, 0x6e, 0x49, 0x6d, 0x70,
+ 0x6c, 0x46, 0x72, 0x61, 0x6d, 0x65, 0x41, 0x72, 0x67, 0x73, 0x2e, 0x53,
+ 0x74, 0x61, 0x74, 0x65, 0x52, 0x05, 0x73, 0x74, 0x61, 0x74, 0x65, 0x12,
+ 0x44, 0x0a, 0x0c, 0x63, 0x75, 0x72, 0x72, 0x65, 0x6e, 0x74, 0x5f, 0x61,
+ 0x72, 0x67, 0x73, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1f, 0x2e,
0x70, 0x65, 0x72, 0x66, 0x65, 0x74, 0x74, 0x6f, 0x2e, 0x70, 0x72, 0x6f,
0x74, 0x6f, 0x73, 0x2e, 0x42, 0x65, 0x67, 0x69, 0x6e, 0x46, 0x72, 0x61,
- 0x6d, 0x65, 0x41, 0x72, 0x67, 0x73, 0x52, 0x12, 0x6c, 0x61, 0x73, 0x74,
- 0x42, 0x65, 0x67, 0x69, 0x6e, 0x46, 0x72, 0x61, 0x6d, 0x65, 0x41, 0x72,
- 0x67, 0x73, 0x22, 0xc5, 0x01, 0x0a, 0x15, 0x42, 0x65, 0x67, 0x69, 0x6e,
- 0x46, 0x72, 0x61, 0x6d, 0x65, 0x53, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x53,
- 0x74, 0x61, 0x74, 0x65, 0x12, 0x1b, 0x0a, 0x09, 0x73, 0x6f, 0x75, 0x72,
- 0x63, 0x65, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0d, 0x52,
- 0x08, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x49, 0x64, 0x12, 0x16, 0x0a,
- 0x06, 0x70, 0x61, 0x75, 0x73, 0x65, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28,
- 0x08, 0x52, 0x06, 0x70, 0x61, 0x75, 0x73, 0x65, 0x64, 0x12, 0x23, 0x0a,
- 0x0d, 0x6e, 0x75, 0x6d, 0x5f, 0x6f, 0x62, 0x73, 0x65, 0x72, 0x76, 0x65,
- 0x72, 0x73, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x0c, 0x6e, 0x75,
- 0x6d, 0x4f, 0x62, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x73, 0x12, 0x52,
+ 0x6d, 0x65, 0x41, 0x72, 0x67, 0x73, 0x48, 0x00, 0x52, 0x0b, 0x63, 0x75,
+ 0x72, 0x72, 0x65, 0x6e, 0x74, 0x41, 0x72, 0x67, 0x73, 0x12, 0x3e, 0x0a,
+ 0x09, 0x6c, 0x61, 0x73, 0x74, 0x5f, 0x61, 0x72, 0x67, 0x73, 0x18, 0x05,
+ 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1f, 0x2e, 0x70, 0x65, 0x72, 0x66, 0x65,
+ 0x74, 0x74, 0x6f, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2e, 0x42,
+ 0x65, 0x67, 0x69, 0x6e, 0x46, 0x72, 0x61, 0x6d, 0x65, 0x41, 0x72, 0x67,
+ 0x73, 0x48, 0x00, 0x52, 0x08, 0x6c, 0x61, 0x73, 0x74, 0x41, 0x72, 0x67,
+ 0x73, 0x12, 0x5c, 0x0a, 0x10, 0x74, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61,
+ 0x6d, 0x70, 0x73, 0x5f, 0x69, 0x6e, 0x5f, 0x75, 0x73, 0x18, 0x06, 0x20,
+ 0x01, 0x28, 0x0b, 0x32, 0x32, 0x2e, 0x70, 0x65, 0x72, 0x66, 0x65, 0x74,
+ 0x74, 0x6f, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2e, 0x42, 0x65,
+ 0x67, 0x69, 0x6e, 0x49, 0x6d, 0x70, 0x6c, 0x46, 0x72, 0x61, 0x6d, 0x65,
+ 0x41, 0x72, 0x67, 0x73, 0x2e, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61,
+ 0x6d, 0x70, 0x73, 0x49, 0x6e, 0x55, 0x73, 0x52, 0x0e, 0x74, 0x69, 0x6d,
+ 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x73, 0x49, 0x6e, 0x55, 0x73, 0x1a,
+ 0xad, 0x02, 0x0a, 0x0e, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d,
+ 0x70, 0x73, 0x49, 0x6e, 0x55, 0x73, 0x12, 0x25, 0x0a, 0x0e, 0x69, 0x6e,
+ 0x74, 0x65, 0x72, 0x76, 0x61, 0x6c, 0x5f, 0x64, 0x65, 0x6c, 0x74, 0x61,
+ 0x18, 0x01, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0d, 0x69, 0x6e, 0x74, 0x65,
+ 0x72, 0x76, 0x61, 0x6c, 0x44, 0x65, 0x6c, 0x74, 0x61, 0x12, 0x31, 0x0a,
+ 0x15, 0x6e, 0x6f, 0x77, 0x5f, 0x74, 0x6f, 0x5f, 0x64, 0x65, 0x61, 0x64,
+ 0x6c, 0x69, 0x6e, 0x65, 0x5f, 0x64, 0x65, 0x6c, 0x74, 0x61, 0x18, 0x02,
+ 0x20, 0x01, 0x28, 0x03, 0x52, 0x12, 0x6e, 0x6f, 0x77, 0x54, 0x6f, 0x44,
+ 0x65, 0x61, 0x64, 0x6c, 0x69, 0x6e, 0x65, 0x44, 0x65, 0x6c, 0x74, 0x61,
+ 0x12, 0x34, 0x0a, 0x17, 0x66, 0x72, 0x61, 0x6d, 0x65, 0x5f, 0x74, 0x69,
+ 0x6d, 0x65, 0x5f, 0x74, 0x6f, 0x5f, 0x6e, 0x6f, 0x77, 0x5f, 0x64, 0x65,
+ 0x6c, 0x74, 0x61, 0x18, 0x03, 0x20, 0x01, 0x28, 0x03, 0x52, 0x13, 0x66,
+ 0x72, 0x61, 0x6d, 0x65, 0x54, 0x69, 0x6d, 0x65, 0x54, 0x6f, 0x4e, 0x6f,
+ 0x77, 0x44, 0x65, 0x6c, 0x74, 0x61, 0x12, 0x3e, 0x0a, 0x1c, 0x66, 0x72,
+ 0x61, 0x6d, 0x65, 0x5f, 0x74, 0x69, 0x6d, 0x65, 0x5f, 0x74, 0x6f, 0x5f,
+ 0x64, 0x65, 0x61, 0x64, 0x6c, 0x69, 0x6e, 0x65, 0x5f, 0x64, 0x65, 0x6c,
+ 0x74, 0x61, 0x18, 0x04, 0x20, 0x01, 0x28, 0x03, 0x52, 0x18, 0x66, 0x72,
+ 0x61, 0x6d, 0x65, 0x54, 0x69, 0x6d, 0x65, 0x54, 0x6f, 0x44, 0x65, 0x61,
+ 0x64, 0x6c, 0x69, 0x6e, 0x65, 0x44, 0x65, 0x6c, 0x74, 0x61, 0x12, 0x10,
+ 0x0a, 0x03, 0x6e, 0x6f, 0x77, 0x18, 0x05, 0x20, 0x01, 0x28, 0x03, 0x52,
+ 0x03, 0x6e, 0x6f, 0x77, 0x12, 0x1d, 0x0a, 0x0a, 0x66, 0x72, 0x61, 0x6d,
+ 0x65, 0x5f, 0x74, 0x69, 0x6d, 0x65, 0x18, 0x06, 0x20, 0x01, 0x28, 0x03,
+ 0x52, 0x09, 0x66, 0x72, 0x61, 0x6d, 0x65, 0x54, 0x69, 0x6d, 0x65, 0x12,
+ 0x1a, 0x0a, 0x08, 0x64, 0x65, 0x61, 0x64, 0x6c, 0x69, 0x6e, 0x65, 0x18,
+ 0x07, 0x20, 0x01, 0x28, 0x03, 0x52, 0x08, 0x64, 0x65, 0x61, 0x64, 0x6c,
+ 0x69, 0x6e, 0x65, 0x22, 0x38, 0x0a, 0x05, 0x53, 0x74, 0x61, 0x74, 0x65,
+ 0x12, 0x18, 0x0a, 0x14, 0x42, 0x45, 0x47, 0x49, 0x4e, 0x5f, 0x46, 0x52,
+ 0x41, 0x4d, 0x45, 0x5f, 0x46, 0x49, 0x4e, 0x49, 0x53, 0x48, 0x45, 0x44,
+ 0x10, 0x00, 0x12, 0x15, 0x0a, 0x11, 0x42, 0x45, 0x47, 0x49, 0x4e, 0x5f,
+ 0x46, 0x52, 0x41, 0x4d, 0x45, 0x5f, 0x55, 0x53, 0x49, 0x4e, 0x47, 0x10,
+ 0x01, 0x42, 0x06, 0x0a, 0x04, 0x61, 0x72, 0x67, 0x73, 0x22, 0xa6, 0x01,
+ 0x0a, 0x17, 0x42, 0x65, 0x67, 0x69, 0x6e, 0x46, 0x72, 0x61, 0x6d, 0x65,
+ 0x4f, 0x62, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x53, 0x74, 0x61, 0x74,
+ 0x65, 0x12, 0x37, 0x0a, 0x18, 0x64, 0x72, 0x6f, 0x70, 0x70, 0x65, 0x64,
+ 0x5f, 0x62, 0x65, 0x67, 0x69, 0x6e, 0x5f, 0x66, 0x72, 0x61, 0x6d, 0x65,
+ 0x5f, 0x61, 0x72, 0x67, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x03, 0x52,
+ 0x15, 0x64, 0x72, 0x6f, 0x70, 0x70, 0x65, 0x64, 0x42, 0x65, 0x67, 0x69,
+ 0x6e, 0x46, 0x72, 0x61, 0x6d, 0x65, 0x41, 0x72, 0x67, 0x73, 0x12, 0x52,
0x0a, 0x15, 0x6c, 0x61, 0x73, 0x74, 0x5f, 0x62, 0x65, 0x67, 0x69, 0x6e,
0x5f, 0x66, 0x72, 0x61, 0x6d, 0x65, 0x5f, 0x61, 0x72, 0x67, 0x73, 0x18,
- 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1f, 0x2e, 0x70, 0x65, 0x72, 0x66,
+ 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1f, 0x2e, 0x70, 0x65, 0x72, 0x66,
0x65, 0x74, 0x74, 0x6f, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2e,
0x42, 0x65, 0x67, 0x69, 0x6e, 0x46, 0x72, 0x61, 0x6d, 0x65, 0x41, 0x72,
0x67, 0x73, 0x52, 0x12, 0x6c, 0x61, 0x73, 0x74, 0x42, 0x65, 0x67, 0x69,
- 0x6e, 0x46, 0x72, 0x61, 0x6d, 0x65, 0x41, 0x72, 0x67, 0x73, 0x22, 0xfd,
- 0x04, 0x0a, 0x17, 0x43, 0x6f, 0x6d, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x6f,
- 0x72, 0x54, 0x69, 0x6d, 0x69, 0x6e, 0x67, 0x48, 0x69, 0x73, 0x74, 0x6f,
- 0x72, 0x79, 0x12, 0x65, 0x0a, 0x31, 0x62, 0x65, 0x67, 0x69, 0x6e, 0x5f,
- 0x6d, 0x61, 0x69, 0x6e, 0x5f, 0x66, 0x72, 0x61, 0x6d, 0x65, 0x5f, 0x71,
- 0x75, 0x65, 0x75, 0x65, 0x5f, 0x63, 0x72, 0x69, 0x74, 0x69, 0x63, 0x61,
- 0x6c, 0x5f, 0x65, 0x73, 0x74, 0x69, 0x6d, 0x61, 0x74, 0x65, 0x5f, 0x64,
- 0x65, 0x6c, 0x74, 0x61, 0x5f, 0x75, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28,
- 0x03, 0x52, 0x2a, 0x62, 0x65, 0x67, 0x69, 0x6e, 0x4d, 0x61, 0x69, 0x6e,
- 0x46, 0x72, 0x61, 0x6d, 0x65, 0x51, 0x75, 0x65, 0x75, 0x65, 0x43, 0x72,
- 0x69, 0x74, 0x69, 0x63, 0x61, 0x6c, 0x45, 0x73, 0x74, 0x69, 0x6d, 0x61,
- 0x74, 0x65, 0x44, 0x65, 0x6c, 0x74, 0x61, 0x55, 0x73, 0x12, 0x6c, 0x0a,
- 0x35, 0x62, 0x65, 0x67, 0x69, 0x6e, 0x5f, 0x6d, 0x61, 0x69, 0x6e, 0x5f,
- 0x66, 0x72, 0x61, 0x6d, 0x65, 0x5f, 0x71, 0x75, 0x65, 0x75, 0x65, 0x5f,
- 0x6e, 0x6f, 0x74, 0x5f, 0x63, 0x72, 0x69, 0x74, 0x69, 0x63, 0x61, 0x6c,
- 0x5f, 0x65, 0x73, 0x74, 0x69, 0x6d, 0x61, 0x74, 0x65, 0x5f, 0x64, 0x65,
- 0x6c, 0x74, 0x61, 0x5f, 0x75, 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x03,
- 0x52, 0x2d, 0x62, 0x65, 0x67, 0x69, 0x6e, 0x4d, 0x61, 0x69, 0x6e, 0x46,
- 0x72, 0x61, 0x6d, 0x65, 0x51, 0x75, 0x65, 0x75, 0x65, 0x4e, 0x6f, 0x74,
- 0x43, 0x72, 0x69, 0x74, 0x69, 0x63, 0x61, 0x6c, 0x45, 0x73, 0x74, 0x69,
- 0x6d, 0x61, 0x74, 0x65, 0x44, 0x65, 0x6c, 0x74, 0x61, 0x55, 0x73, 0x12,
- 0x76, 0x0a, 0x3b, 0x62, 0x65, 0x67, 0x69, 0x6e, 0x5f, 0x6d, 0x61, 0x69,
- 0x6e, 0x5f, 0x66, 0x72, 0x61, 0x6d, 0x65, 0x5f, 0x73, 0x74, 0x61, 0x72,
- 0x74, 0x5f, 0x74, 0x6f, 0x5f, 0x72, 0x65, 0x61, 0x64, 0x79, 0x5f, 0x74,
- 0x6f, 0x5f, 0x63, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x5f, 0x65, 0x73, 0x74,
+ 0x6e, 0x46, 0x72, 0x61, 0x6d, 0x65, 0x41, 0x72, 0x67, 0x73, 0x22, 0xc5,
+ 0x01, 0x0a, 0x15, 0x42, 0x65, 0x67, 0x69, 0x6e, 0x46, 0x72, 0x61, 0x6d,
+ 0x65, 0x53, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x53, 0x74, 0x61, 0x74, 0x65,
+ 0x12, 0x1b, 0x0a, 0x09, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x5f, 0x69,
+ 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x08, 0x73, 0x6f, 0x75,
+ 0x72, 0x63, 0x65, 0x49, 0x64, 0x12, 0x16, 0x0a, 0x06, 0x70, 0x61, 0x75,
+ 0x73, 0x65, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x08, 0x52, 0x06, 0x70,
+ 0x61, 0x75, 0x73, 0x65, 0x64, 0x12, 0x23, 0x0a, 0x0d, 0x6e, 0x75, 0x6d,
+ 0x5f, 0x6f, 0x62, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x73, 0x18, 0x03,
+ 0x20, 0x01, 0x28, 0x0d, 0x52, 0x0c, 0x6e, 0x75, 0x6d, 0x4f, 0x62, 0x73,
+ 0x65, 0x72, 0x76, 0x65, 0x72, 0x73, 0x12, 0x52, 0x0a, 0x15, 0x6c, 0x61,
+ 0x73, 0x74, 0x5f, 0x62, 0x65, 0x67, 0x69, 0x6e, 0x5f, 0x66, 0x72, 0x61,
+ 0x6d, 0x65, 0x5f, 0x61, 0x72, 0x67, 0x73, 0x18, 0x04, 0x20, 0x01, 0x28,
+ 0x0b, 0x32, 0x1f, 0x2e, 0x70, 0x65, 0x72, 0x66, 0x65, 0x74, 0x74, 0x6f,
+ 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2e, 0x42, 0x65, 0x67, 0x69,
+ 0x6e, 0x46, 0x72, 0x61, 0x6d, 0x65, 0x41, 0x72, 0x67, 0x73, 0x52, 0x12,
+ 0x6c, 0x61, 0x73, 0x74, 0x42, 0x65, 0x67, 0x69, 0x6e, 0x46, 0x72, 0x61,
+ 0x6d, 0x65, 0x41, 0x72, 0x67, 0x73, 0x22, 0xfd, 0x04, 0x0a, 0x17, 0x43,
+ 0x6f, 0x6d, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x6f, 0x72, 0x54, 0x69, 0x6d,
+ 0x69, 0x6e, 0x67, 0x48, 0x69, 0x73, 0x74, 0x6f, 0x72, 0x79, 0x12, 0x65,
+ 0x0a, 0x31, 0x62, 0x65, 0x67, 0x69, 0x6e, 0x5f, 0x6d, 0x61, 0x69, 0x6e,
+ 0x5f, 0x66, 0x72, 0x61, 0x6d, 0x65, 0x5f, 0x71, 0x75, 0x65, 0x75, 0x65,
+ 0x5f, 0x63, 0x72, 0x69, 0x74, 0x69, 0x63, 0x61, 0x6c, 0x5f, 0x65, 0x73,
+ 0x74, 0x69, 0x6d, 0x61, 0x74, 0x65, 0x5f, 0x64, 0x65, 0x6c, 0x74, 0x61,
+ 0x5f, 0x75, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x03, 0x52, 0x2a, 0x62,
+ 0x65, 0x67, 0x69, 0x6e, 0x4d, 0x61, 0x69, 0x6e, 0x46, 0x72, 0x61, 0x6d,
+ 0x65, 0x51, 0x75, 0x65, 0x75, 0x65, 0x43, 0x72, 0x69, 0x74, 0x69, 0x63,
+ 0x61, 0x6c, 0x45, 0x73, 0x74, 0x69, 0x6d, 0x61, 0x74, 0x65, 0x44, 0x65,
+ 0x6c, 0x74, 0x61, 0x55, 0x73, 0x12, 0x6c, 0x0a, 0x35, 0x62, 0x65, 0x67,
+ 0x69, 0x6e, 0x5f, 0x6d, 0x61, 0x69, 0x6e, 0x5f, 0x66, 0x72, 0x61, 0x6d,
+ 0x65, 0x5f, 0x71, 0x75, 0x65, 0x75, 0x65, 0x5f, 0x6e, 0x6f, 0x74, 0x5f,
+ 0x63, 0x72, 0x69, 0x74, 0x69, 0x63, 0x61, 0x6c, 0x5f, 0x65, 0x73, 0x74,
0x69, 0x6d, 0x61, 0x74, 0x65, 0x5f, 0x64, 0x65, 0x6c, 0x74, 0x61, 0x5f,
- 0x75, 0x73, 0x18, 0x03, 0x20, 0x01, 0x28, 0x03, 0x52, 0x31, 0x62, 0x65,
+ 0x75, 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x03, 0x52, 0x2d, 0x62, 0x65,
0x67, 0x69, 0x6e, 0x4d, 0x61, 0x69, 0x6e, 0x46, 0x72, 0x61, 0x6d, 0x65,
- 0x53, 0x74, 0x61, 0x72, 0x74, 0x54, 0x6f, 0x52, 0x65, 0x61, 0x64, 0x79,
- 0x54, 0x6f, 0x43, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x45, 0x73, 0x74, 0x69,
- 0x6d, 0x61, 0x74, 0x65, 0x44, 0x65, 0x6c, 0x74, 0x61, 0x55, 0x73, 0x12,
- 0x5d, 0x0a, 0x2d, 0x63, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x5f, 0x74, 0x6f,
- 0x5f, 0x72, 0x65, 0x61, 0x64, 0x79, 0x5f, 0x74, 0x6f, 0x5f, 0x61, 0x63,
- 0x74, 0x69, 0x76, 0x61, 0x74, 0x65, 0x5f, 0x65, 0x73, 0x74, 0x69, 0x6d,
- 0x61, 0x74, 0x65, 0x5f, 0x64, 0x65, 0x6c, 0x74, 0x61, 0x5f, 0x75, 0x73,
- 0x18, 0x04, 0x20, 0x01, 0x28, 0x03, 0x52, 0x26, 0x63, 0x6f, 0x6d, 0x6d,
- 0x69, 0x74, 0x54, 0x6f, 0x52, 0x65, 0x61, 0x64, 0x79, 0x54, 0x6f, 0x41,
- 0x63, 0x74, 0x69, 0x76, 0x61, 0x74, 0x65, 0x45, 0x73, 0x74, 0x69, 0x6d,
- 0x61, 0x74, 0x65, 0x44, 0x65, 0x6c, 0x74, 0x61, 0x55, 0x73, 0x12, 0x44,
- 0x0a, 0x1f, 0x70, 0x72, 0x65, 0x70, 0x61, 0x72, 0x65, 0x5f, 0x74, 0x69,
- 0x6c, 0x65, 0x73, 0x5f, 0x65, 0x73, 0x74, 0x69, 0x6d, 0x61, 0x74, 0x65,
- 0x5f, 0x64, 0x65, 0x6c, 0x74, 0x61, 0x5f, 0x75, 0x73, 0x18, 0x05, 0x20,
- 0x01, 0x28, 0x03, 0x52, 0x1b, 0x70, 0x72, 0x65, 0x70, 0x61, 0x72, 0x65,
- 0x54, 0x69, 0x6c, 0x65, 0x73, 0x45, 0x73, 0x74, 0x69, 0x6d, 0x61, 0x74,
- 0x65, 0x44, 0x65, 0x6c, 0x74, 0x61, 0x55, 0x73, 0x12, 0x3b, 0x0a, 0x1a,
- 0x61, 0x63, 0x74, 0x69, 0x76, 0x61, 0x74, 0x65, 0x5f, 0x65, 0x73, 0x74,
- 0x69, 0x6d, 0x61, 0x74, 0x65, 0x5f, 0x64, 0x65, 0x6c, 0x74, 0x61, 0x5f,
- 0x75, 0x73, 0x18, 0x06, 0x20, 0x01, 0x28, 0x03, 0x52, 0x17, 0x61, 0x63,
- 0x74, 0x69, 0x76, 0x61, 0x74, 0x65, 0x45, 0x73, 0x74, 0x69, 0x6d, 0x61,
- 0x74, 0x65, 0x44, 0x65, 0x6c, 0x74, 0x61, 0x55, 0x73, 0x12, 0x33, 0x0a,
- 0x16, 0x64, 0x72, 0x61, 0x77, 0x5f, 0x65, 0x73, 0x74, 0x69, 0x6d, 0x61,
- 0x74, 0x65, 0x5f, 0x64, 0x65, 0x6c, 0x74, 0x61, 0x5f, 0x75, 0x73, 0x18,
- 0x07, 0x20, 0x01, 0x28, 0x03, 0x52, 0x13, 0x64, 0x72, 0x61, 0x77, 0x45,
- 0x73, 0x74, 0x69, 0x6d, 0x61, 0x74, 0x65, 0x44, 0x65, 0x6c, 0x74, 0x61,
- 0x55, 0x73, 0x2a, 0xb0, 0x05, 0x0a, 0x1f, 0x43, 0x68, 0x72, 0x6f, 0x6d,
- 0x65, 0x43, 0x6f, 0x6d, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x6f, 0x72, 0x53,
- 0x63, 0x68, 0x65, 0x64, 0x75, 0x6c, 0x65, 0x72, 0x41, 0x63, 0x74, 0x69,
- 0x6f, 0x6e, 0x12, 0x23, 0x0a, 0x1f, 0x43, 0x43, 0x5f, 0x53, 0x43, 0x48,
- 0x45, 0x44, 0x55, 0x4c, 0x45, 0x52, 0x5f, 0x41, 0x43, 0x54, 0x49, 0x4f,
- 0x4e, 0x5f, 0x55, 0x4e, 0x53, 0x50, 0x45, 0x43, 0x49, 0x46, 0x49, 0x45,
- 0x44, 0x10, 0x00, 0x12, 0x1c, 0x0a, 0x18, 0x43, 0x43, 0x5f, 0x53, 0x43,
- 0x48, 0x45, 0x44, 0x55, 0x4c, 0x45, 0x52, 0x5f, 0x41, 0x43, 0x54, 0x49,
- 0x4f, 0x4e, 0x5f, 0x4e, 0x4f, 0x4e, 0x45, 0x10, 0x01, 0x12, 0x2d, 0x0a,
- 0x29, 0x43, 0x43, 0x5f, 0x53, 0x43, 0x48, 0x45, 0x44, 0x55, 0x4c, 0x45,
- 0x52, 0x5f, 0x41, 0x43, 0x54, 0x49, 0x4f, 0x4e, 0x5f, 0x53, 0x45, 0x4e,
- 0x44, 0x5f, 0x42, 0x45, 0x47, 0x49, 0x4e, 0x5f, 0x4d, 0x41, 0x49, 0x4e,
- 0x5f, 0x46, 0x52, 0x41, 0x4d, 0x45, 0x10, 0x02, 0x12, 0x1e, 0x0a, 0x1a,
- 0x43, 0x43, 0x5f, 0x53, 0x43, 0x48, 0x45, 0x44, 0x55, 0x4c, 0x45, 0x52,
- 0x5f, 0x41, 0x43, 0x54, 0x49, 0x4f, 0x4e, 0x5f, 0x43, 0x4f, 0x4d, 0x4d,
- 0x49, 0x54, 0x10, 0x03, 0x12, 0x2a, 0x0a, 0x26, 0x43, 0x43, 0x5f, 0x53,
+ 0x51, 0x75, 0x65, 0x75, 0x65, 0x4e, 0x6f, 0x74, 0x43, 0x72, 0x69, 0x74,
+ 0x69, 0x63, 0x61, 0x6c, 0x45, 0x73, 0x74, 0x69, 0x6d, 0x61, 0x74, 0x65,
+ 0x44, 0x65, 0x6c, 0x74, 0x61, 0x55, 0x73, 0x12, 0x76, 0x0a, 0x3b, 0x62,
+ 0x65, 0x67, 0x69, 0x6e, 0x5f, 0x6d, 0x61, 0x69, 0x6e, 0x5f, 0x66, 0x72,
+ 0x61, 0x6d, 0x65, 0x5f, 0x73, 0x74, 0x61, 0x72, 0x74, 0x5f, 0x74, 0x6f,
+ 0x5f, 0x72, 0x65, 0x61, 0x64, 0x79, 0x5f, 0x74, 0x6f, 0x5f, 0x63, 0x6f,
+ 0x6d, 0x6d, 0x69, 0x74, 0x5f, 0x65, 0x73, 0x74, 0x69, 0x6d, 0x61, 0x74,
+ 0x65, 0x5f, 0x64, 0x65, 0x6c, 0x74, 0x61, 0x5f, 0x75, 0x73, 0x18, 0x03,
+ 0x20, 0x01, 0x28, 0x03, 0x52, 0x31, 0x62, 0x65, 0x67, 0x69, 0x6e, 0x4d,
+ 0x61, 0x69, 0x6e, 0x46, 0x72, 0x61, 0x6d, 0x65, 0x53, 0x74, 0x61, 0x72,
+ 0x74, 0x54, 0x6f, 0x52, 0x65, 0x61, 0x64, 0x79, 0x54, 0x6f, 0x43, 0x6f,
+ 0x6d, 0x6d, 0x69, 0x74, 0x45, 0x73, 0x74, 0x69, 0x6d, 0x61, 0x74, 0x65,
+ 0x44, 0x65, 0x6c, 0x74, 0x61, 0x55, 0x73, 0x12, 0x5d, 0x0a, 0x2d, 0x63,
+ 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x5f, 0x74, 0x6f, 0x5f, 0x72, 0x65, 0x61,
+ 0x64, 0x79, 0x5f, 0x74, 0x6f, 0x5f, 0x61, 0x63, 0x74, 0x69, 0x76, 0x61,
+ 0x74, 0x65, 0x5f, 0x65, 0x73, 0x74, 0x69, 0x6d, 0x61, 0x74, 0x65, 0x5f,
+ 0x64, 0x65, 0x6c, 0x74, 0x61, 0x5f, 0x75, 0x73, 0x18, 0x04, 0x20, 0x01,
+ 0x28, 0x03, 0x52, 0x26, 0x63, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x54, 0x6f,
+ 0x52, 0x65, 0x61, 0x64, 0x79, 0x54, 0x6f, 0x41, 0x63, 0x74, 0x69, 0x76,
+ 0x61, 0x74, 0x65, 0x45, 0x73, 0x74, 0x69, 0x6d, 0x61, 0x74, 0x65, 0x44,
+ 0x65, 0x6c, 0x74, 0x61, 0x55, 0x73, 0x12, 0x44, 0x0a, 0x1f, 0x70, 0x72,
+ 0x65, 0x70, 0x61, 0x72, 0x65, 0x5f, 0x74, 0x69, 0x6c, 0x65, 0x73, 0x5f,
+ 0x65, 0x73, 0x74, 0x69, 0x6d, 0x61, 0x74, 0x65, 0x5f, 0x64, 0x65, 0x6c,
+ 0x74, 0x61, 0x5f, 0x75, 0x73, 0x18, 0x05, 0x20, 0x01, 0x28, 0x03, 0x52,
+ 0x1b, 0x70, 0x72, 0x65, 0x70, 0x61, 0x72, 0x65, 0x54, 0x69, 0x6c, 0x65,
+ 0x73, 0x45, 0x73, 0x74, 0x69, 0x6d, 0x61, 0x74, 0x65, 0x44, 0x65, 0x6c,
+ 0x74, 0x61, 0x55, 0x73, 0x12, 0x3b, 0x0a, 0x1a, 0x61, 0x63, 0x74, 0x69,
+ 0x76, 0x61, 0x74, 0x65, 0x5f, 0x65, 0x73, 0x74, 0x69, 0x6d, 0x61, 0x74,
+ 0x65, 0x5f, 0x64, 0x65, 0x6c, 0x74, 0x61, 0x5f, 0x75, 0x73, 0x18, 0x06,
+ 0x20, 0x01, 0x28, 0x03, 0x52, 0x17, 0x61, 0x63, 0x74, 0x69, 0x76, 0x61,
+ 0x74, 0x65, 0x45, 0x73, 0x74, 0x69, 0x6d, 0x61, 0x74, 0x65, 0x44, 0x65,
+ 0x6c, 0x74, 0x61, 0x55, 0x73, 0x12, 0x33, 0x0a, 0x16, 0x64, 0x72, 0x61,
+ 0x77, 0x5f, 0x65, 0x73, 0x74, 0x69, 0x6d, 0x61, 0x74, 0x65, 0x5f, 0x64,
+ 0x65, 0x6c, 0x74, 0x61, 0x5f, 0x75, 0x73, 0x18, 0x07, 0x20, 0x01, 0x28,
+ 0x03, 0x52, 0x13, 0x64, 0x72, 0x61, 0x77, 0x45, 0x73, 0x74, 0x69, 0x6d,
+ 0x61, 0x74, 0x65, 0x44, 0x65, 0x6c, 0x74, 0x61, 0x55, 0x73, 0x2a, 0xb0,
+ 0x05, 0x0a, 0x1f, 0x43, 0x68, 0x72, 0x6f, 0x6d, 0x65, 0x43, 0x6f, 0x6d,
+ 0x70, 0x6f, 0x73, 0x69, 0x74, 0x6f, 0x72, 0x53, 0x63, 0x68, 0x65, 0x64,
+ 0x75, 0x6c, 0x65, 0x72, 0x41, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x23,
+ 0x0a, 0x1f, 0x43, 0x43, 0x5f, 0x53, 0x43, 0x48, 0x45, 0x44, 0x55, 0x4c,
+ 0x45, 0x52, 0x5f, 0x41, 0x43, 0x54, 0x49, 0x4f, 0x4e, 0x5f, 0x55, 0x4e,
+ 0x53, 0x50, 0x45, 0x43, 0x49, 0x46, 0x49, 0x45, 0x44, 0x10, 0x00, 0x12,
+ 0x1c, 0x0a, 0x18, 0x43, 0x43, 0x5f, 0x53, 0x43, 0x48, 0x45, 0x44, 0x55,
+ 0x4c, 0x45, 0x52, 0x5f, 0x41, 0x43, 0x54, 0x49, 0x4f, 0x4e, 0x5f, 0x4e,
+ 0x4f, 0x4e, 0x45, 0x10, 0x01, 0x12, 0x2d, 0x0a, 0x29, 0x43, 0x43, 0x5f,
+ 0x53, 0x43, 0x48, 0x45, 0x44, 0x55, 0x4c, 0x45, 0x52, 0x5f, 0x41, 0x43,
+ 0x54, 0x49, 0x4f, 0x4e, 0x5f, 0x53, 0x45, 0x4e, 0x44, 0x5f, 0x42, 0x45,
+ 0x47, 0x49, 0x4e, 0x5f, 0x4d, 0x41, 0x49, 0x4e, 0x5f, 0x46, 0x52, 0x41,
+ 0x4d, 0x45, 0x10, 0x02, 0x12, 0x1e, 0x0a, 0x1a, 0x43, 0x43, 0x5f, 0x53,
0x43, 0x48, 0x45, 0x44, 0x55, 0x4c, 0x45, 0x52, 0x5f, 0x41, 0x43, 0x54,
- 0x49, 0x4f, 0x4e, 0x5f, 0x41, 0x43, 0x54, 0x49, 0x56, 0x41, 0x54, 0x45,
- 0x5f, 0x53, 0x59, 0x4e, 0x43, 0x5f, 0x54, 0x52, 0x45, 0x45, 0x10, 0x04,
- 0x12, 0x28, 0x0a, 0x24, 0x43, 0x43, 0x5f, 0x53, 0x43, 0x48, 0x45, 0x44,
+ 0x49, 0x4f, 0x4e, 0x5f, 0x43, 0x4f, 0x4d, 0x4d, 0x49, 0x54, 0x10, 0x03,
+ 0x12, 0x2a, 0x0a, 0x26, 0x43, 0x43, 0x5f, 0x53, 0x43, 0x48, 0x45, 0x44,
0x55, 0x4c, 0x45, 0x52, 0x5f, 0x41, 0x43, 0x54, 0x49, 0x4f, 0x4e, 0x5f,
- 0x44, 0x52, 0x41, 0x57, 0x5f, 0x49, 0x46, 0x5f, 0x50, 0x4f, 0x53, 0x53,
- 0x49, 0x42, 0x4c, 0x45, 0x10, 0x05, 0x12, 0x23, 0x0a, 0x1f, 0x43, 0x43,
+ 0x41, 0x43, 0x54, 0x49, 0x56, 0x41, 0x54, 0x45, 0x5f, 0x53, 0x59, 0x4e,
+ 0x43, 0x5f, 0x54, 0x52, 0x45, 0x45, 0x10, 0x04, 0x12, 0x28, 0x0a, 0x24,
+ 0x43, 0x43, 0x5f, 0x53, 0x43, 0x48, 0x45, 0x44, 0x55, 0x4c, 0x45, 0x52,
+ 0x5f, 0x41, 0x43, 0x54, 0x49, 0x4f, 0x4e, 0x5f, 0x44, 0x52, 0x41, 0x57,
+ 0x5f, 0x49, 0x46, 0x5f, 0x50, 0x4f, 0x53, 0x53, 0x49, 0x42, 0x4c, 0x45,
+ 0x10, 0x05, 0x12, 0x23, 0x0a, 0x1f, 0x43, 0x43, 0x5f, 0x53, 0x43, 0x48,
+ 0x45, 0x44, 0x55, 0x4c, 0x45, 0x52, 0x5f, 0x41, 0x43, 0x54, 0x49, 0x4f,
+ 0x4e, 0x5f, 0x44, 0x52, 0x41, 0x57, 0x5f, 0x46, 0x4f, 0x52, 0x43, 0x45,
+ 0x44, 0x10, 0x06, 0x12, 0x22, 0x0a, 0x1e, 0x43, 0x43, 0x5f, 0x53, 0x43,
+ 0x48, 0x45, 0x44, 0x55, 0x4c, 0x45, 0x52, 0x5f, 0x41, 0x43, 0x54, 0x49,
+ 0x4f, 0x4e, 0x5f, 0x44, 0x52, 0x41, 0x57, 0x5f, 0x41, 0x42, 0x4f, 0x52,
+ 0x54, 0x10, 0x07, 0x12, 0x3c, 0x0a, 0x38, 0x43, 0x43, 0x5f, 0x53, 0x43,
+ 0x48, 0x45, 0x44, 0x55, 0x4c, 0x45, 0x52, 0x5f, 0x41, 0x43, 0x54, 0x49,
+ 0x4f, 0x4e, 0x5f, 0x42, 0x45, 0x47, 0x49, 0x4e, 0x5f, 0x4c, 0x41, 0x59,
+ 0x45, 0x52, 0x5f, 0x54, 0x52, 0x45, 0x45, 0x5f, 0x46, 0x52, 0x41, 0x4d,
+ 0x45, 0x5f, 0x53, 0x49, 0x4e, 0x4b, 0x5f, 0x43, 0x52, 0x45, 0x41, 0x54,
+ 0x49, 0x4f, 0x4e, 0x10, 0x08, 0x12, 0x25, 0x0a, 0x21, 0x43, 0x43, 0x5f,
+ 0x53, 0x43, 0x48, 0x45, 0x44, 0x55, 0x4c, 0x45, 0x52, 0x5f, 0x41, 0x43,
+ 0x54, 0x49, 0x4f, 0x4e, 0x5f, 0x50, 0x52, 0x45, 0x50, 0x41, 0x52, 0x45,
+ 0x5f, 0x54, 0x49, 0x4c, 0x45, 0x53, 0x10, 0x09, 0x12, 0x38, 0x0a, 0x34,
+ 0x43, 0x43, 0x5f, 0x53, 0x43, 0x48, 0x45, 0x44, 0x55, 0x4c, 0x45, 0x52,
+ 0x5f, 0x41, 0x43, 0x54, 0x49, 0x4f, 0x4e, 0x5f, 0x49, 0x4e, 0x56, 0x41,
+ 0x4c, 0x49, 0x44, 0x41, 0x54, 0x45, 0x5f, 0x4c, 0x41, 0x59, 0x45, 0x52,
+ 0x5f, 0x54, 0x52, 0x45, 0x45, 0x5f, 0x46, 0x52, 0x41, 0x4d, 0x45, 0x5f,
+ 0x53, 0x49, 0x4e, 0x4b, 0x10, 0x0a, 0x12, 0x36, 0x0a, 0x32, 0x43, 0x43,
0x5f, 0x53, 0x43, 0x48, 0x45, 0x44, 0x55, 0x4c, 0x45, 0x52, 0x5f, 0x41,
- 0x43, 0x54, 0x49, 0x4f, 0x4e, 0x5f, 0x44, 0x52, 0x41, 0x57, 0x5f, 0x46,
- 0x4f, 0x52, 0x43, 0x45, 0x44, 0x10, 0x06, 0x12, 0x22, 0x0a, 0x1e, 0x43,
- 0x43, 0x5f, 0x53, 0x43, 0x48, 0x45, 0x44, 0x55, 0x4c, 0x45, 0x52, 0x5f,
- 0x41, 0x43, 0x54, 0x49, 0x4f, 0x4e, 0x5f, 0x44, 0x52, 0x41, 0x57, 0x5f,
- 0x41, 0x42, 0x4f, 0x52, 0x54, 0x10, 0x07, 0x12, 0x3c, 0x0a, 0x38, 0x43,
- 0x43, 0x5f, 0x53, 0x43, 0x48, 0x45, 0x44, 0x55, 0x4c, 0x45, 0x52, 0x5f,
- 0x41, 0x43, 0x54, 0x49, 0x4f, 0x4e, 0x5f, 0x42, 0x45, 0x47, 0x49, 0x4e,
- 0x5f, 0x4c, 0x41, 0x59, 0x45, 0x52, 0x5f, 0x54, 0x52, 0x45, 0x45, 0x5f,
- 0x46, 0x52, 0x41, 0x4d, 0x45, 0x5f, 0x53, 0x49, 0x4e, 0x4b, 0x5f, 0x43,
- 0x52, 0x45, 0x41, 0x54, 0x49, 0x4f, 0x4e, 0x10, 0x08, 0x12, 0x25, 0x0a,
- 0x21, 0x43, 0x43, 0x5f, 0x53, 0x43, 0x48, 0x45, 0x44, 0x55, 0x4c, 0x45,
- 0x52, 0x5f, 0x41, 0x43, 0x54, 0x49, 0x4f, 0x4e, 0x5f, 0x50, 0x52, 0x45,
- 0x50, 0x41, 0x52, 0x45, 0x5f, 0x54, 0x49, 0x4c, 0x45, 0x53, 0x10, 0x09,
- 0x12, 0x38, 0x0a, 0x34, 0x43, 0x43, 0x5f, 0x53, 0x43, 0x48, 0x45, 0x44,
- 0x55, 0x4c, 0x45, 0x52, 0x5f, 0x41, 0x43, 0x54, 0x49, 0x4f, 0x4e, 0x5f,
- 0x49, 0x4e, 0x56, 0x41, 0x4c, 0x49, 0x44, 0x41, 0x54, 0x45, 0x5f, 0x4c,
- 0x41, 0x59, 0x45, 0x52, 0x5f, 0x54, 0x52, 0x45, 0x45, 0x5f, 0x46, 0x52,
- 0x41, 0x4d, 0x45, 0x5f, 0x53, 0x49, 0x4e, 0x4b, 0x10, 0x0a, 0x12, 0x36,
- 0x0a, 0x32, 0x43, 0x43, 0x5f, 0x53, 0x43, 0x48, 0x45, 0x44, 0x55, 0x4c,
- 0x45, 0x52, 0x5f, 0x41, 0x43, 0x54, 0x49, 0x4f, 0x4e, 0x5f, 0x50, 0x45,
- 0x52, 0x46, 0x4f, 0x52, 0x4d, 0x5f, 0x49, 0x4d, 0x50, 0x4c, 0x5f, 0x53,
- 0x49, 0x44, 0x45, 0x5f, 0x49, 0x4e, 0x56, 0x41, 0x4c, 0x49, 0x44, 0x41,
- 0x54, 0x49, 0x4f, 0x4e, 0x10, 0x0b, 0x12, 0x42, 0x0a, 0x3e, 0x43, 0x43,
- 0x5f, 0x53, 0x43, 0x48, 0x45, 0x44, 0x55, 0x4c, 0x45, 0x52, 0x5f, 0x41,
- 0x43, 0x54, 0x49, 0x4f, 0x4e, 0x5f, 0x4e, 0x4f, 0x54, 0x49, 0x46, 0x59,
- 0x5f, 0x42, 0x45, 0x47, 0x49, 0x4e, 0x5f, 0x4d, 0x41, 0x49, 0x4e, 0x5f,
- 0x46, 0x52, 0x41, 0x4d, 0x45, 0x5f, 0x4e, 0x4f, 0x54, 0x5f, 0x45, 0x58,
- 0x50, 0x45, 0x43, 0x54, 0x45, 0x44, 0x5f, 0x55, 0x4e, 0x54, 0x49, 0x4c,
- 0x10, 0x0c, 0x12, 0x41, 0x0a, 0x3d, 0x43, 0x43, 0x5f, 0x53, 0x43, 0x48,
+ 0x43, 0x54, 0x49, 0x4f, 0x4e, 0x5f, 0x50, 0x45, 0x52, 0x46, 0x4f, 0x52,
+ 0x4d, 0x5f, 0x49, 0x4d, 0x50, 0x4c, 0x5f, 0x53, 0x49, 0x44, 0x45, 0x5f,
+ 0x49, 0x4e, 0x56, 0x41, 0x4c, 0x49, 0x44, 0x41, 0x54, 0x49, 0x4f, 0x4e,
+ 0x10, 0x0b, 0x12, 0x42, 0x0a, 0x3e, 0x43, 0x43, 0x5f, 0x53, 0x43, 0x48,
0x45, 0x44, 0x55, 0x4c, 0x45, 0x52, 0x5f, 0x41, 0x43, 0x54, 0x49, 0x4f,
0x4e, 0x5f, 0x4e, 0x4f, 0x54, 0x49, 0x46, 0x59, 0x5f, 0x42, 0x45, 0x47,
0x49, 0x4e, 0x5f, 0x4d, 0x41, 0x49, 0x4e, 0x5f, 0x46, 0x52, 0x41, 0x4d,
0x45, 0x5f, 0x4e, 0x4f, 0x54, 0x5f, 0x45, 0x58, 0x50, 0x45, 0x43, 0x54,
- 0x45, 0x44, 0x5f, 0x53, 0x4f, 0x4f, 0x4e, 0x10, 0x0d, 0x42, 0x02, 0x48,
- 0x03, 0x0a, 0xb8, 0x01, 0x0a, 0x3f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73,
- 0x2f, 0x70, 0x65, 0x72, 0x66, 0x65, 0x74, 0x74, 0x6f, 0x2f, 0x74, 0x72,
- 0x61, 0x63, 0x65, 0x2f, 0x74, 0x72, 0x61, 0x63, 0x6b, 0x5f, 0x65, 0x76,
- 0x65, 0x6e, 0x74, 0x2f, 0x63, 0x68, 0x72, 0x6f, 0x6d, 0x65, 0x5f, 0x68,
- 0x69, 0x73, 0x74, 0x6f, 0x67, 0x72, 0x61, 0x6d, 0x5f, 0x73, 0x61, 0x6d,
- 0x70, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x0f, 0x70,
- 0x65, 0x72, 0x66, 0x65, 0x74, 0x74, 0x6f, 0x2e, 0x70, 0x72, 0x6f, 0x74,
- 0x6f, 0x73, 0x22, 0x60, 0x0a, 0x15, 0x43, 0x68, 0x72, 0x6f, 0x6d, 0x65,
- 0x48, 0x69, 0x73, 0x74, 0x6f, 0x67, 0x72, 0x61, 0x6d, 0x53, 0x61, 0x6d,
- 0x70, 0x6c, 0x65, 0x12, 0x1b, 0x0a, 0x09, 0x6e, 0x61, 0x6d, 0x65, 0x5f,
- 0x68, 0x61, 0x73, 0x68, 0x18, 0x01, 0x20, 0x01, 0x28, 0x04, 0x52, 0x08,
- 0x6e, 0x61, 0x6d, 0x65, 0x48, 0x61, 0x73, 0x68, 0x12, 0x12, 0x0a, 0x04,
- 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04,
- 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x16, 0x0a, 0x06, 0x73, 0x61, 0x6d, 0x70,
- 0x6c, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x03, 0x52, 0x06, 0x73, 0x61,
- 0x6d, 0x70, 0x6c, 0x65, 0x42, 0x02, 0x48, 0x03, 0x0a, 0x7d, 0x0a, 0x3c,
+ 0x45, 0x44, 0x5f, 0x55, 0x4e, 0x54, 0x49, 0x4c, 0x10, 0x0c, 0x12, 0x41,
+ 0x0a, 0x3d, 0x43, 0x43, 0x5f, 0x53, 0x43, 0x48, 0x45, 0x44, 0x55, 0x4c,
+ 0x45, 0x52, 0x5f, 0x41, 0x43, 0x54, 0x49, 0x4f, 0x4e, 0x5f, 0x4e, 0x4f,
+ 0x54, 0x49, 0x46, 0x59, 0x5f, 0x42, 0x45, 0x47, 0x49, 0x4e, 0x5f, 0x4d,
+ 0x41, 0x49, 0x4e, 0x5f, 0x46, 0x52, 0x41, 0x4d, 0x45, 0x5f, 0x4e, 0x4f,
+ 0x54, 0x5f, 0x45, 0x58, 0x50, 0x45, 0x43, 0x54, 0x45, 0x44, 0x5f, 0x53,
+ 0x4f, 0x4f, 0x4e, 0x10, 0x0d, 0x0a, 0xb4, 0x01, 0x0a, 0x3f, 0x70, 0x72,
+ 0x6f, 0x74, 0x6f, 0x73, 0x2f, 0x70, 0x65, 0x72, 0x66, 0x65, 0x74, 0x74,
+ 0x6f, 0x2f, 0x74, 0x72, 0x61, 0x63, 0x65, 0x2f, 0x74, 0x72, 0x61, 0x63,
+ 0x6b, 0x5f, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x2f, 0x63, 0x68, 0x72, 0x6f,
+ 0x6d, 0x65, 0x5f, 0x68, 0x69, 0x73, 0x74, 0x6f, 0x67, 0x72, 0x61, 0x6d,
+ 0x5f, 0x73, 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74,
+ 0x6f, 0x12, 0x0f, 0x70, 0x65, 0x72, 0x66, 0x65, 0x74, 0x74, 0x6f, 0x2e,
+ 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x22, 0x60, 0x0a, 0x15, 0x43, 0x68,
+ 0x72, 0x6f, 0x6d, 0x65, 0x48, 0x69, 0x73, 0x74, 0x6f, 0x67, 0x72, 0x61,
+ 0x6d, 0x53, 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x12, 0x1b, 0x0a, 0x09, 0x6e,
+ 0x61, 0x6d, 0x65, 0x5f, 0x68, 0x61, 0x73, 0x68, 0x18, 0x01, 0x20, 0x01,
+ 0x28, 0x04, 0x52, 0x08, 0x6e, 0x61, 0x6d, 0x65, 0x48, 0x61, 0x73, 0x68,
+ 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x02, 0x20, 0x01,
+ 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x16, 0x0a, 0x06,
+ 0x73, 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x03,
+ 0x52, 0x06, 0x73, 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x0a, 0x79, 0x0a, 0x3c,
0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2f, 0x70, 0x65, 0x72, 0x66, 0x65,
0x74, 0x74, 0x6f, 0x2f, 0x74, 0x72, 0x61, 0x63, 0x65, 0x2f, 0x74, 0x72,
0x61, 0x63, 0x6b, 0x5f, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x2f, 0x63, 0x68,
@@ -1022,109 +1020,108 @@
0x72, 0x6f, 0x74, 0x6f, 0x73, 0x22, 0x28, 0x0a, 0x12, 0x43, 0x68, 0x72,
0x6f, 0x6d, 0x65, 0x4b, 0x65, 0x79, 0x65, 0x64, 0x53, 0x65, 0x72, 0x76,
0x69, 0x63, 0x65, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18,
- 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x42,
- 0x02, 0x48, 0x03, 0x0a, 0xbc, 0x08, 0x0a, 0x39, 0x70, 0x72, 0x6f, 0x74,
- 0x6f, 0x73, 0x2f, 0x70, 0x65, 0x72, 0x66, 0x65, 0x74, 0x74, 0x6f, 0x2f,
- 0x74, 0x72, 0x61, 0x63, 0x65, 0x2f, 0x74, 0x72, 0x61, 0x63, 0x6b, 0x5f,
- 0x65, 0x76, 0x65, 0x6e, 0x74, 0x2f, 0x63, 0x68, 0x72, 0x6f, 0x6d, 0x65,
- 0x5f, 0x6c, 0x65, 0x67, 0x61, 0x63, 0x79, 0x5f, 0x69, 0x70, 0x63, 0x2e,
- 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x0f, 0x70, 0x65, 0x72, 0x66, 0x65,
- 0x74, 0x74, 0x6f, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x22, 0xe9,
- 0x07, 0x0a, 0x0f, 0x43, 0x68, 0x72, 0x6f, 0x6d, 0x65, 0x4c, 0x65, 0x67,
- 0x61, 0x63, 0x79, 0x49, 0x70, 0x63, 0x12, 0x52, 0x0a, 0x0d, 0x6d, 0x65,
- 0x73, 0x73, 0x61, 0x67, 0x65, 0x5f, 0x63, 0x6c, 0x61, 0x73, 0x73, 0x18,
- 0x01, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x2d, 0x2e, 0x70, 0x65, 0x72, 0x66,
- 0x65, 0x74, 0x74, 0x6f, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2e,
- 0x43, 0x68, 0x72, 0x6f, 0x6d, 0x65, 0x4c, 0x65, 0x67, 0x61, 0x63, 0x79,
- 0x49, 0x70, 0x63, 0x2e, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x43,
- 0x6c, 0x61, 0x73, 0x73, 0x52, 0x0c, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67,
- 0x65, 0x43, 0x6c, 0x61, 0x73, 0x73, 0x12, 0x21, 0x0a, 0x0c, 0x6d, 0x65,
- 0x73, 0x73, 0x61, 0x67, 0x65, 0x5f, 0x6c, 0x69, 0x6e, 0x65, 0x18, 0x02,
- 0x20, 0x01, 0x28, 0x0d, 0x52, 0x0b, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67,
- 0x65, 0x4c, 0x69, 0x6e, 0x65, 0x22, 0xde, 0x06, 0x0a, 0x0c, 0x4d, 0x65,
- 0x73, 0x73, 0x61, 0x67, 0x65, 0x43, 0x6c, 0x61, 0x73, 0x73, 0x12, 0x15,
- 0x0a, 0x11, 0x43, 0x4c, 0x41, 0x53, 0x53, 0x5f, 0x55, 0x4e, 0x53, 0x50,
- 0x45, 0x43, 0x49, 0x46, 0x49, 0x45, 0x44, 0x10, 0x00, 0x12, 0x14, 0x0a,
- 0x10, 0x43, 0x4c, 0x41, 0x53, 0x53, 0x5f, 0x41, 0x55, 0x54, 0x4f, 0x4d,
- 0x41, 0x54, 0x49, 0x4f, 0x4e, 0x10, 0x01, 0x12, 0x0f, 0x0a, 0x0b, 0x43,
- 0x4c, 0x41, 0x53, 0x53, 0x5f, 0x46, 0x52, 0x41, 0x4d, 0x45, 0x10, 0x02,
- 0x12, 0x0e, 0x0a, 0x0a, 0x43, 0x4c, 0x41, 0x53, 0x53, 0x5f, 0x50, 0x41,
- 0x47, 0x45, 0x10, 0x03, 0x12, 0x0e, 0x0a, 0x0a, 0x43, 0x4c, 0x41, 0x53,
- 0x53, 0x5f, 0x56, 0x49, 0x45, 0x57, 0x10, 0x04, 0x12, 0x10, 0x0a, 0x0c,
- 0x43, 0x4c, 0x41, 0x53, 0x53, 0x5f, 0x57, 0x49, 0x44, 0x47, 0x45, 0x54,
- 0x10, 0x05, 0x12, 0x0f, 0x0a, 0x0b, 0x43, 0x4c, 0x41, 0x53, 0x53, 0x5f,
- 0x49, 0x4e, 0x50, 0x55, 0x54, 0x10, 0x06, 0x12, 0x0e, 0x0a, 0x0a, 0x43,
- 0x4c, 0x41, 0x53, 0x53, 0x5f, 0x54, 0x45, 0x53, 0x54, 0x10, 0x07, 0x12,
- 0x10, 0x0a, 0x0c, 0x43, 0x4c, 0x41, 0x53, 0x53, 0x5f, 0x57, 0x4f, 0x52,
- 0x4b, 0x45, 0x52, 0x10, 0x08, 0x12, 0x0e, 0x0a, 0x0a, 0x43, 0x4c, 0x41,
- 0x53, 0x53, 0x5f, 0x4e, 0x41, 0x43, 0x4c, 0x10, 0x09, 0x12, 0x15, 0x0a,
- 0x11, 0x43, 0x4c, 0x41, 0x53, 0x53, 0x5f, 0x47, 0x50, 0x55, 0x5f, 0x43,
- 0x48, 0x41, 0x4e, 0x4e, 0x45, 0x4c, 0x10, 0x0a, 0x12, 0x0f, 0x0a, 0x0b,
- 0x43, 0x4c, 0x41, 0x53, 0x53, 0x5f, 0x4d, 0x45, 0x44, 0x49, 0x41, 0x10,
- 0x0b, 0x12, 0x0f, 0x0a, 0x0b, 0x43, 0x4c, 0x41, 0x53, 0x53, 0x5f, 0x50,
- 0x50, 0x41, 0x50, 0x49, 0x10, 0x0c, 0x12, 0x10, 0x0a, 0x0c, 0x43, 0x4c,
- 0x41, 0x53, 0x53, 0x5f, 0x43, 0x48, 0x52, 0x4f, 0x4d, 0x45, 0x10, 0x0d,
- 0x12, 0x0e, 0x0a, 0x0a, 0x43, 0x4c, 0x41, 0x53, 0x53, 0x5f, 0x44, 0x52,
- 0x41, 0x47, 0x10, 0x0e, 0x12, 0x0f, 0x0a, 0x0b, 0x43, 0x4c, 0x41, 0x53,
- 0x53, 0x5f, 0x50, 0x52, 0x49, 0x4e, 0x54, 0x10, 0x0f, 0x12, 0x13, 0x0a,
- 0x0f, 0x43, 0x4c, 0x41, 0x53, 0x53, 0x5f, 0x45, 0x58, 0x54, 0x45, 0x4e,
- 0x53, 0x49, 0x4f, 0x4e, 0x10, 0x10, 0x12, 0x1b, 0x0a, 0x17, 0x43, 0x4c,
- 0x41, 0x53, 0x53, 0x5f, 0x54, 0x45, 0x58, 0x54, 0x5f, 0x49, 0x4e, 0x50,
- 0x55, 0x54, 0x5f, 0x43, 0x4c, 0x49, 0x45, 0x4e, 0x54, 0x10, 0x11, 0x12,
- 0x14, 0x0a, 0x10, 0x43, 0x4c, 0x41, 0x53, 0x53, 0x5f, 0x42, 0x4c, 0x49,
- 0x4e, 0x4b, 0x5f, 0x54, 0x45, 0x53, 0x54, 0x10, 0x12, 0x12, 0x17, 0x0a,
- 0x13, 0x43, 0x4c, 0x41, 0x53, 0x53, 0x5f, 0x41, 0x43, 0x43, 0x45, 0x53,
- 0x53, 0x49, 0x42, 0x49, 0x4c, 0x49, 0x54, 0x59, 0x10, 0x13, 0x12, 0x13,
- 0x0a, 0x0f, 0x43, 0x4c, 0x41, 0x53, 0x53, 0x5f, 0x50, 0x52, 0x45, 0x52,
- 0x45, 0x4e, 0x44, 0x45, 0x52, 0x10, 0x14, 0x12, 0x14, 0x0a, 0x10, 0x43,
- 0x4c, 0x41, 0x53, 0x53, 0x5f, 0x43, 0x48, 0x52, 0x4f, 0x4d, 0x4f, 0x54,
- 0x49, 0x4e, 0x47, 0x10, 0x15, 0x12, 0x18, 0x0a, 0x14, 0x43, 0x4c, 0x41,
- 0x53, 0x53, 0x5f, 0x42, 0x52, 0x4f, 0x57, 0x53, 0x45, 0x52, 0x5f, 0x50,
- 0x4c, 0x55, 0x47, 0x49, 0x4e, 0x10, 0x16, 0x12, 0x1a, 0x0a, 0x16, 0x43,
- 0x4c, 0x41, 0x53, 0x53, 0x5f, 0x41, 0x4e, 0x44, 0x52, 0x4f, 0x49, 0x44,
- 0x5f, 0x57, 0x45, 0x42, 0x5f, 0x56, 0x49, 0x45, 0x57, 0x10, 0x17, 0x12,
- 0x13, 0x0a, 0x0f, 0x43, 0x4c, 0x41, 0x53, 0x53, 0x5f, 0x4e, 0x41, 0x43,
- 0x4c, 0x5f, 0x48, 0x4f, 0x53, 0x54, 0x10, 0x18, 0x12, 0x19, 0x0a, 0x15,
- 0x43, 0x4c, 0x41, 0x53, 0x53, 0x5f, 0x45, 0x4e, 0x43, 0x52, 0x59, 0x50,
- 0x54, 0x45, 0x44, 0x5f, 0x4d, 0x45, 0x44, 0x49, 0x41, 0x10, 0x19, 0x12,
- 0x0e, 0x0a, 0x0a, 0x43, 0x4c, 0x41, 0x53, 0x53, 0x5f, 0x43, 0x41, 0x53,
- 0x54, 0x10, 0x1a, 0x12, 0x19, 0x0a, 0x15, 0x43, 0x4c, 0x41, 0x53, 0x53,
- 0x5f, 0x47, 0x49, 0x4e, 0x5f, 0x4a, 0x41, 0x56, 0x41, 0x5f, 0x42, 0x52,
- 0x49, 0x44, 0x47, 0x45, 0x10, 0x1b, 0x12, 0x21, 0x0a, 0x1d, 0x43, 0x4c,
- 0x41, 0x53, 0x53, 0x5f, 0x43, 0x48, 0x52, 0x4f, 0x4d, 0x45, 0x5f, 0x55,
- 0x54, 0x49, 0x4c, 0x49, 0x54, 0x59, 0x5f, 0x50, 0x52, 0x49, 0x4e, 0x54,
- 0x49, 0x4e, 0x47, 0x10, 0x1c, 0x12, 0x13, 0x0a, 0x0f, 0x43, 0x4c, 0x41,
- 0x53, 0x53, 0x5f, 0x4f, 0x5a, 0x4f, 0x4e, 0x45, 0x5f, 0x47, 0x50, 0x55,
- 0x10, 0x1d, 0x12, 0x12, 0x0a, 0x0e, 0x43, 0x4c, 0x41, 0x53, 0x53, 0x5f,
- 0x57, 0x45, 0x42, 0x5f, 0x54, 0x45, 0x53, 0x54, 0x10, 0x1e, 0x12, 0x17,
- 0x0a, 0x13, 0x43, 0x4c, 0x41, 0x53, 0x53, 0x5f, 0x4e, 0x45, 0x54, 0x57,
- 0x4f, 0x52, 0x4b, 0x5f, 0x48, 0x49, 0x4e, 0x54, 0x53, 0x10, 0x1f, 0x12,
- 0x1f, 0x0a, 0x1b, 0x43, 0x4c, 0x41, 0x53, 0x53, 0x5f, 0x45, 0x58, 0x54,
- 0x45, 0x4e, 0x53, 0x49, 0x4f, 0x4e, 0x53, 0x5f, 0x47, 0x55, 0x45, 0x53,
- 0x54, 0x5f, 0x56, 0x49, 0x45, 0x57, 0x10, 0x20, 0x12, 0x14, 0x0a, 0x10,
- 0x43, 0x4c, 0x41, 0x53, 0x53, 0x5f, 0x47, 0x55, 0x45, 0x53, 0x54, 0x5f,
- 0x56, 0x49, 0x45, 0x57, 0x10, 0x21, 0x12, 0x1f, 0x0a, 0x1b, 0x43, 0x4c,
- 0x41, 0x53, 0x53, 0x5f, 0x4d, 0x45, 0x44, 0x49, 0x41, 0x5f, 0x50, 0x4c,
- 0x41, 0x59, 0x45, 0x52, 0x5f, 0x44, 0x45, 0x4c, 0x45, 0x47, 0x41, 0x54,
- 0x45, 0x10, 0x22, 0x12, 0x1a, 0x0a, 0x16, 0x43, 0x4c, 0x41, 0x53, 0x53,
- 0x5f, 0x45, 0x58, 0x54, 0x45, 0x4e, 0x53, 0x49, 0x4f, 0x4e, 0x5f, 0x57,
- 0x4f, 0x52, 0x4b, 0x45, 0x52, 0x10, 0x23, 0x12, 0x1c, 0x0a, 0x18, 0x43,
- 0x4c, 0x41, 0x53, 0x53, 0x5f, 0x53, 0x55, 0x42, 0x52, 0x45, 0x53, 0x4f,
- 0x55, 0x52, 0x43, 0x45, 0x5f, 0x46, 0x49, 0x4c, 0x54, 0x45, 0x52, 0x10,
- 0x24, 0x12, 0x1b, 0x0a, 0x17, 0x43, 0x4c, 0x41, 0x53, 0x53, 0x5f, 0x55,
- 0x4e, 0x46, 0x52, 0x45, 0x45, 0x5a, 0x41, 0x42, 0x4c, 0x45, 0x5f, 0x46,
- 0x52, 0x41, 0x4d, 0x45, 0x10, 0x25, 0x42, 0x02, 0x48, 0x03, 0x0a, 0x7b,
- 0x0a, 0x39, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2f, 0x70, 0x65, 0x72,
- 0x66, 0x65, 0x74, 0x74, 0x6f, 0x2f, 0x74, 0x72, 0x61, 0x63, 0x65, 0x2f,
- 0x74, 0x72, 0x61, 0x63, 0x6b, 0x5f, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x2f,
- 0x63, 0x68, 0x72, 0x6f, 0x6d, 0x65, 0x5f, 0x75, 0x73, 0x65, 0x72, 0x5f,
- 0x65, 0x76, 0x65, 0x6e, 0x74, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12,
- 0x0f, 0x70, 0x65, 0x72, 0x66, 0x65, 0x74, 0x74, 0x6f, 0x2e, 0x70, 0x72,
- 0x6f, 0x74, 0x6f, 0x73, 0x22, 0x29, 0x0a, 0x0f, 0x43, 0x68, 0x72, 0x6f,
- 0x6d, 0x65, 0x55, 0x73, 0x65, 0x72, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x12,
- 0x16, 0x0a, 0x06, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x01, 0x20,
- 0x01, 0x28, 0x09, 0x52, 0x06, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x42,
- 0x02, 0x48, 0x03, 0x0a, 0x81, 0x18, 0x0a, 0x33, 0x70, 0x72, 0x6f, 0x74,
+ 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x0a,
+ 0xb8, 0x08, 0x0a, 0x39, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2f, 0x70,
+ 0x65, 0x72, 0x66, 0x65, 0x74, 0x74, 0x6f, 0x2f, 0x74, 0x72, 0x61, 0x63,
+ 0x65, 0x2f, 0x74, 0x72, 0x61, 0x63, 0x6b, 0x5f, 0x65, 0x76, 0x65, 0x6e,
+ 0x74, 0x2f, 0x63, 0x68, 0x72, 0x6f, 0x6d, 0x65, 0x5f, 0x6c, 0x65, 0x67,
+ 0x61, 0x63, 0x79, 0x5f, 0x69, 0x70, 0x63, 0x2e, 0x70, 0x72, 0x6f, 0x74,
+ 0x6f, 0x12, 0x0f, 0x70, 0x65, 0x72, 0x66, 0x65, 0x74, 0x74, 0x6f, 0x2e,
+ 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x22, 0xe9, 0x07, 0x0a, 0x0f, 0x43,
+ 0x68, 0x72, 0x6f, 0x6d, 0x65, 0x4c, 0x65, 0x67, 0x61, 0x63, 0x79, 0x49,
+ 0x70, 0x63, 0x12, 0x52, 0x0a, 0x0d, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67,
+ 0x65, 0x5f, 0x63, 0x6c, 0x61, 0x73, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28,
+ 0x0e, 0x32, 0x2d, 0x2e, 0x70, 0x65, 0x72, 0x66, 0x65, 0x74, 0x74, 0x6f,
+ 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2e, 0x43, 0x68, 0x72, 0x6f,
+ 0x6d, 0x65, 0x4c, 0x65, 0x67, 0x61, 0x63, 0x79, 0x49, 0x70, 0x63, 0x2e,
+ 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x43, 0x6c, 0x61, 0x73, 0x73,
+ 0x52, 0x0c, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x43, 0x6c, 0x61,
+ 0x73, 0x73, 0x12, 0x21, 0x0a, 0x0c, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67,
+ 0x65, 0x5f, 0x6c, 0x69, 0x6e, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0d,
+ 0x52, 0x0b, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x4c, 0x69, 0x6e,
+ 0x65, 0x22, 0xde, 0x06, 0x0a, 0x0c, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67,
+ 0x65, 0x43, 0x6c, 0x61, 0x73, 0x73, 0x12, 0x15, 0x0a, 0x11, 0x43, 0x4c,
+ 0x41, 0x53, 0x53, 0x5f, 0x55, 0x4e, 0x53, 0x50, 0x45, 0x43, 0x49, 0x46,
+ 0x49, 0x45, 0x44, 0x10, 0x00, 0x12, 0x14, 0x0a, 0x10, 0x43, 0x4c, 0x41,
+ 0x53, 0x53, 0x5f, 0x41, 0x55, 0x54, 0x4f, 0x4d, 0x41, 0x54, 0x49, 0x4f,
+ 0x4e, 0x10, 0x01, 0x12, 0x0f, 0x0a, 0x0b, 0x43, 0x4c, 0x41, 0x53, 0x53,
+ 0x5f, 0x46, 0x52, 0x41, 0x4d, 0x45, 0x10, 0x02, 0x12, 0x0e, 0x0a, 0x0a,
+ 0x43, 0x4c, 0x41, 0x53, 0x53, 0x5f, 0x50, 0x41, 0x47, 0x45, 0x10, 0x03,
+ 0x12, 0x0e, 0x0a, 0x0a, 0x43, 0x4c, 0x41, 0x53, 0x53, 0x5f, 0x56, 0x49,
+ 0x45, 0x57, 0x10, 0x04, 0x12, 0x10, 0x0a, 0x0c, 0x43, 0x4c, 0x41, 0x53,
+ 0x53, 0x5f, 0x57, 0x49, 0x44, 0x47, 0x45, 0x54, 0x10, 0x05, 0x12, 0x0f,
+ 0x0a, 0x0b, 0x43, 0x4c, 0x41, 0x53, 0x53, 0x5f, 0x49, 0x4e, 0x50, 0x55,
+ 0x54, 0x10, 0x06, 0x12, 0x0e, 0x0a, 0x0a, 0x43, 0x4c, 0x41, 0x53, 0x53,
+ 0x5f, 0x54, 0x45, 0x53, 0x54, 0x10, 0x07, 0x12, 0x10, 0x0a, 0x0c, 0x43,
+ 0x4c, 0x41, 0x53, 0x53, 0x5f, 0x57, 0x4f, 0x52, 0x4b, 0x45, 0x52, 0x10,
+ 0x08, 0x12, 0x0e, 0x0a, 0x0a, 0x43, 0x4c, 0x41, 0x53, 0x53, 0x5f, 0x4e,
+ 0x41, 0x43, 0x4c, 0x10, 0x09, 0x12, 0x15, 0x0a, 0x11, 0x43, 0x4c, 0x41,
+ 0x53, 0x53, 0x5f, 0x47, 0x50, 0x55, 0x5f, 0x43, 0x48, 0x41, 0x4e, 0x4e,
+ 0x45, 0x4c, 0x10, 0x0a, 0x12, 0x0f, 0x0a, 0x0b, 0x43, 0x4c, 0x41, 0x53,
+ 0x53, 0x5f, 0x4d, 0x45, 0x44, 0x49, 0x41, 0x10, 0x0b, 0x12, 0x0f, 0x0a,
+ 0x0b, 0x43, 0x4c, 0x41, 0x53, 0x53, 0x5f, 0x50, 0x50, 0x41, 0x50, 0x49,
+ 0x10, 0x0c, 0x12, 0x10, 0x0a, 0x0c, 0x43, 0x4c, 0x41, 0x53, 0x53, 0x5f,
+ 0x43, 0x48, 0x52, 0x4f, 0x4d, 0x45, 0x10, 0x0d, 0x12, 0x0e, 0x0a, 0x0a,
+ 0x43, 0x4c, 0x41, 0x53, 0x53, 0x5f, 0x44, 0x52, 0x41, 0x47, 0x10, 0x0e,
+ 0x12, 0x0f, 0x0a, 0x0b, 0x43, 0x4c, 0x41, 0x53, 0x53, 0x5f, 0x50, 0x52,
+ 0x49, 0x4e, 0x54, 0x10, 0x0f, 0x12, 0x13, 0x0a, 0x0f, 0x43, 0x4c, 0x41,
+ 0x53, 0x53, 0x5f, 0x45, 0x58, 0x54, 0x45, 0x4e, 0x53, 0x49, 0x4f, 0x4e,
+ 0x10, 0x10, 0x12, 0x1b, 0x0a, 0x17, 0x43, 0x4c, 0x41, 0x53, 0x53, 0x5f,
+ 0x54, 0x45, 0x58, 0x54, 0x5f, 0x49, 0x4e, 0x50, 0x55, 0x54, 0x5f, 0x43,
+ 0x4c, 0x49, 0x45, 0x4e, 0x54, 0x10, 0x11, 0x12, 0x14, 0x0a, 0x10, 0x43,
+ 0x4c, 0x41, 0x53, 0x53, 0x5f, 0x42, 0x4c, 0x49, 0x4e, 0x4b, 0x5f, 0x54,
+ 0x45, 0x53, 0x54, 0x10, 0x12, 0x12, 0x17, 0x0a, 0x13, 0x43, 0x4c, 0x41,
+ 0x53, 0x53, 0x5f, 0x41, 0x43, 0x43, 0x45, 0x53, 0x53, 0x49, 0x42, 0x49,
+ 0x4c, 0x49, 0x54, 0x59, 0x10, 0x13, 0x12, 0x13, 0x0a, 0x0f, 0x43, 0x4c,
+ 0x41, 0x53, 0x53, 0x5f, 0x50, 0x52, 0x45, 0x52, 0x45, 0x4e, 0x44, 0x45,
+ 0x52, 0x10, 0x14, 0x12, 0x14, 0x0a, 0x10, 0x43, 0x4c, 0x41, 0x53, 0x53,
+ 0x5f, 0x43, 0x48, 0x52, 0x4f, 0x4d, 0x4f, 0x54, 0x49, 0x4e, 0x47, 0x10,
+ 0x15, 0x12, 0x18, 0x0a, 0x14, 0x43, 0x4c, 0x41, 0x53, 0x53, 0x5f, 0x42,
+ 0x52, 0x4f, 0x57, 0x53, 0x45, 0x52, 0x5f, 0x50, 0x4c, 0x55, 0x47, 0x49,
+ 0x4e, 0x10, 0x16, 0x12, 0x1a, 0x0a, 0x16, 0x43, 0x4c, 0x41, 0x53, 0x53,
+ 0x5f, 0x41, 0x4e, 0x44, 0x52, 0x4f, 0x49, 0x44, 0x5f, 0x57, 0x45, 0x42,
+ 0x5f, 0x56, 0x49, 0x45, 0x57, 0x10, 0x17, 0x12, 0x13, 0x0a, 0x0f, 0x43,
+ 0x4c, 0x41, 0x53, 0x53, 0x5f, 0x4e, 0x41, 0x43, 0x4c, 0x5f, 0x48, 0x4f,
+ 0x53, 0x54, 0x10, 0x18, 0x12, 0x19, 0x0a, 0x15, 0x43, 0x4c, 0x41, 0x53,
+ 0x53, 0x5f, 0x45, 0x4e, 0x43, 0x52, 0x59, 0x50, 0x54, 0x45, 0x44, 0x5f,
+ 0x4d, 0x45, 0x44, 0x49, 0x41, 0x10, 0x19, 0x12, 0x0e, 0x0a, 0x0a, 0x43,
+ 0x4c, 0x41, 0x53, 0x53, 0x5f, 0x43, 0x41, 0x53, 0x54, 0x10, 0x1a, 0x12,
+ 0x19, 0x0a, 0x15, 0x43, 0x4c, 0x41, 0x53, 0x53, 0x5f, 0x47, 0x49, 0x4e,
+ 0x5f, 0x4a, 0x41, 0x56, 0x41, 0x5f, 0x42, 0x52, 0x49, 0x44, 0x47, 0x45,
+ 0x10, 0x1b, 0x12, 0x21, 0x0a, 0x1d, 0x43, 0x4c, 0x41, 0x53, 0x53, 0x5f,
+ 0x43, 0x48, 0x52, 0x4f, 0x4d, 0x45, 0x5f, 0x55, 0x54, 0x49, 0x4c, 0x49,
+ 0x54, 0x59, 0x5f, 0x50, 0x52, 0x49, 0x4e, 0x54, 0x49, 0x4e, 0x47, 0x10,
+ 0x1c, 0x12, 0x13, 0x0a, 0x0f, 0x43, 0x4c, 0x41, 0x53, 0x53, 0x5f, 0x4f,
+ 0x5a, 0x4f, 0x4e, 0x45, 0x5f, 0x47, 0x50, 0x55, 0x10, 0x1d, 0x12, 0x12,
+ 0x0a, 0x0e, 0x43, 0x4c, 0x41, 0x53, 0x53, 0x5f, 0x57, 0x45, 0x42, 0x5f,
+ 0x54, 0x45, 0x53, 0x54, 0x10, 0x1e, 0x12, 0x17, 0x0a, 0x13, 0x43, 0x4c,
+ 0x41, 0x53, 0x53, 0x5f, 0x4e, 0x45, 0x54, 0x57, 0x4f, 0x52, 0x4b, 0x5f,
+ 0x48, 0x49, 0x4e, 0x54, 0x53, 0x10, 0x1f, 0x12, 0x1f, 0x0a, 0x1b, 0x43,
+ 0x4c, 0x41, 0x53, 0x53, 0x5f, 0x45, 0x58, 0x54, 0x45, 0x4e, 0x53, 0x49,
+ 0x4f, 0x4e, 0x53, 0x5f, 0x47, 0x55, 0x45, 0x53, 0x54, 0x5f, 0x56, 0x49,
+ 0x45, 0x57, 0x10, 0x20, 0x12, 0x14, 0x0a, 0x10, 0x43, 0x4c, 0x41, 0x53,
+ 0x53, 0x5f, 0x47, 0x55, 0x45, 0x53, 0x54, 0x5f, 0x56, 0x49, 0x45, 0x57,
+ 0x10, 0x21, 0x12, 0x1f, 0x0a, 0x1b, 0x43, 0x4c, 0x41, 0x53, 0x53, 0x5f,
+ 0x4d, 0x45, 0x44, 0x49, 0x41, 0x5f, 0x50, 0x4c, 0x41, 0x59, 0x45, 0x52,
+ 0x5f, 0x44, 0x45, 0x4c, 0x45, 0x47, 0x41, 0x54, 0x45, 0x10, 0x22, 0x12,
+ 0x1a, 0x0a, 0x16, 0x43, 0x4c, 0x41, 0x53, 0x53, 0x5f, 0x45, 0x58, 0x54,
+ 0x45, 0x4e, 0x53, 0x49, 0x4f, 0x4e, 0x5f, 0x57, 0x4f, 0x52, 0x4b, 0x45,
+ 0x52, 0x10, 0x23, 0x12, 0x1c, 0x0a, 0x18, 0x43, 0x4c, 0x41, 0x53, 0x53,
+ 0x5f, 0x53, 0x55, 0x42, 0x52, 0x45, 0x53, 0x4f, 0x55, 0x52, 0x43, 0x45,
+ 0x5f, 0x46, 0x49, 0x4c, 0x54, 0x45, 0x52, 0x10, 0x24, 0x12, 0x1b, 0x0a,
+ 0x17, 0x43, 0x4c, 0x41, 0x53, 0x53, 0x5f, 0x55, 0x4e, 0x46, 0x52, 0x45,
+ 0x45, 0x5a, 0x41, 0x42, 0x4c, 0x45, 0x5f, 0x46, 0x52, 0x41, 0x4d, 0x45,
+ 0x10, 0x25, 0x0a, 0x77, 0x0a, 0x39, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73,
+ 0x2f, 0x70, 0x65, 0x72, 0x66, 0x65, 0x74, 0x74, 0x6f, 0x2f, 0x74, 0x72,
+ 0x61, 0x63, 0x65, 0x2f, 0x74, 0x72, 0x61, 0x63, 0x6b, 0x5f, 0x65, 0x76,
+ 0x65, 0x6e, 0x74, 0x2f, 0x63, 0x68, 0x72, 0x6f, 0x6d, 0x65, 0x5f, 0x75,
+ 0x73, 0x65, 0x72, 0x5f, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x2e, 0x70, 0x72,
+ 0x6f, 0x74, 0x6f, 0x12, 0x0f, 0x70, 0x65, 0x72, 0x66, 0x65, 0x74, 0x74,
+ 0x6f, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x22, 0x29, 0x0a, 0x0f,
+ 0x43, 0x68, 0x72, 0x6f, 0x6d, 0x65, 0x55, 0x73, 0x65, 0x72, 0x45, 0x76,
+ 0x65, 0x6e, 0x74, 0x12, 0x16, 0x0a, 0x06, 0x61, 0x63, 0x74, 0x69, 0x6f,
+ 0x6e, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x61, 0x63, 0x74,
+ 0x69, 0x6f, 0x6e, 0x0a, 0xfd, 0x17, 0x0a, 0x33, 0x70, 0x72, 0x6f, 0x74,
0x6f, 0x73, 0x2f, 0x70, 0x65, 0x72, 0x66, 0x65, 0x74, 0x74, 0x6f, 0x2f,
0x74, 0x72, 0x61, 0x63, 0x65, 0x2f, 0x74, 0x72, 0x61, 0x63, 0x6b, 0x5f,
0x65, 0x76, 0x65, 0x6e, 0x74, 0x2f, 0x74, 0x72, 0x61, 0x63, 0x6b, 0x5f,
@@ -1380,7 +1377,7 @@
0x65, 0x12, 0x10, 0x0a, 0x03, 0x69, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01,
0x28, 0x04, 0x52, 0x03, 0x69, 0x69, 0x64, 0x12, 0x12, 0x0a, 0x04, 0x6e,
0x61, 0x6d, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e,
- 0x61, 0x6d, 0x65, 0x42, 0x02, 0x48, 0x03}};
+ 0x61, 0x6d, 0x65}};
} // namespace perfetto
diff --git a/src/trace_processor/importers/proto/track_event_module.cc b/src/trace_processor/importers/proto/track_event_module.cc
index c731fcc..1bbbebd 100644
--- a/src/trace_processor/importers/proto/track_event_module.cc
+++ b/src/trace_processor/importers/proto/track_event_module.cc
@@ -14,9 +14,14 @@
* limitations under the License.
*/
#include "src/trace_processor/importers/proto/track_event_module.h"
-#include "perfetto/base/build_config.h"
-#include "src/trace_processor/timestamped_trace_piece.h"
+#include "perfetto/base/build_config.h"
+#include "perfetto/ext/base/string_utils.h"
+#include "src/trace_processor/timestamped_trace_piece.h"
+#include "src/trace_processor/trace_processor_context.h"
+#include "src/trace_processor/track_tracker.h"
+
+#include "protos/perfetto/config/data_source_config.pbzero.h"
#include "protos/perfetto/config/trace_config.pbzero.h"
#include "protos/perfetto/trace/trace_packet.pbzero.h"
@@ -43,20 +48,15 @@
uint32_t field_id) {
switch (field_id) {
case TracePacket::kTrackDescriptorFieldNumber:
- tokenizer_.TokenizeTrackDescriptorPacket(decoder);
- return ModuleResult::Handled();
+ return tokenizer_.TokenizeTrackDescriptorPacket(state, decoder,
+ packet_timestamp);
case TracePacket::kTrackEventFieldNumber:
tokenizer_.TokenizeTrackEventPacket(state, decoder, packet,
packet_timestamp);
return ModuleResult::Handled();
case TracePacket::kThreadDescriptorFieldNumber:
- // TODO(eseckler): Remove these once Chrome has switched fully over to
- // TrackDescriptors.
- tokenizer_.TokenizeThreadDescriptorPacket(state, decoder);
- return ModuleResult::Handled();
- case TracePacket::kProcessDescriptorFieldNumber:
- tokenizer_.TokenizeProcessDescriptorPacket(decoder);
- return ModuleResult::Handled();
+ // TODO(eseckler): Remove once Chrome has switched to TrackDescriptors.
+ return tokenizer_.TokenizeThreadDescriptorPacket(state, decoder);
}
return ModuleResult::Ignored();
}
@@ -64,12 +64,28 @@
void TrackEventModule::ParsePacket(const TracePacket::Decoder& decoder,
const TimestampedTracePiece& ttp,
uint32_t field_id) {
- if (field_id == TracePacket::kTrackEventFieldNumber) {
- PERFETTO_DCHECK(ttp.type == TimestampedTracePiece::Type::kTrackEvent);
- parser_.ParseTrackEvent(
- ttp.timestamp, ttp.track_event_data->thread_timestamp,
- ttp.track_event_data->thread_instruction_count,
- ttp.track_event_data->sequence_state, decoder.track_event());
+ switch (field_id) {
+ case TracePacket::kTrackDescriptorFieldNumber:
+ PERFETTO_DCHECK(ttp.type == TimestampedTracePiece::Type::kTracePacket);
+ parser_.ParseTrackDescriptor(decoder.track_descriptor());
+ break;
+ case TracePacket::kTrackEventFieldNumber:
+ PERFETTO_DCHECK(ttp.type == TimestampedTracePiece::Type::kTrackEvent);
+ parser_.ParseTrackEvent(
+ ttp.timestamp, ttp.track_event_data->thread_timestamp,
+ ttp.track_event_data->thread_instruction_count,
+ ttp.track_event_data->sequence_state, decoder.track_event());
+ break;
+ case TracePacket::kProcessDescriptorFieldNumber:
+ // TODO(eseckler): Remove once Chrome has switched to TrackDescriptors.
+ PERFETTO_DCHECK(ttp.type == TimestampedTracePiece::Type::kTracePacket);
+ parser_.ParseProcessDescriptor(decoder.process_descriptor());
+ break;
+ case TracePacket::kThreadDescriptorFieldNumber:
+ // TODO(eseckler): Remove once Chrome has switched to TrackDescriptors.
+ PERFETTO_DCHECK(ttp.type == TimestampedTracePiece::Type::kTracePacket);
+ parser_.ParseThreadDescriptor(decoder.thread_descriptor());
+ break;
}
}
diff --git a/src/trace_processor/importers/proto/track_event_parser.cc b/src/trace_processor/importers/proto/track_event_parser.cc
index f631b6b..fc46e7b 100644
--- a/src/trace_processor/importers/proto/track_event_parser.cc
+++ b/src/trace_processor/importers/proto/track_event_parser.cc
@@ -31,11 +31,16 @@
#include "protos/perfetto/trace/track_event/chrome_histogram_sample.pbzero.h"
#include "protos/perfetto/trace/track_event/chrome_keyed_service.pbzero.h"
#include "protos/perfetto/trace/track_event/chrome_legacy_ipc.pbzero.h"
+#include "protos/perfetto/trace/track_event/chrome_process_descriptor.pbzero.h"
+#include "protos/perfetto/trace/track_event/chrome_thread_descriptor.pbzero.h"
#include "protos/perfetto/trace/track_event/chrome_user_event.pbzero.h"
#include "protos/perfetto/trace/track_event/debug_annotation.pbzero.h"
#include "protos/perfetto/trace/track_event/log_message.pbzero.h"
+#include "protos/perfetto/trace/track_event/process_descriptor.pbzero.h"
#include "protos/perfetto/trace/track_event/source_location.pbzero.h"
#include "protos/perfetto/trace/track_event/task_execution.pbzero.h"
+#include "protos/perfetto/trace/track_event/thread_descriptor.pbzero.h"
+#include "protos/perfetto/trace/track_event/track_descriptor.pbzero.h"
#include "protos/perfetto/trace/track_event/track_event.pbzero.h"
namespace perfetto {
@@ -109,8 +114,8 @@
context->storage->InternString("track_event.log_message")),
raw_legacy_event_id_(
context->storage->InternString("track_event.legacy_event")),
- legacy_event_original_tid_id_(
- context->storage->InternString("legacy_event.original_tid")),
+ legacy_event_passthrough_utid_id_(
+ context->storage->InternString("legacy_event.passthrough_utid")),
legacy_event_category_key_id_(
context->storage->InternString("legacy_event.category")),
legacy_event_name_key_id_(
@@ -200,7 +205,141 @@
context->storage->InternString("MEDIA_PLAYER_DELEGATE"),
context->storage->InternString("EXTENSION_WORKER"),
context->storage->InternString("SUBRESOURCE_FILTER"),
- context->storage->InternString("UNFREEZABLE_FRAME")}} {}
+ context->storage->InternString("UNFREEZABLE_FRAME")}},
+ chrome_process_name_ids_{
+ {kNullStringId, context_->storage->InternString("Browser"),
+ context_->storage->InternString("Renderer"),
+ context_->storage->InternString("Utility"),
+ context_->storage->InternString("Zygote"),
+ context_->storage->InternString("SandboxHelper"),
+ context_->storage->InternString("Gpu"),
+ context_->storage->InternString("PpapiPlugin"),
+ context_->storage->InternString("PpapiBroker")}},
+ chrome_thread_name_ids_{
+ {kNullStringId, context_->storage->InternString("CrProcessMain"),
+ context_->storage->InternString("ChromeIOThread"),
+ context_->storage->InternString("ThreadPoolBackgroundWorker&"),
+ context_->storage->InternString("ThreadPoolForegroundWorker&"),
+ context_->storage->InternString(
+ "ThreadPoolSingleThreadForegroundBlocking&"),
+ context_->storage->InternString(
+ "ThreadPoolSingleThreadBackgroundBlocking&"),
+ context_->storage->InternString("ThreadPoolService"),
+ context_->storage->InternString("Compositor"),
+ context_->storage->InternString("VizCompositorThread"),
+ context_->storage->InternString("CompositorTileWorker&"),
+ context_->storage->InternString("ServiceWorkerThread&"),
+ context_->storage->InternString("MemoryInfra"),
+ context_->storage->InternString("StackSamplingProfiler")}} {}
+
+void TrackEventParser::ParseTrackDescriptor(
+ protozero::ConstBytes track_descriptor) {
+ protos::pbzero::TrackDescriptor::Decoder decoder(track_descriptor);
+
+ // Ensure that the track and its parents are resolved. This may start a new
+ // process and/or thread (i.e. new upid/utid).
+ TrackId track_id =
+ *context_->track_tracker->GetDescriptorTrack(decoder.uuid());
+
+ if (decoder.has_process()) {
+ UniquePid upid = ParseProcessDescriptor(decoder.process());
+ if (decoder.has_chrome_process())
+ ParseChromeProcessDescriptor(upid, decoder.chrome_process());
+ }
+
+ if (decoder.has_thread()) {
+ UniqueTid utid = ParseThreadDescriptor(decoder.thread());
+ if (decoder.has_chrome_thread())
+ ParseChromeThreadDescriptor(utid, decoder.chrome_thread());
+ }
+
+ if (decoder.has_name()) {
+ auto* tracks = context_->storage->mutable_track_table();
+ StringId name_id = context_->storage->InternString(decoder.name());
+ tracks->mutable_name()->Set(*tracks->id().IndexOf(track_id), name_id);
+ }
+}
+
+UniquePid TrackEventParser::ParseProcessDescriptor(
+ protozero::ConstBytes process_descriptor) {
+ protos::pbzero::ProcessDescriptor::Decoder decoder(process_descriptor);
+ UniquePid upid = context_->process_tracker->GetOrCreateProcess(
+ static_cast<uint32_t>(decoder.pid()));
+ if (decoder.has_process_name() && decoder.process_name().size) {
+ // Don't override system-provided names.
+ context_->process_tracker->SetProcessNameIfUnset(
+ upid, context_->storage->InternString(decoder.process_name()));
+ }
+ // TODO(skyostil): Remove parsing for legacy chrome_process_type field.
+ if (decoder.has_chrome_process_type()) {
+ auto process_type = decoder.chrome_process_type();
+ size_t name_index =
+ static_cast<size_t>(process_type) < chrome_process_name_ids_.size()
+ ? static_cast<size_t>(process_type)
+ : 0u;
+ StringId name_id = chrome_process_name_ids_[name_index];
+ // Don't override system-provided names.
+ context_->process_tracker->SetProcessNameIfUnset(upid, name_id);
+ }
+ return upid;
+}
+
+void TrackEventParser::ParseChromeProcessDescriptor(
+ UniquePid upid,
+ protozero::ConstBytes chrome_process_descriptor) {
+ protos::pbzero::ChromeProcessDescriptor::Decoder decoder(
+ chrome_process_descriptor);
+ auto process_type = decoder.process_type();
+ size_t name_index =
+ static_cast<size_t>(process_type) < chrome_process_name_ids_.size()
+ ? static_cast<size_t>(process_type)
+ : 0u;
+ StringId name_id = chrome_process_name_ids_[name_index];
+ // Don't override system-provided names.
+ context_->process_tracker->SetProcessNameIfUnset(upid, name_id);
+}
+
+UniqueTid TrackEventParser::ParseThreadDescriptor(
+ protozero::ConstBytes thread_descriptor) {
+ protos::pbzero::ThreadDescriptor::Decoder decoder(thread_descriptor);
+ UniqueTid utid = context_->process_tracker->UpdateThread(
+ static_cast<uint32_t>(decoder.tid()),
+ static_cast<uint32_t>(decoder.pid()));
+ StringId name_id = kNullStringId;
+ if (decoder.has_thread_name() && decoder.thread_name().size) {
+ name_id = context_->storage->InternString(decoder.thread_name());
+ } else if (decoder.has_chrome_thread_type()) {
+ // TODO(skyostil): Remove parsing for legacy chrome_thread_type field.
+ auto thread_type = decoder.chrome_thread_type();
+ size_t name_index =
+ static_cast<size_t>(thread_type) < chrome_thread_name_ids_.size()
+ ? static_cast<size_t>(thread_type)
+ : 0u;
+ name_id = chrome_thread_name_ids_[name_index];
+ }
+ if (name_id != kNullStringId) {
+ // Don't override system-provided names.
+ context_->process_tracker->SetThreadNameIfUnset(utid, name_id);
+ }
+ return utid;
+}
+
+void TrackEventParser::ParseChromeThreadDescriptor(
+ UniqueTid utid,
+ protozero::ConstBytes chrome_thread_descriptor) {
+ protos::pbzero::ChromeThreadDescriptor::Decoder decoder(
+ chrome_thread_descriptor);
+ if (!decoder.has_thread_type())
+ return;
+
+ auto thread_type = decoder.thread_type();
+ size_t name_index =
+ static_cast<size_t>(thread_type) < chrome_thread_name_ids_.size()
+ ? static_cast<size_t>(thread_type)
+ : 0u;
+ StringId name_id = chrome_thread_name_ids_[name_index];
+ context_->process_tracker->SetThreadNameIfUnset(utid, name_id);
+}
void TrackEventParser::ParseTrackEvent(
int64_t ts,
@@ -252,7 +391,7 @@
category_strings.push_back(*it);
}
- StringId category_id = 0;
+ StringId category_id = kNullStringId;
// If there's a single category, we can avoid building a concatenated
// string.
@@ -289,7 +428,7 @@
category_id = storage->InternString(base::StringView(categories));
}
- StringId name_id = 0;
+ StringId name_id = kNullStringId;
uint64_t name_iid = event.name_iid();
if (!name_iid)
@@ -317,9 +456,19 @@
base::Optional<UniqueTid> utid;
base::Optional<UniqueTid> upid;
+ // All events in legacy JSON require a thread ID, but for some types of events
+ // (e.g. async events or process/global-scoped instants), we don't store it in
+ // the slice/track model. To pass the utid through to the json export, we
+ // store it in an arg.
+ base::Optional<UniqueTid> legacy_passthrough_utid;
+
// Determine track from track_uuid specified in either TrackEvent or
- // TrackEventDefaults. If none is set, fall back to the track specified by the
- // sequence's (or event's) pid + tid or a default track.
+ // TrackEventDefaults. If a non-default track is not set, we either:
+ // a) fall back to the track specified by the sequence's (or event's) pid +
+ // tid (only in case of legacy tracks/events, i.e. events that don't
+ // specify an explicit track uuid or use legacy event phases instead of
+ // TrackEvent types), or
+ // b) a default track.
if (track_uuid) {
base::Optional<TrackId> opt_track_id =
track_tracker->GetDescriptorTrack(track_uuid);
@@ -334,16 +483,25 @@
context_->storage->thread_track_table().id().IndexOf(track_id);
if (thread_track_row) {
utid = storage->thread_track_table().utid()[*thread_track_row];
- upid = storage->GetThread(*utid).upid;
+ upid = storage->thread_table().upid()[*utid];
} else {
auto process_track_row =
context_->storage->process_track_table().id().IndexOf(track_id);
- if (process_track_row)
+ if (process_track_row) {
upid = storage->process_track_table().upid()[*process_track_row];
+ if (sequence_state->state()->pid_and_tid_valid()) {
+ uint32_t pid = static_cast<uint32_t>(sequence_state->state()->pid());
+ uint32_t tid = static_cast<uint32_t>(sequence_state->state()->tid());
+ UniqueTid utid_candidate = procs->UpdateThread(tid, pid);
+ if (storage->thread_table().upid()[utid_candidate] == upid)
+ legacy_passthrough_utid = utid_candidate;
+ }
+ }
}
- } else if (sequence_state->state()->pid_and_tid_valid() ||
- (legacy_event.has_pid_override() &&
- legacy_event.has_tid_override())) {
+ } else if ((!event.has_track_uuid() || !event.has_type()) &&
+ (sequence_state->state()->pid_and_tid_valid() ||
+ (legacy_event.has_pid_override() &&
+ legacy_event.has_tid_override()))) {
uint32_t pid = static_cast<uint32_t>(sequence_state->state()->pid());
uint32_t tid = static_cast<uint32_t>(sequence_state->state()->tid());
if (legacy_event.has_pid_override())
@@ -352,18 +510,12 @@
tid = static_cast<uint32_t>(legacy_event.tid_override());
utid = procs->UpdateThread(tid, pid);
- upid = storage->GetThread(*utid).upid;
- track_id = track_tracker->GetOrCreateDescriptorTrackForThread(*utid);
+ upid = storage->thread_table().upid()[*utid];
+ track_id = track_tracker->InternThreadTrack(*utid);
} else {
track_id = track_tracker->GetOrCreateDefaultDescriptorTrack();
}
- // All events in legacy JSON require a thread ID, but for some types of events
- // (e.g. async events or process/global-scoped instants), we don't store it in
- // the slice/track model. To pass the original tid through to the json export,
- // we store it in an arg.
- uint32_t legacy_tid = 0;
-
// TODO(eseckler): Replace phase with type and remove handling of
// legacy_event.phase() once it is no longer used by producers.
int32_t phase = 0;
@@ -409,8 +561,7 @@
track_id = context_->track_tracker->InternLegacyChromeAsyncTrack(
name_id, upid ? *upid : 0, source_id, source_id_is_process_scoped,
id_scope);
- if (utid)
- legacy_tid = storage->GetThread(*utid).tid;
+ legacy_passthrough_utid = utid;
break;
}
case 'i':
@@ -431,8 +582,7 @@
case LegacyEvent::SCOPE_GLOBAL:
track_id = context_->track_tracker
->GetOrCreateLegacyChromeGlobalInstantTrack();
- if (utid)
- legacy_tid = storage->GetThread(*utid).tid;
+ legacy_passthrough_utid = utid;
break;
case LegacyEvent::SCOPE_PROCESS:
if (!upid) {
@@ -445,8 +595,7 @@
track_id =
context_->track_tracker->InternLegacyChromeProcessInstantTrack(
*upid);
- if (utid)
- legacy_tid = storage->GetThread(*utid).tid;
+ legacy_passthrough_utid = utid;
break;
}
break;
@@ -472,7 +621,8 @@
}
auto args_callback = [this, &event, &legacy_event, sequence_state, ts, utid,
- legacy_tid](ArgsTracker::BoundInserter* inserter) {
+ legacy_passthrough_utid](
+ ArgsTracker::BoundInserter* inserter) {
for (auto it = event.debug_annotations(); it; ++it) {
ParseDebugAnnotationArgs(*it, sequence_state, inserter);
}
@@ -500,9 +650,9 @@
ParseChromeHistogramSample(event.chrome_histogram_sample(), inserter);
}
- if (legacy_tid) {
- inserter->AddArg(legacy_event_original_tid_id_,
- Variadic::Integer(static_cast<int32_t>(legacy_tid)));
+ if (legacy_passthrough_utid) {
+ inserter->AddArg(legacy_event_passthrough_utid_id_,
+ Variadic::UnsignedInteger(*legacy_passthrough_utid));
}
// TODO(eseckler): Parse legacy flow events into flow events table once we
@@ -756,14 +906,14 @@
return;
}
- uint32_t row = context_->storage->mutable_raw_events()->AddRawEvent(
- ts, raw_legacy_event_id_, 0, *utid);
+ RawId id = context_->storage->mutable_raw_table()->Insert(
+ {ts, raw_legacy_event_id_, 0, *utid});
ArgsTracker args(context_);
- ArgsTracker::BoundInserter inserter(&args, TableId::kRawEvents, row);
+ auto inserter = args.AddArgsTo(id);
- inserter.AddArg(legacy_event_category_key_id_, Variadic::String(category_id));
- inserter.AddArg(legacy_event_name_key_id_, Variadic::String(name_id));
+ inserter.AddArg(legacy_event_category_key_id_, Variadic::String(category_id))
+ .AddArg(legacy_event_name_key_id_, Variadic::String(name_id));
std::string phase_string(1, static_cast<char>(legacy_event.phase()));
StringId phase_id = context_->storage->InternString(phase_string.c_str());
@@ -837,7 +987,7 @@
protos::pbzero::DebugAnnotation::Decoder annotation(debug_annotation.data,
debug_annotation.size);
- StringId name_id = 0;
+ StringId name_id = kNullStringId;
uint64_t name_iid = annotation.name_iid();
if (PERFETTO_LIKELY(name_iid)) {
@@ -954,8 +1104,8 @@
if (!decoder)
return;
- StringId file_name_id = 0;
- StringId function_name_id = 0;
+ StringId file_name_id = kNullStringId;
+ StringId function_name_id = kNullStringId;
uint32_t line_number = 0;
TraceStorage* storage = context_->storage.get();
@@ -987,7 +1137,7 @@
TraceStorage* storage = context_->storage.get();
- StringId log_message_id = 0;
+ StringId log_message_id = kNullStringId;
auto* decoder = sequence_state->LookupInternedMessage<
protos::pbzero::InternedData::kLogMessageBodyFieldNumber,
@@ -1002,8 +1152,8 @@
context_->storage->mutable_android_log_table()->Insert(
{ts, *utid,
/*priority*/ 0,
- /*tag_id*/ 0, // TODO(nicomazz): Abuse tag_id to display
- // "file_name:line_number".
+ /*tag_id*/ kNullStringId, // TODO(nicomazz): Abuse tag_id to display
+ // "file_name:line_number".
log_message_id});
inserter->AddArg(log_message_body_key_id_, Variadic::String(log_message_id));
diff --git a/src/trace_processor/importers/proto/track_event_parser.h b/src/trace_processor/importers/proto/track_event_parser.h
index a0a42c7..10d8e03 100644
--- a/src/trace_processor/importers/proto/track_event_parser.h
+++ b/src/trace_processor/importers/proto/track_event_parser.h
@@ -39,11 +39,19 @@
public:
explicit TrackEventParser(TraceProcessorContext* context);
+ void ParseTrackDescriptor(protozero::ConstBytes);
+ UniquePid ParseProcessDescriptor(protozero::ConstBytes);
+ UniqueTid ParseThreadDescriptor(protozero::ConstBytes);
+
void ParseTrackEvent(int64_t ts,
int64_t tts,
int64_t ticount,
PacketSequenceStateGeneration*,
protozero::ConstBytes);
+
+ private:
+ void ParseChromeProcessDescriptor(UniquePid upid, protozero::ConstBytes);
+ void ParseChromeThreadDescriptor(UniqueTid utid, protozero::ConstBytes);
void ParseLegacyEventAsRawEvent(
int64_t ts,
int64_t tts,
@@ -80,7 +88,6 @@
void ParseChromeHistogramSample(protozero::ConstBytes chrome_keyed_service,
ArgsTracker::BoundInserter* inserter);
- private:
TraceProcessorContext* context_;
const StringId task_file_name_args_key_id_;
@@ -88,7 +95,7 @@
const StringId task_line_number_args_key_id_;
const StringId log_message_body_key_id_;
const StringId raw_legacy_event_id_;
- const StringId legacy_event_original_tid_id_;
+ const StringId legacy_event_passthrough_utid_id_;
const StringId legacy_event_category_key_id_;
const StringId legacy_event_name_key_id_;
const StringId legacy_event_phase_key_id_;
@@ -117,6 +124,8 @@
const StringId chrome_histogram_sample_sample_args_key_id_;
std::array<StringId, 38> chrome_legacy_ipc_class_ids_;
+ std::array<StringId, 9> chrome_process_name_ids_;
+ std::array<StringId, 14> chrome_thread_name_ids_;
};
} // namespace trace_processor
diff --git a/src/trace_processor/importers/proto/track_event_tokenizer.cc b/src/trace_processor/importers/proto/track_event_tokenizer.cc
index 44f0750..ebd1391 100644
--- a/src/trace_processor/importers/proto/track_event_tokenizer.cc
+++ b/src/trace_processor/importers/proto/track_event_tokenizer.cc
@@ -41,63 +41,20 @@
namespace trace_processor {
TrackEventTokenizer::TrackEventTokenizer(TraceProcessorContext* context)
- : context_(context),
- process_name_ids_{{context_->storage->InternString("Unknown"),
- context_->storage->InternString("Browser"),
- context_->storage->InternString("Renderer"),
- context_->storage->InternString("Utility"),
- context_->storage->InternString("Zygote"),
- context_->storage->InternString("SandboxHelper"),
- context_->storage->InternString("Gpu"),
- context_->storage->InternString("PpapiPlugin"),
- context_->storage->InternString("PpapiBroker")}} {}
+ : context_(context) {}
-void TrackEventTokenizer::TokenizeTrackDescriptorPacket(
- const protos::pbzero::TracePacket::Decoder& packet_decoder) {
+ModuleResult TrackEventTokenizer::TokenizeTrackDescriptorPacket(
+ PacketSequenceState* state,
+ const protos::pbzero::TracePacket::Decoder& packet_decoder,
+ int64_t packet_timestamp) {
auto track_descriptor_field = packet_decoder.track_descriptor();
protos::pbzero::TrackDescriptor::Decoder track_descriptor_decoder(
track_descriptor_field.data, track_descriptor_field.size);
if (!track_descriptor_decoder.has_uuid()) {
- PERFETTO_ELOG("TrackDescriptor packet without trusted_packet_sequence_id");
+ PERFETTO_ELOG("TrackDescriptor packet without uuid");
context_->storage->IncrementStats(stats::track_event_tokenizer_errors);
- return;
- }
-
- base::Optional<UniquePid> upid;
- base::Optional<UniqueTid> utid;
-
- if (track_descriptor_decoder.has_process()) {
- auto process_descriptor_field = track_descriptor_decoder.process();
- protos::pbzero::ProcessDescriptor::Decoder process_descriptor_decoder(
- process_descriptor_field.data, process_descriptor_field.size);
-
- // TODO(eseckler): Also parse process name / type here.
-
- upid = context_->process_tracker->GetOrCreateProcess(
- static_cast<uint32_t>(process_descriptor_decoder.pid()));
-
- if (track_descriptor_decoder.has_chrome_process()) {
- auto chrome_process_descriptor_field =
- track_descriptor_decoder.chrome_process();
- protos::pbzero::ChromeProcessDescriptor::Decoder
- chrome_process_descriptor_decoder(
- chrome_process_descriptor_field.data,
- chrome_process_descriptor_field.size);
-
- auto process_type = chrome_process_descriptor_decoder.process_type();
- size_t name_index =
- static_cast<size_t>(process_type) < process_name_ids_.size()
- ? static_cast<size_t>(process_type)
- : 0u;
- StringId name = process_name_ids_[name_index];
-
- // Don't override system-provided names.
- context_->process_tracker->SetProcessNameIfUnset(
- context_->process_tracker->GetOrCreateProcess(
- static_cast<uint32_t>(process_descriptor_decoder.pid())),
- name);
- }
+ return ModuleResult::Handled();
}
if (track_descriptor_decoder.has_thread()) {
@@ -105,61 +62,57 @@
protos::pbzero::ThreadDescriptor::Decoder thread_descriptor_decoder(
thread_descriptor_field.data, thread_descriptor_field.size);
- TokenizeThreadDescriptor(thread_descriptor_decoder);
- utid = context_->process_tracker->UpdateThread(
- static_cast<uint32_t>(thread_descriptor_decoder.tid()),
- static_cast<uint32_t>(thread_descriptor_decoder.pid()));
- upid = *context_->storage->GetThread(*utid).upid;
-
- if (track_descriptor_decoder.has_chrome_thread()) {
- auto chrome_thread_descriptor_field =
- track_descriptor_decoder.chrome_thread();
- protos::pbzero::ChromeThreadDescriptor::Decoder
- chrome_thread_descriptor_decoder(chrome_thread_descriptor_field.data,
- chrome_thread_descriptor_field.size);
-
- TokenizeChromeThreadDescriptor(thread_descriptor_decoder.pid(),
- thread_descriptor_decoder.tid(),
- chrome_thread_descriptor_decoder);
+ if (!thread_descriptor_decoder.has_pid() ||
+ !thread_descriptor_decoder.has_tid()) {
+ PERFETTO_ELOG(
+ "No pid or tid in ThreadDescriptor for track with uuid %" PRIu64,
+ track_descriptor_decoder.uuid());
+ context_->storage->IncrementStats(stats::track_event_tokenizer_errors);
+ return ModuleResult::Handled();
}
+
+ if (state->IsIncrementalStateValid()) {
+ TokenizeThreadDescriptor(state, thread_descriptor_decoder);
+ }
+
+ context_->track_tracker->ReserveDescriptorThreadTrack(
+ track_descriptor_decoder.uuid(), track_descriptor_decoder.parent_uuid(),
+ static_cast<uint32_t>(thread_descriptor_decoder.pid()),
+ static_cast<uint32_t>(thread_descriptor_decoder.tid()),
+ packet_timestamp);
+ } else if (track_descriptor_decoder.has_process()) {
+ auto process_descriptor_field = track_descriptor_decoder.process();
+ protos::pbzero::ProcessDescriptor::Decoder process_descriptor_decoder(
+ process_descriptor_field.data, process_descriptor_field.size);
+
+ if (!process_descriptor_decoder.has_pid()) {
+ PERFETTO_ELOG("No pid in ProcessDescriptor for track with uuid %" PRIu64,
+ track_descriptor_decoder.uuid());
+ context_->storage->IncrementStats(stats::track_event_tokenizer_errors);
+ return ModuleResult::Handled();
+ }
+
+ context_->track_tracker->ReserveDescriptorProcessTrack(
+ track_descriptor_decoder.uuid(),
+ static_cast<uint32_t>(process_descriptor_decoder.pid()),
+ packet_timestamp);
+ } else {
+ context_->track_tracker->ReserveDescriptorChildTrack(
+ track_descriptor_decoder.uuid(),
+ track_descriptor_decoder.parent_uuid());
}
- StringId name_id =
- context_->storage->InternString(track_descriptor_decoder.name());
-
- context_->track_tracker->UpdateDescriptorTrack(
- track_descriptor_decoder.uuid(), name_id, upid, utid);
+ // Let ProtoTraceTokenizer forward the packet to the parser.
+ return ModuleResult::Ignored();
}
-void TrackEventTokenizer::TokenizeProcessDescriptorPacket(
- const protos::pbzero::TracePacket::Decoder& packet_decoder) {
- protos::pbzero::ProcessDescriptor::Decoder process_descriptor_decoder(
- packet_decoder.process_descriptor());
- // TODO(skyostil): Remove parsing for legacy chrome_process_type field.
- if (!process_descriptor_decoder.has_chrome_process_type())
- return;
-
- auto process_type = process_descriptor_decoder.chrome_process_type();
- size_t name_index =
- static_cast<size_t>(process_type) < process_name_ids_.size()
- ? static_cast<size_t>(process_type)
- : 0u;
- StringId name = process_name_ids_[name_index];
-
- // Don't override system-provided names.
- context_->process_tracker->SetProcessNameIfUnset(
- context_->process_tracker->GetOrCreateProcess(
- static_cast<uint32_t>(process_descriptor_decoder.pid())),
- name);
-}
-
-void TrackEventTokenizer::TokenizeThreadDescriptorPacket(
+ModuleResult TrackEventTokenizer::TokenizeThreadDescriptorPacket(
PacketSequenceState* state,
const protos::pbzero::TracePacket::Decoder& packet_decoder) {
if (PERFETTO_UNLIKELY(!packet_decoder.has_trusted_packet_sequence_id())) {
PERFETTO_ELOG("ThreadDescriptor packet without trusted_packet_sequence_id");
context_->storage->IncrementStats(stats::track_event_tokenizer_errors);
- return;
+ return ModuleResult::Handled();
}
// TrackEvents will be ignored while incremental state is invalid. As a
@@ -169,155 +122,29 @@
// the first subsequent descriptor after incremental state is cleared.
if (!state->IsIncrementalStateValid()) {
context_->storage->IncrementStats(stats::tokenizer_skipped_packets);
- return;
+ return ModuleResult::Handled();
}
auto thread_descriptor_field = packet_decoder.thread_descriptor();
protos::pbzero::ThreadDescriptor::Decoder thread_descriptor_decoder(
thread_descriptor_field.data, thread_descriptor_field.size);
+ TokenizeThreadDescriptor(state, thread_descriptor_decoder);
+ // Let ProtoTraceTokenizer forward the packet to the parser.
+ return ModuleResult::Ignored();
+}
+
+void TrackEventTokenizer::TokenizeThreadDescriptor(
+ PacketSequenceState* state,
+ const protos::pbzero::ThreadDescriptor::Decoder&
+ thread_descriptor_decoder) {
+ // TODO(eseckler): Remove support for legacy thread descriptor-based default
+ // tracks and delta timestamps.
state->SetThreadDescriptor(
thread_descriptor_decoder.pid(), thread_descriptor_decoder.tid(),
thread_descriptor_decoder.reference_timestamp_us() * 1000,
thread_descriptor_decoder.reference_thread_time_us() * 1000,
thread_descriptor_decoder.reference_thread_instruction_count());
-
- TokenizeThreadDescriptor(thread_descriptor_decoder);
-}
-
-void TrackEventTokenizer::TokenizeThreadDescriptor(
- const protos::pbzero::ThreadDescriptor::Decoder&
- thread_descriptor_decoder) {
- base::StringView name;
- if (thread_descriptor_decoder.has_thread_name()) {
- name = thread_descriptor_decoder.thread_name();
- } else if (thread_descriptor_decoder.has_chrome_thread_type()) {
- // TODO(skyostil): Remove parsing for legacy chrome_thread_type field.
- using protos::pbzero::ThreadDescriptor;
- switch (thread_descriptor_decoder.chrome_thread_type()) {
- case ThreadDescriptor::CHROME_THREAD_MAIN:
- name = "CrProcessMain";
- break;
- case ThreadDescriptor::CHROME_THREAD_IO:
- name = "ChromeIOThread";
- break;
- case ThreadDescriptor::CHROME_THREAD_POOL_FG_WORKER:
- name = "ThreadPoolForegroundWorker&";
- break;
- case ThreadDescriptor::CHROME_THREAD_POOL_BG_WORKER:
- name = "ThreadPoolBackgroundWorker&";
- break;
- case ThreadDescriptor::CHROME_THREAD_POOL_FB_BLOCKING:
- name = "ThreadPoolSingleThreadForegroundBlocking&";
- break;
- case ThreadDescriptor::CHROME_THREAD_POOL_BG_BLOCKING:
- name = "ThreadPoolSingleThreadBackgroundBlocking&";
- break;
- case ThreadDescriptor::CHROME_THREAD_POOL_SERVICE:
- name = "ThreadPoolService";
- break;
- case ThreadDescriptor::CHROME_THREAD_COMPOSITOR_WORKER:
- name = "CompositorTileWorker&";
- break;
- case ThreadDescriptor::CHROME_THREAD_COMPOSITOR:
- name = "Compositor";
- break;
- case ThreadDescriptor::CHROME_THREAD_VIZ_COMPOSITOR:
- name = "VizCompositorThread";
- break;
- case ThreadDescriptor::CHROME_THREAD_SERVICE_WORKER:
- name = "ServiceWorkerThread&";
- break;
- case ThreadDescriptor::CHROME_THREAD_MEMORY_INFRA:
- name = "MemoryInfra";
- break;
- case ThreadDescriptor::CHROME_THREAD_SAMPLING_PROFILER:
- name = "StackSamplingProfiler";
- break;
- case ThreadDescriptor::CHROME_THREAD_UNSPECIFIED:
- name = "ChromeUnspecified";
- break;
- }
- }
-
- if (!name.empty()) {
- auto thread_name_id = context_->storage->InternString(name);
- ProcessTracker* procs = context_->process_tracker.get();
- // Don't override system-provided names.
- procs->SetThreadNameIfUnset(
- procs->UpdateThread(
- static_cast<uint32_t>(thread_descriptor_decoder.tid()),
- static_cast<uint32_t>(thread_descriptor_decoder.pid())),
- thread_name_id);
- }
-}
-
-void TrackEventTokenizer::TokenizeChromeThreadDescriptor(
- int32_t pid,
- int32_t tid,
- const protos::pbzero::ChromeThreadDescriptor::Decoder&
- thread_descriptor_decoder) {
- if (!thread_descriptor_decoder.has_thread_type())
- return;
-
- base::StringView name;
- using protos::pbzero::ChromeThreadDescriptor;
- // Thread names that end in an ampersand indicate multiple thread instances
- // (e.g., CompositorTileWorker{1,2,...}) that have been collapsed into a
- // single thread name.
- switch (thread_descriptor_decoder.thread_type()) {
- case ChromeThreadDescriptor::THREAD_MAIN:
- name = "CrProcessMain";
- break;
- case ChromeThreadDescriptor::THREAD_IO:
- name = "ChromeIOThread";
- break;
- case ChromeThreadDescriptor::THREAD_POOL_FG_WORKER:
- name = "ThreadPoolForegroundWorker&";
- break;
- case ChromeThreadDescriptor::THREAD_POOL_BG_WORKER:
- name = "ThreadPoolBackgroundWorker&";
- break;
- case ChromeThreadDescriptor::THREAD_POOL_FB_BLOCKING:
- name = "ThreadPoolSingleThreadForegroundBlocking&";
- break;
- case ChromeThreadDescriptor::THREAD_POOL_BG_BLOCKING:
- name = "ThreadPoolSingleThreadBackgroundBlocking&";
- break;
- case ChromeThreadDescriptor::THREAD_POOL_SERVICE:
- name = "ThreadPoolService";
- break;
- case ChromeThreadDescriptor::THREAD_COMPOSITOR_WORKER:
- name = "CompositorTileWorker&";
- break;
- case ChromeThreadDescriptor::THREAD_COMPOSITOR:
- name = "Compositor";
- break;
- case ChromeThreadDescriptor::THREAD_VIZ_COMPOSITOR:
- name = "VizCompositorThread";
- break;
- case ChromeThreadDescriptor::THREAD_SERVICE_WORKER:
- name = "ServiceWorkerThread&";
- break;
- case ChromeThreadDescriptor::THREAD_MEMORY_INFRA:
- name = "MemoryInfra";
- break;
- case ChromeThreadDescriptor::THREAD_SAMPLING_PROFILER:
- name = "StackSamplingProfiler";
- break;
- case ChromeThreadDescriptor::THREAD_UNSPECIFIED:
- name = "ChromeUnspecified";
- break;
- }
-
- if (!name.empty()) {
- auto thread_name_id = context_->storage->InternString(name);
- ProcessTracker* procs = context_->process_tracker.get();
- // Don't override system-provided names.
- procs->SetThreadNameIfUnset(procs->UpdateThread(static_cast<uint32_t>(tid),
- static_cast<uint32_t>(pid)),
- thread_name_id);
- }
}
void TrackEventTokenizer::TokenizeTrackEventPacket(
@@ -392,7 +219,7 @@
protos::pbzero::ClockSnapshot::Clock::MONOTONIC, timestamp);
if (trace_ts.has_value())
timestamp = trace_ts.value();
- } else if (packet_decoder.timestamp()) {
+ } else if (packet_decoder.has_timestamp()) {
timestamp = packet_timestamp;
} else {
PERFETTO_ELOG("TrackEvent without valid timestamp");
diff --git a/src/trace_processor/importers/proto/track_event_tokenizer.h b/src/trace_processor/importers/proto/track_event_tokenizer.h
index 4c848f7..48fdf47 100644
--- a/src/trace_processor/importers/proto/track_event_tokenizer.h
+++ b/src/trace_processor/importers/proto/track_event_tokenizer.h
@@ -19,6 +19,7 @@
#include <stdint.h>
+#include "src/trace_processor/importers/proto/proto_importer_module.h"
#include "src/trace_processor/trace_storage.h"
namespace perfetto {
@@ -26,6 +27,7 @@
namespace protos {
namespace pbzero {
class ChromeThreadDescriptor_Decoder;
+class ProcessDescriptor_Decoder;
class ThreadDescriptor_Decoder;
class TracePacket_Decoder;
} // namespace pbzero
@@ -41,28 +43,24 @@
public:
explicit TrackEventTokenizer(TraceProcessorContext* context);
- void TokenizeTrackDescriptorPacket(
- const protos::pbzero::TracePacket_Decoder&);
- void TokenizeProcessDescriptorPacket(
- const protos::pbzero::TracePacket_Decoder&);
- void TokenizeThreadDescriptorPacket(
+ ModuleResult TokenizeTrackDescriptorPacket(
+ PacketSequenceState* state,
+ const protos::pbzero::TracePacket_Decoder&,
+ int64_t packet_timestamp);
+ ModuleResult TokenizeThreadDescriptorPacket(
PacketSequenceState* state,
const protos::pbzero::TracePacket_Decoder&);
- void TokenizeThreadDescriptor(
- const protos::pbzero::ThreadDescriptor_Decoder&);
- void TokenizeChromeThreadDescriptor(
- int32_t pid,
- int32_t tid,
- const protos::pbzero::ChromeThreadDescriptor_Decoder&);
void TokenizeTrackEventPacket(PacketSequenceState* state,
const protos::pbzero::TracePacket_Decoder&,
TraceBlobView* packet,
int64_t packet_timestamp);
private:
- TraceProcessorContext* context_;
+ void TokenizeThreadDescriptor(
+ PacketSequenceState* state,
+ const protos::pbzero::ThreadDescriptor_Decoder&);
- std::array<StringId, 9> process_name_ids_;
+ TraceProcessorContext* context_;
};
} // namespace trace_processor
diff --git a/src/trace_processor/importers/systrace/systrace_parser.cc b/src/trace_processor/importers/systrace/systrace_parser.cc
index b6642a2..745a447 100644
--- a/src/trace_processor/importers/systrace/systrace_parser.cc
+++ b/src/trace_processor/importers/systrace/systrace_parser.cc
@@ -109,7 +109,8 @@
StringId name_id = context_->storage->InternString(point.name);
UniqueTid utid = context_->process_tracker->UpdateThread(pid, point.tgid);
TrackId track_id = context_->track_tracker->InternThreadTrack(utid);
- context_->slice_tracker->Begin(ts, track_id, 0 /* cat */, name_id);
+ context_->slice_tracker->Begin(ts, track_id, kNullStringId /* cat */,
+ name_id);
break;
}
@@ -142,7 +143,7 @@
TrackId track_id = context_->track_tracker->InternAndroidAsyncTrack(
name_id, upid, cookie);
if (point.phase == 'S') {
- context_->slice_tracker->Begin(ts, track_id, 0, name_id);
+ context_->slice_tracker->Begin(ts, track_id, kNullStringId, name_id);
} else {
context_->slice_tracker->End(ts, track_id);
}
diff --git a/src/trace_processor/importers/systrace/systrace_trace_parser.cc b/src/trace_processor/importers/systrace/systrace_trace_parser.cc
index 2ffaac4..d23581c 100644
--- a/src/trace_processor/importers/systrace/systrace_trace_parser.cc
+++ b/src/trace_processor/importers/systrace/systrace_trace_parser.cc
@@ -27,6 +27,7 @@
#include "src/trace_processor/track_tracker.h"
#include <inttypes.h>
+#include <cctype>
#include <string>
#include <unordered_map>
@@ -37,9 +38,9 @@
std::string SubstrTrim(const std::string& input) {
std::string s = input;
s.erase(s.begin(), std::find_if(s.begin(), s.end(),
- [](int ch) { return !std::isspace(ch); }));
+ [](char ch) { return !std::isspace(ch); }));
s.erase(std::find_if(s.rbegin(), s.rend(),
- [](int ch) { return !std::isspace(ch); })
+ [](char ch) { return !std::isspace(ch); })
.base(),
s.end());
return s;
diff --git a/src/trace_processor/importers/systrace/systrace_trace_parser.h b/src/trace_processor/importers/systrace/systrace_trace_parser.h
index 1b5926b..26553e9 100644
--- a/src/trace_processor/importers/systrace/systrace_trace_parser.h
+++ b/src/trace_processor/importers/systrace/systrace_trace_parser.h
@@ -47,8 +47,8 @@
util::Status ParseSingleSystraceEvent(const std::string& buffer);
TraceProcessorContext* const context_;
- const StringId sched_wakeup_name_id_ = 0;
- const StringId cpu_idle_name_id_ = 0;
+ const StringId sched_wakeup_name_id_ = kNullStringId;
+ const StringId cpu_idle_name_id_ = kNullStringId;
const std::regex line_matcher_;
ParseState state_ = ParseState::kBeforeParse;
diff --git a/src/trace_processor/metadata.h b/src/trace_processor/metadata.h
index e7edcd8..2546cec 100644
--- a/src/trace_processor/metadata.h
+++ b/src/trace_processor/metadata.h
@@ -20,7 +20,7 @@
#include <stddef.h>
#include "src/trace_processor/containers/string_pool.h"
-#include "src/trace_processor/variadic.h"
+#include "src/trace_processor/types/variadic.h"
namespace perfetto {
namespace trace_processor {
@@ -45,7 +45,8 @@
F(system_version, KeyType::kSingle, Variadic::kString), \
F(system_release, KeyType::kSingle, Variadic::kString), \
F(system_machine, KeyType::kSingle, Variadic::kString), \
- F(android_build_fingerprint, KeyType::kSingle, Variadic::kString)
+ F(android_build_fingerprint, KeyType::kSingle, Variadic::kString), \
+ F(trace_size_bytes, KeyType::kSingle, Variadic::kInt)
// clang-format on
// Compile time list of metadata items.
@@ -55,6 +56,9 @@
F(kMulti, "multi")
// clang-format
+// Ignore GCC warning about a missing argument for a variadic macro parameter.
+#pragma GCC system_header
+
#define PERFETTO_TP_META_TYPE_ENUM(varname, ...) varname
enum class KeyType : size_t {
PERFETTO_TP_METADATA_KEY_TYPES(PERFETTO_TP_META_TYPE_ENUM),
diff --git a/src/trace_processor/metrics/BUILD.gn b/src/trace_processor/metrics/BUILD.gn
index 537f55e..92512a9 100644
--- a/src/trace_processor/metrics/BUILD.gn
+++ b/src/trace_processor/metrics/BUILD.gn
@@ -32,6 +32,7 @@
"android/android_startup_cpu.sql",
"android/android_package_list.sql",
"android/heap_profile_callsites.sql",
+ "android/android_hwui_metric.sql",
"android/java_heap_stats.sql",
"android/process_unagg_mem_view.sql",
"android/process_mem.sql",
@@ -56,46 +57,45 @@
rebase_path(generated_header, root_build_dir),
]
inputs = sql_files
- outputs = [
- generated_header,
- ]
+ outputs = [ generated_header ]
public_configs = [ ":gen_config" ]
}
-source_set("lib") {
- sources = [
- "metrics.cc",
- "metrics.descriptor.h",
- "metrics.h",
- ]
- deps = [
- "../../../gn:default_deps",
- "../../../gn:sqlite",
- "../../../include/perfetto/trace_processor",
- "../../../protos/perfetto/common:zero",
- "../../../protos/perfetto/metrics:zero",
- "../../../protos/perfetto/metrics/android:zero",
- "../../../protos/perfetto/trace_processor:metrics_impl_zero",
- "../../base",
- "../../protozero:protozero",
- "../sqlite",
- ]
- public_deps = [
- ":gen_merged_sql_metrics",
- "../../trace_processor:descriptors",
- ]
-}
+if (enable_perfetto_trace_processor_sqlite) {
+ source_set("lib") {
+ sources = [
+ "custom_options.descriptor.h",
+ "metrics.cc",
+ "metrics.descriptor.h",
+ "metrics.h",
+ ]
+ deps = [
+ "../../../gn:default_deps",
+ "../../../gn:sqlite",
+ "../../../include/perfetto/trace_processor",
+ "../../../protos/perfetto/common:zero",
+ "../../../protos/perfetto/metrics:zero",
+ "../../../protos/perfetto/metrics/android:zero",
+ "../../../protos/perfetto/trace_processor:metrics_impl_zero",
+ "../../base",
+ "../../protozero:protozero",
+ "../sqlite",
+ ]
+ public_deps = [
+ ":gen_merged_sql_metrics",
+ "../../trace_processor:descriptors",
+ ]
+ }
-perfetto_unittest_source_set("unittests") {
- testonly = true
- sources = [
- "metrics_unittest.cc",
- ]
- deps = [
- ":lib",
- "../../../gn:default_deps",
- "../../../gn:gtest_and_gmock",
- "../../../gn:sqlite",
- "../../../protos/perfetto/common:zero",
- ]
+ perfetto_unittest_source_set("unittests") {
+ testonly = true
+ sources = [ "metrics_unittest.cc" ]
+ deps = [
+ ":lib",
+ "../../../gn:default_deps",
+ "../../../gn:gtest_and_gmock",
+ "../../../gn:sqlite",
+ "../../../protos/perfetto/common:zero",
+ ]
+ }
}
diff --git a/src/trace_processor/metrics/android/android_hwui_metric.sql b/src/trace_processor/metrics/android/android_hwui_metric.sql
new file mode 100644
index 0000000..f7ba671
--- /dev/null
+++ b/src/trace_processor/metrics/android/android_hwui_metric.sql
@@ -0,0 +1,247 @@
+--
+-- Copyright 2020 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
+--
+-- https://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.
+--
+
+
+-- TOP processes that have a RenderThread, sorted by CPU time on RT
+CREATE VIEW hwui_processes AS
+SELECT
+ process.name as process_name,
+ process.upid as process_upid,
+ CAST(SUM(sched.dur) / 1e6 as INT64) as rt_cpu_time_ms,
+ thread.utid as render_thread_id
+FROM sched
+INNER JOIN thread ON (thread.utid = sched.utid AND thread.name='RenderThread')
+INNER JOIN process ON (process.upid = thread.upid)
+GROUP BY process.name
+ORDER BY rt_cpu_time_ms DESC;
+
+CREATE VIEW hwui_draw_frame AS
+SELECT
+ count(*) as draw_frame_count,
+ max(dur) as draw_frame_max,
+ min(dur) as draw_frame_min,
+ avg(dur) as draw_frame_avg,
+ thread_track.utid as render_thread_id
+FROM slice
+INNER JOIN thread_track ON (thread_track.id = slice.track_id)
+WHERE slice.name='DrawFrame' AND slice.dur >= 0
+GROUP BY thread_track.utid;
+
+CREATE VIEW hwui_flush_commands AS
+SELECT
+ count(*) as flush_count,
+ max(dur) as flush_max,
+ min(dur) as flush_min,
+ avg(dur) as flush_avg,
+ thread_track.utid as render_thread_id
+FROM slice
+INNER JOIN thread_track ON (thread_track.id = slice.track_id)
+WHERE slice.name='flush commands' AND slice.dur >= 0
+GROUP BY thread_track.utid;
+
+CREATE VIEW hwui_prepare_tree AS
+SELECT
+ count(*) as prepare_tree_count,
+ max(dur) as prepare_tree_max,
+ min(dur) as prepare_tree_min,
+ avg(dur) as prepare_tree_avg,
+ thread_track.utid as render_thread_id
+FROM slice
+INNER JOIN thread_track ON (thread_track.id = slice.track_id)
+WHERE slice.name='prepareTree' AND slice.dur >= 0
+GROUP BY thread_track.utid;
+
+CREATE VIEW hwui_gpu_completion AS
+SELECT
+ count(*) as gpu_completion_count,
+ max(dur) as gpu_completion_max,
+ min(dur) as gpu_completion_min,
+ avg(dur) as gpu_completion_avg,
+ thread.upid as process_upid
+FROM slice
+INNER JOIN thread_track ON (thread_track.id = slice.track_id)
+INNER JOIN thread ON (thread.name='GPU completion' AND thread.utid = thread_track.utid)
+WHERE slice.name LIKE 'waiting for GPU completion%' AND slice.dur >= 0
+GROUP BY thread_track.utid;
+
+CREATE VIEW hwui_ui_record AS
+SELECT
+ count(*) as ui_record_count,
+ max(dur) as ui_record_max,
+ min(dur) as ui_record_min,
+ avg(dur) as ui_record_avg,
+ thread.upid as process_upid
+FROM slice
+INNER JOIN thread_track ON (thread_track.id = slice.track_id)
+INNER JOIN thread ON (thread.name=substr(process.name,-15) AND thread.utid = thread_track.utid)
+INNER JOIN process ON (process.upid = thread.upid)
+WHERE slice.name='Record View#draw()' AND slice.dur >= 0
+GROUP BY thread_track.utid;
+
+CREATE VIEW hwui_shader_compile AS
+SELECT
+ count(*) as shader_compile_count,
+ sum(dur) as shader_compile_time,
+ avg(dur) as shader_compile_avg,
+ thread_track.utid as render_thread_id
+FROM slice
+INNER JOIN thread_track ON (thread_track.id = slice.track_id)
+WHERE slice.name='shader_compile' AND slice.dur >= 0
+GROUP BY thread_track.utid;
+
+CREATE VIEW hwui_cache_hit AS
+SELECT
+ count(*) as cache_hit_count,
+ sum(dur) as cache_hit_time,
+ avg(dur) as cache_hit_avg,
+ thread_track.utid as render_thread_id
+FROM slice
+INNER JOIN thread_track ON (thread_track.id = slice.track_id)
+WHERE slice.name='cache_hit' AND slice.dur >= 0
+GROUP BY thread_track.utid;
+
+CREATE VIEW hwui_cache_miss AS
+SELECT
+ count(*) as cache_miss_count,
+ sum(dur) as cache_miss_time,
+ avg(dur) as cache_miss_avg,
+ thread_track.utid as render_thread_id
+FROM slice
+INNER JOIN thread_track ON (thread_track.id = slice.track_id)
+WHERE slice.name='cache_miss' AND slice.dur >= 0
+GROUP BY thread_track.utid;
+
+CREATE VIEW hwui_graphics_cpu_mem AS
+SELECT
+ max(value) as graphics_cpu_mem_max,
+ min(value) as graphics_cpu_mem_min,
+ avg(value) as graphics_cpu_mem_avg,
+ process_counter_track.upid as process_upid
+FROM counter
+INNER JOIN process_counter_track ON (counter.track_id = process_counter_track.id)
+WHERE name='HWUI CPU Memory' AND counter.value >= 0
+GROUP BY process_counter_track.upid;
+
+CREATE VIEW hwui_graphics_gpu_mem AS
+SELECT
+ max(value) as graphics_gpu_mem_max,
+ min(value) as graphics_gpu_mem_min,
+ avg(value) as graphics_gpu_mem_avg,
+ process_counter_track.upid as process_upid
+FROM counter
+INNER JOIN process_counter_track ON (counter.track_id = process_counter_track.id)
+WHERE name='HWUI GPU Memory' AND counter.value >= 0
+GROUP BY process_counter_track.upid;
+
+CREATE VIEW hwui_texture_mem AS
+SELECT
+ max(value) as texture_mem_max,
+ min(value) as texture_mem_min,
+ avg(value) as texture_mem_avg,
+ process_counter_track.upid as process_upid
+FROM counter
+INNER JOIN process_counter_track ON (counter.track_id = process_counter_track.id)
+WHERE name='HWUI Texture Memory' AND counter.value >= 0
+GROUP BY process_counter_track.upid;
+
+CREATE VIEW hwui_all_mem AS
+SELECT
+ max(value) as all_mem_max,
+ min(value) as all_mem_min,
+ avg(value) as all_mem_avg,
+ process_counter_track.upid as process_upid
+FROM counter
+INNER JOIN process_counter_track ON (counter.track_id = process_counter_track.id)
+WHERE name='HWUI All Memory' AND counter.value >= 0
+GROUP BY process_counter_track.upid;
+
+CREATE VIEW android_hwui_metric_output AS
+SELECT AndroidHwuiMetric(
+ 'process_info', (
+ SELECT RepeatedField(
+ ProcessRenderInfo(
+ 'process_name', process_name,
+ 'rt_cpu_time_ms', rt_cpu_time_ms,
+
+ 'draw_frame_count', hwui_draw_frame.draw_frame_count,
+ 'draw_frame_max', hwui_draw_frame.draw_frame_max,
+ 'draw_frame_min', hwui_draw_frame.draw_frame_min,
+ 'draw_frame_avg', hwui_draw_frame.draw_frame_avg,
+
+ 'flush_count', hwui_flush_commands.flush_count,
+ 'flush_max', hwui_flush_commands.flush_max,
+ 'flush_min', hwui_flush_commands.flush_min,
+ 'flush_avg', hwui_flush_commands.flush_avg,
+
+ 'prepare_tree_count', hwui_prepare_tree.prepare_tree_count,
+ 'prepare_tree_max', hwui_prepare_tree.prepare_tree_max,
+ 'prepare_tree_min', hwui_prepare_tree.prepare_tree_min,
+ 'prepare_tree_avg', hwui_prepare_tree.prepare_tree_avg,
+
+ 'gpu_completion_count', hwui_gpu_completion.gpu_completion_count,
+ 'gpu_completion_max', hwui_gpu_completion.gpu_completion_max,
+ 'gpu_completion_min', hwui_gpu_completion.gpu_completion_min,
+ 'gpu_completion_avg', hwui_gpu_completion.gpu_completion_avg,
+
+ 'ui_record_count', hwui_ui_record.ui_record_count,
+ 'ui_record_max', hwui_ui_record.ui_record_max,
+ 'ui_record_min', hwui_ui_record.ui_record_min,
+ 'ui_record_avg', hwui_ui_record.ui_record_avg,
+
+ 'shader_compile_count', hwui_shader_compile.shader_compile_count,
+ 'shader_compile_time', hwui_shader_compile.shader_compile_time,
+ 'shader_compile_avg', hwui_shader_compile.shader_compile_avg,
+
+ 'cache_hit_count', hwui_cache_hit.cache_hit_count,
+ 'cache_hit_time', hwui_cache_hit.cache_hit_time,
+ 'cache_hit_avg', hwui_cache_hit.cache_hit_avg,
+
+ 'cache_miss_count', hwui_cache_miss.cache_miss_count,
+ 'cache_miss_time', hwui_cache_miss.cache_miss_time,
+ 'cache_miss_avg', hwui_cache_miss.cache_miss_avg,
+
+ 'graphics_cpu_mem_max', CAST(hwui_graphics_cpu_mem.graphics_cpu_mem_max as INT64),
+ 'graphics_cpu_mem_min', CAST(hwui_graphics_cpu_mem.graphics_cpu_mem_min as INT64),
+ 'graphics_cpu_mem_avg', hwui_graphics_cpu_mem.graphics_cpu_mem_avg,
+
+ 'graphics_gpu_mem_max', CAST(hwui_graphics_gpu_mem.graphics_gpu_mem_max as INT64),
+ 'graphics_gpu_mem_min', CAST(hwui_graphics_gpu_mem.graphics_gpu_mem_min as INT64),
+ 'graphics_gpu_mem_avg', hwui_graphics_gpu_mem.graphics_gpu_mem_avg,
+
+ 'texture_mem_max', CAST(hwui_texture_mem.texture_mem_max as INT64),
+ 'texture_mem_min', CAST(hwui_texture_mem.texture_mem_min as INT64),
+ 'texture_mem_avg', hwui_texture_mem.texture_mem_avg,
+
+ 'all_mem_max', CAST(hwui_all_mem.all_mem_max as INT64),
+ 'all_mem_min', CAST(hwui_all_mem.all_mem_min as INT64),
+ 'all_mem_avg', hwui_all_mem.all_mem_avg
+ )
+ )
+ FROM hwui_processes
+ LEFT JOIN hwui_draw_frame ON (hwui_draw_frame.render_thread_id = hwui_processes.render_thread_id)
+ LEFT JOIN hwui_flush_commands ON (hwui_flush_commands.render_thread_id = hwui_processes.render_thread_id)
+ LEFT JOIN hwui_prepare_tree ON (hwui_prepare_tree.render_thread_id = hwui_processes.render_thread_id)
+ LEFT JOIN hwui_gpu_completion ON (hwui_gpu_completion.process_upid = hwui_processes.process_upid)
+ LEFT JOIN hwui_ui_record ON (hwui_ui_record.process_upid = hwui_processes.process_upid)
+ LEFT JOIN hwui_shader_compile ON (hwui_shader_compile.render_thread_id = hwui_processes.render_thread_id)
+ LEFT JOIN hwui_cache_hit ON (hwui_cache_hit.render_thread_id = hwui_processes.render_thread_id)
+ LEFT JOIN hwui_cache_miss ON (hwui_cache_miss.render_thread_id = hwui_processes.render_thread_id)
+ LEFT JOIN hwui_graphics_cpu_mem ON (hwui_graphics_cpu_mem.process_upid = hwui_processes.process_upid)
+ LEFT JOIN hwui_graphics_gpu_mem ON (hwui_graphics_gpu_mem.process_upid = hwui_processes.process_upid)
+ LEFT JOIN hwui_texture_mem ON (hwui_texture_mem.process_upid = hwui_processes.process_upid)
+ LEFT JOIN hwui_all_mem ON (hwui_all_mem.process_upid = hwui_processes.process_upid)
+ )
+);
diff --git a/src/trace_processor/metrics/android/android_startup_launches.sql b/src/trace_processor/metrics/android/android_startup_launches.sql
index 63b38ac..9b8caf1 100644
--- a/src/trace_processor/metrics/android/android_startup_launches.sql
+++ b/src/trace_processor/metrics/android/android_startup_launches.sql
@@ -32,7 +32,7 @@
SELECT
ts,
package_name,
- type
+ launching_events_helper.type
FROM raw
CROSS JOIN launching_events_helper
JOIN thread USING(utid)
diff --git a/src/trace_processor/metrics/android/unmapped_java_symbols.sql b/src/trace_processor/metrics/android/unmapped_java_symbols.sql
index c2e7785..e25745c 100644
--- a/src/trace_processor/metrics/android/unmapped_java_symbols.sql
+++ b/src/trace_processor/metrics/android/unmapped_java_symbols.sql
@@ -19,7 +19,22 @@
CREATE TABLE IF NOT EXISTS types_per_upid AS
WITH distinct_unmapped_type_names AS (
SELECT DISTINCT upid, type_name
- FROM heap_graph_object WHERE deobfuscated_type_name IS NULL
+ FROM (
+ SELECT upid, RTRIM(type_name, '[]') AS type_name
+ FROM heap_graph_object
+ WHERE deobfuscated_type_name IS NULL
+ )
+ WHERE type_name NOT IN ('byte', 'char', 'short', 'int', 'long', 'boolean', 'float', 'double')
+ AND type_name NOT LIKE '$Proxy%'
+ AND type_name NOT LIKE 'java.%'
+ AND type_name NOT LIKE 'javax.%'
+ AND type_name NOT LIKE 'j$.%'
+ AND type_name NOT LIKE 'android.%'
+ AND type_name NOT LIKE 'com.android.%'
+ AND type_name NOT LIKE 'sun.%'
+ AND type_name NOT LIKE 'dalvik.%'
+ AND type_name NOT LIKE 'libcore.%'
+ AND LENGTH(type_name) > 0
)
SELECT upid, RepeatedField(type_name) AS types
FROM distinct_unmapped_type_names GROUP BY 1;
@@ -29,6 +44,16 @@
SELECT DISTINCT upid, field_name
FROM heap_graph_object JOIN heap_graph_reference USING (reference_set_id)
WHERE deobfuscated_type_name IS NULL
+ AND field_name NOT LIKE '$Proxy%'
+ AND field_name NOT LIKE 'java.%'
+ AND field_name NOT LIKE 'javax.%'
+ AND field_name NOT LIKE 'j$.%'
+ AND field_name NOT LIKE 'android.%'
+ AND field_name NOT LIKE 'com.android.%'
+ AND field_name NOT LIKE 'sun.%'
+ AND field_name NOT LIKE 'dalvik.%'
+ AND field_name NOT LIKE 'libcore.%'
+ AND LENGTH(field_name) > 0
)
SELECT upid, RepeatedField(field_name) AS fields
FROM distinct_unmapped_field_names GROUP BY 1;
diff --git a/src/trace_processor/metrics/custom_options.descriptor.h b/src/trace_processor/metrics/custom_options.descriptor.h
new file mode 100644
index 0000000..3829d74
--- /dev/null
+++ b/src/trace_processor/metrics/custom_options.descriptor.h
@@ -0,0 +1,692 @@
+/*
+ * Copyright (C) 2019 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.
+ */
+
+#ifndef SRC_TRACE_PROCESSOR_METRICS_CUSTOM_OPTIONS_DESCRIPTOR_H_
+#define SRC_TRACE_PROCESSOR_METRICS_CUSTOM_OPTIONS_DESCRIPTOR_H_
+
+#include <stddef.h>
+#include <stdint.h>
+
+#include <array>
+
+// This file was autogenerated by tools/gen_binary_descriptors. Do not edit.
+
+// SHA1(tools/gen_binary_descriptors)
+// d6628b15181dba5287e35b56b966b39ea93d42b1
+// SHA1(protos/perfetto/metrics/custom_options.proto)
+// 074c971d85f72345988fb3279345cd6b3dabde9c
+
+// This is the proto CustomOptions encoded as a ProtoFileDescriptor to allow
+// for reflection without libprotobuf full/non-lite protos.
+
+namespace perfetto {
+
+constexpr std::array<uint8_t, 7803> kCustomOptionsDescriptor{
+ {0x0a, 0x9b, 0x3b, 0x0a, 0x20, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2f,
+ 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2f, 0x64, 0x65, 0x73,
+ 0x63, 0x72, 0x69, 0x70, 0x74, 0x6f, 0x72, 0x2e, 0x70, 0x72, 0x6f, 0x74,
+ 0x6f, 0x12, 0x0f, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72,
+ 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x22, 0x4d, 0x0a, 0x11, 0x46, 0x69,
+ 0x6c, 0x65, 0x44, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x6f, 0x72,
+ 0x53, 0x65, 0x74, 0x12, 0x38, 0x0a, 0x04, 0x66, 0x69, 0x6c, 0x65, 0x18,
+ 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x24, 0x2e, 0x67, 0x6f, 0x6f, 0x67,
+ 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e,
+ 0x46, 0x69, 0x6c, 0x65, 0x44, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74,
+ 0x6f, 0x72, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x52, 0x04, 0x66, 0x69, 0x6c,
+ 0x65, 0x22, 0xe4, 0x04, 0x0a, 0x13, 0x46, 0x69, 0x6c, 0x65, 0x44, 0x65,
+ 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x6f, 0x72, 0x50, 0x72, 0x6f, 0x74,
+ 0x6f, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20,
+ 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x18, 0x0a,
+ 0x07, 0x70, 0x61, 0x63, 0x6b, 0x61, 0x67, 0x65, 0x18, 0x02, 0x20, 0x01,
+ 0x28, 0x09, 0x52, 0x07, 0x70, 0x61, 0x63, 0x6b, 0x61, 0x67, 0x65, 0x12,
+ 0x1e, 0x0a, 0x0a, 0x64, 0x65, 0x70, 0x65, 0x6e, 0x64, 0x65, 0x6e, 0x63,
+ 0x79, 0x18, 0x03, 0x20, 0x03, 0x28, 0x09, 0x52, 0x0a, 0x64, 0x65, 0x70,
+ 0x65, 0x6e, 0x64, 0x65, 0x6e, 0x63, 0x79, 0x12, 0x2b, 0x0a, 0x11, 0x70,
+ 0x75, 0x62, 0x6c, 0x69, 0x63, 0x5f, 0x64, 0x65, 0x70, 0x65, 0x6e, 0x64,
+ 0x65, 0x6e, 0x63, 0x79, 0x18, 0x0a, 0x20, 0x03, 0x28, 0x05, 0x52, 0x10,
+ 0x70, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x44, 0x65, 0x70, 0x65, 0x6e, 0x64,
+ 0x65, 0x6e, 0x63, 0x79, 0x12, 0x27, 0x0a, 0x0f, 0x77, 0x65, 0x61, 0x6b,
+ 0x5f, 0x64, 0x65, 0x70, 0x65, 0x6e, 0x64, 0x65, 0x6e, 0x63, 0x79, 0x18,
+ 0x0b, 0x20, 0x03, 0x28, 0x05, 0x52, 0x0e, 0x77, 0x65, 0x61, 0x6b, 0x44,
+ 0x65, 0x70, 0x65, 0x6e, 0x64, 0x65, 0x6e, 0x63, 0x79, 0x12, 0x43, 0x0a,
+ 0x0c, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x5f, 0x74, 0x79, 0x70,
+ 0x65, 0x18, 0x04, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x20, 0x2e, 0x67, 0x6f,
+ 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75,
+ 0x66, 0x2e, 0x44, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x6f, 0x72,
+ 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x52, 0x0b, 0x6d, 0x65, 0x73, 0x73, 0x61,
+ 0x67, 0x65, 0x54, 0x79, 0x70, 0x65, 0x12, 0x41, 0x0a, 0x09, 0x65, 0x6e,
+ 0x75, 0x6d, 0x5f, 0x74, 0x79, 0x70, 0x65, 0x18, 0x05, 0x20, 0x03, 0x28,
+ 0x0b, 0x32, 0x24, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70,
+ 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6e, 0x75, 0x6d,
+ 0x44, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x6f, 0x72, 0x50, 0x72,
+ 0x6f, 0x74, 0x6f, 0x52, 0x08, 0x65, 0x6e, 0x75, 0x6d, 0x54, 0x79, 0x70,
+ 0x65, 0x12, 0x41, 0x0a, 0x07, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65,
+ 0x18, 0x06, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x27, 0x2e, 0x67, 0x6f, 0x6f,
+ 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66,
+ 0x2e, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x44, 0x65, 0x73, 0x63,
+ 0x72, 0x69, 0x70, 0x74, 0x6f, 0x72, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x52,
+ 0x07, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x12, 0x43, 0x0a, 0x09,
+ 0x65, 0x78, 0x74, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x07, 0x20,
+ 0x03, 0x28, 0x0b, 0x32, 0x25, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65,
+ 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x46, 0x69,
+ 0x65, 0x6c, 0x64, 0x44, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x6f,
+ 0x72, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x52, 0x09, 0x65, 0x78, 0x74, 0x65,
+ 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x36, 0x0a, 0x07, 0x6f, 0x70, 0x74,
+ 0x69, 0x6f, 0x6e, 0x73, 0x18, 0x08, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1c,
+ 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74,
+ 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x46, 0x69, 0x6c, 0x65, 0x4f, 0x70, 0x74,
+ 0x69, 0x6f, 0x6e, 0x73, 0x52, 0x07, 0x6f, 0x70, 0x74, 0x69, 0x6f, 0x6e,
+ 0x73, 0x12, 0x49, 0x0a, 0x10, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x5f,
+ 0x63, 0x6f, 0x64, 0x65, 0x5f, 0x69, 0x6e, 0x66, 0x6f, 0x18, 0x09, 0x20,
+ 0x01, 0x28, 0x0b, 0x32, 0x1f, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65,
+ 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x53, 0x6f,
+ 0x75, 0x72, 0x63, 0x65, 0x43, 0x6f, 0x64, 0x65, 0x49, 0x6e, 0x66, 0x6f,
+ 0x52, 0x0e, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x43, 0x6f, 0x64, 0x65,
+ 0x49, 0x6e, 0x66, 0x6f, 0x12, 0x16, 0x0a, 0x06, 0x73, 0x79, 0x6e, 0x74,
+ 0x61, 0x78, 0x18, 0x0c, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x73, 0x79,
+ 0x6e, 0x74, 0x61, 0x78, 0x22, 0xb9, 0x06, 0x0a, 0x0f, 0x44, 0x65, 0x73,
+ 0x63, 0x72, 0x69, 0x70, 0x74, 0x6f, 0x72, 0x50, 0x72, 0x6f, 0x74, 0x6f,
+ 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01,
+ 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x3b, 0x0a, 0x05,
+ 0x66, 0x69, 0x65, 0x6c, 0x64, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32,
+ 0x25, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f,
+ 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x46, 0x69, 0x65, 0x6c, 0x64, 0x44,
+ 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x6f, 0x72, 0x50, 0x72, 0x6f,
+ 0x74, 0x6f, 0x52, 0x05, 0x66, 0x69, 0x65, 0x6c, 0x64, 0x12, 0x43, 0x0a,
+ 0x09, 0x65, 0x78, 0x74, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x06,
+ 0x20, 0x03, 0x28, 0x0b, 0x32, 0x25, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c,
+ 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x46,
+ 0x69, 0x65, 0x6c, 0x64, 0x44, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74,
+ 0x6f, 0x72, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x52, 0x09, 0x65, 0x78, 0x74,
+ 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x41, 0x0a, 0x0b, 0x6e, 0x65,
+ 0x73, 0x74, 0x65, 0x64, 0x5f, 0x74, 0x79, 0x70, 0x65, 0x18, 0x03, 0x20,
+ 0x03, 0x28, 0x0b, 0x32, 0x20, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65,
+ 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x44, 0x65,
+ 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x6f, 0x72, 0x50, 0x72, 0x6f, 0x74,
+ 0x6f, 0x52, 0x0a, 0x6e, 0x65, 0x73, 0x74, 0x65, 0x64, 0x54, 0x79, 0x70,
+ 0x65, 0x12, 0x41, 0x0a, 0x09, 0x65, 0x6e, 0x75, 0x6d, 0x5f, 0x74, 0x79,
+ 0x70, 0x65, 0x18, 0x04, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x24, 0x2e, 0x67,
+ 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62,
+ 0x75, 0x66, 0x2e, 0x45, 0x6e, 0x75, 0x6d, 0x44, 0x65, 0x73, 0x63, 0x72,
+ 0x69, 0x70, 0x74, 0x6f, 0x72, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x52, 0x08,
+ 0x65, 0x6e, 0x75, 0x6d, 0x54, 0x79, 0x70, 0x65, 0x12, 0x58, 0x0a, 0x0f,
+ 0x65, 0x78, 0x74, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x5f, 0x72, 0x61,
+ 0x6e, 0x67, 0x65, 0x18, 0x05, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x2f, 0x2e,
+ 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f,
+ 0x62, 0x75, 0x66, 0x2e, 0x44, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74,
+ 0x6f, 0x72, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x45, 0x78, 0x74, 0x65,
+ 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x52, 0x61, 0x6e, 0x67, 0x65, 0x52, 0x0e,
+ 0x65, 0x78, 0x74, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x52, 0x61, 0x6e,
+ 0x67, 0x65, 0x12, 0x44, 0x0a, 0x0a, 0x6f, 0x6e, 0x65, 0x6f, 0x66, 0x5f,
+ 0x64, 0x65, 0x63, 0x6c, 0x18, 0x08, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x25,
+ 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74,
+ 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x4f, 0x6e, 0x65, 0x6f, 0x66, 0x44, 0x65,
+ 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x6f, 0x72, 0x50, 0x72, 0x6f, 0x74,
+ 0x6f, 0x52, 0x09, 0x6f, 0x6e, 0x65, 0x6f, 0x66, 0x44, 0x65, 0x63, 0x6c,
+ 0x12, 0x39, 0x0a, 0x07, 0x6f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x18,
+ 0x07, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1f, 0x2e, 0x67, 0x6f, 0x6f, 0x67,
+ 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e,
+ 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x4f, 0x70, 0x74, 0x69, 0x6f,
+ 0x6e, 0x73, 0x52, 0x07, 0x6f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x12,
+ 0x55, 0x0a, 0x0e, 0x72, 0x65, 0x73, 0x65, 0x72, 0x76, 0x65, 0x64, 0x5f,
+ 0x72, 0x61, 0x6e, 0x67, 0x65, 0x18, 0x09, 0x20, 0x03, 0x28, 0x0b, 0x32,
+ 0x2e, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f,
+ 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x44, 0x65, 0x73, 0x63, 0x72, 0x69,
+ 0x70, 0x74, 0x6f, 0x72, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x52, 0x65,
+ 0x73, 0x65, 0x72, 0x76, 0x65, 0x64, 0x52, 0x61, 0x6e, 0x67, 0x65, 0x52,
+ 0x0d, 0x72, 0x65, 0x73, 0x65, 0x72, 0x76, 0x65, 0x64, 0x52, 0x61, 0x6e,
+ 0x67, 0x65, 0x12, 0x23, 0x0a, 0x0d, 0x72, 0x65, 0x73, 0x65, 0x72, 0x76,
+ 0x65, 0x64, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x0a, 0x20, 0x03, 0x28,
+ 0x09, 0x52, 0x0c, 0x72, 0x65, 0x73, 0x65, 0x72, 0x76, 0x65, 0x64, 0x4e,
+ 0x61, 0x6d, 0x65, 0x1a, 0x7a, 0x0a, 0x0e, 0x45, 0x78, 0x74, 0x65, 0x6e,
+ 0x73, 0x69, 0x6f, 0x6e, 0x52, 0x61, 0x6e, 0x67, 0x65, 0x12, 0x14, 0x0a,
+ 0x05, 0x73, 0x74, 0x61, 0x72, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x05,
+ 0x52, 0x05, 0x73, 0x74, 0x61, 0x72, 0x74, 0x12, 0x10, 0x0a, 0x03, 0x65,
+ 0x6e, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x05, 0x52, 0x03, 0x65, 0x6e,
+ 0x64, 0x12, 0x40, 0x0a, 0x07, 0x6f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73,
+ 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x26, 0x2e, 0x67, 0x6f, 0x6f,
+ 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66,
+ 0x2e, 0x45, 0x78, 0x74, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x52, 0x61,
+ 0x6e, 0x67, 0x65, 0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x52, 0x07,
+ 0x6f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x1a, 0x37, 0x0a, 0x0d, 0x52,
+ 0x65, 0x73, 0x65, 0x72, 0x76, 0x65, 0x64, 0x52, 0x61, 0x6e, 0x67, 0x65,
+ 0x12, 0x14, 0x0a, 0x05, 0x73, 0x74, 0x61, 0x72, 0x74, 0x18, 0x01, 0x20,
+ 0x01, 0x28, 0x05, 0x52, 0x05, 0x73, 0x74, 0x61, 0x72, 0x74, 0x12, 0x10,
+ 0x0a, 0x03, 0x65, 0x6e, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x05, 0x52,
+ 0x03, 0x65, 0x6e, 0x64, 0x22, 0x7c, 0x0a, 0x15, 0x45, 0x78, 0x74, 0x65,
+ 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x52, 0x61, 0x6e, 0x67, 0x65, 0x4f, 0x70,
+ 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x12, 0x58, 0x0a, 0x14, 0x75, 0x6e, 0x69,
+ 0x6e, 0x74, 0x65, 0x72, 0x70, 0x72, 0x65, 0x74, 0x65, 0x64, 0x5f, 0x6f,
+ 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0xe7, 0x07, 0x20, 0x03, 0x28, 0x0b,
+ 0x32, 0x24, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72,
+ 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x55, 0x6e, 0x69, 0x6e, 0x74,
+ 0x65, 0x72, 0x70, 0x72, 0x65, 0x74, 0x65, 0x64, 0x4f, 0x70, 0x74, 0x69,
+ 0x6f, 0x6e, 0x52, 0x13, 0x75, 0x6e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x70,
+ 0x72, 0x65, 0x74, 0x65, 0x64, 0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x2a,
+ 0x09, 0x08, 0xe8, 0x07, 0x10, 0x80, 0x80, 0x80, 0x80, 0x02, 0x22, 0x98,
+ 0x06, 0x0a, 0x14, 0x46, 0x69, 0x65, 0x6c, 0x64, 0x44, 0x65, 0x73, 0x63,
+ 0x72, 0x69, 0x70, 0x74, 0x6f, 0x72, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x12,
+ 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28,
+ 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x16, 0x0a, 0x06, 0x6e,
+ 0x75, 0x6d, 0x62, 0x65, 0x72, 0x18, 0x03, 0x20, 0x01, 0x28, 0x05, 0x52,
+ 0x06, 0x6e, 0x75, 0x6d, 0x62, 0x65, 0x72, 0x12, 0x41, 0x0a, 0x05, 0x6c,
+ 0x61, 0x62, 0x65, 0x6c, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x2b,
+ 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74,
+ 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x46, 0x69, 0x65, 0x6c, 0x64, 0x44, 0x65,
+ 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x6f, 0x72, 0x50, 0x72, 0x6f, 0x74,
+ 0x6f, 0x2e, 0x4c, 0x61, 0x62, 0x65, 0x6c, 0x52, 0x05, 0x6c, 0x61, 0x62,
+ 0x65, 0x6c, 0x12, 0x3e, 0x0a, 0x04, 0x74, 0x79, 0x70, 0x65, 0x18, 0x05,
+ 0x20, 0x01, 0x28, 0x0e, 0x32, 0x2a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c,
+ 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x46,
+ 0x69, 0x65, 0x6c, 0x64, 0x44, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74,
+ 0x6f, 0x72, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x54, 0x79, 0x70, 0x65,
+ 0x52, 0x04, 0x74, 0x79, 0x70, 0x65, 0x12, 0x1b, 0x0a, 0x09, 0x74, 0x79,
+ 0x70, 0x65, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x06, 0x20, 0x01, 0x28,
+ 0x09, 0x52, 0x08, 0x74, 0x79, 0x70, 0x65, 0x4e, 0x61, 0x6d, 0x65, 0x12,
+ 0x1a, 0x0a, 0x08, 0x65, 0x78, 0x74, 0x65, 0x6e, 0x64, 0x65, 0x65, 0x18,
+ 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x65, 0x78, 0x74, 0x65, 0x6e,
+ 0x64, 0x65, 0x65, 0x12, 0x23, 0x0a, 0x0d, 0x64, 0x65, 0x66, 0x61, 0x75,
+ 0x6c, 0x74, 0x5f, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x07, 0x20, 0x01,
+ 0x28, 0x09, 0x52, 0x0c, 0x64, 0x65, 0x66, 0x61, 0x75, 0x6c, 0x74, 0x56,
+ 0x61, 0x6c, 0x75, 0x65, 0x12, 0x1f, 0x0a, 0x0b, 0x6f, 0x6e, 0x65, 0x6f,
+ 0x66, 0x5f, 0x69, 0x6e, 0x64, 0x65, 0x78, 0x18, 0x09, 0x20, 0x01, 0x28,
+ 0x05, 0x52, 0x0a, 0x6f, 0x6e, 0x65, 0x6f, 0x66, 0x49, 0x6e, 0x64, 0x65,
+ 0x78, 0x12, 0x1b, 0x0a, 0x09, 0x6a, 0x73, 0x6f, 0x6e, 0x5f, 0x6e, 0x61,
+ 0x6d, 0x65, 0x18, 0x0a, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x6a, 0x73,
+ 0x6f, 0x6e, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x37, 0x0a, 0x07, 0x6f, 0x70,
+ 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x18, 0x08, 0x20, 0x01, 0x28, 0x0b, 0x32,
+ 0x1d, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f,
+ 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x46, 0x69, 0x65, 0x6c, 0x64, 0x4f,
+ 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x52, 0x07, 0x6f, 0x70, 0x74, 0x69,
+ 0x6f, 0x6e, 0x73, 0x22, 0xb6, 0x02, 0x0a, 0x04, 0x54, 0x79, 0x70, 0x65,
+ 0x12, 0x0f, 0x0a, 0x0b, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x44, 0x4f, 0x55,
+ 0x42, 0x4c, 0x45, 0x10, 0x01, 0x12, 0x0e, 0x0a, 0x0a, 0x54, 0x59, 0x50,
+ 0x45, 0x5f, 0x46, 0x4c, 0x4f, 0x41, 0x54, 0x10, 0x02, 0x12, 0x0e, 0x0a,
+ 0x0a, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x49, 0x4e, 0x54, 0x36, 0x34, 0x10,
+ 0x03, 0x12, 0x0f, 0x0a, 0x0b, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x55, 0x49,
+ 0x4e, 0x54, 0x36, 0x34, 0x10, 0x04, 0x12, 0x0e, 0x0a, 0x0a, 0x54, 0x59,
+ 0x50, 0x45, 0x5f, 0x49, 0x4e, 0x54, 0x33, 0x32, 0x10, 0x05, 0x12, 0x10,
+ 0x0a, 0x0c, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x46, 0x49, 0x58, 0x45, 0x44,
+ 0x36, 0x34, 0x10, 0x06, 0x12, 0x10, 0x0a, 0x0c, 0x54, 0x59, 0x50, 0x45,
+ 0x5f, 0x46, 0x49, 0x58, 0x45, 0x44, 0x33, 0x32, 0x10, 0x07, 0x12, 0x0d,
+ 0x0a, 0x09, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x42, 0x4f, 0x4f, 0x4c, 0x10,
+ 0x08, 0x12, 0x0f, 0x0a, 0x0b, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x53, 0x54,
+ 0x52, 0x49, 0x4e, 0x47, 0x10, 0x09, 0x12, 0x0e, 0x0a, 0x0a, 0x54, 0x59,
+ 0x50, 0x45, 0x5f, 0x47, 0x52, 0x4f, 0x55, 0x50, 0x10, 0x0a, 0x12, 0x10,
+ 0x0a, 0x0c, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x4d, 0x45, 0x53, 0x53, 0x41,
+ 0x47, 0x45, 0x10, 0x0b, 0x12, 0x0e, 0x0a, 0x0a, 0x54, 0x59, 0x50, 0x45,
+ 0x5f, 0x42, 0x59, 0x54, 0x45, 0x53, 0x10, 0x0c, 0x12, 0x0f, 0x0a, 0x0b,
+ 0x54, 0x59, 0x50, 0x45, 0x5f, 0x55, 0x49, 0x4e, 0x54, 0x33, 0x32, 0x10,
+ 0x0d, 0x12, 0x0d, 0x0a, 0x09, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x45, 0x4e,
+ 0x55, 0x4d, 0x10, 0x0e, 0x12, 0x11, 0x0a, 0x0d, 0x54, 0x59, 0x50, 0x45,
+ 0x5f, 0x53, 0x46, 0x49, 0x58, 0x45, 0x44, 0x33, 0x32, 0x10, 0x0f, 0x12,
+ 0x11, 0x0a, 0x0d, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x53, 0x46, 0x49, 0x58,
+ 0x45, 0x44, 0x36, 0x34, 0x10, 0x10, 0x12, 0x0f, 0x0a, 0x0b, 0x54, 0x59,
+ 0x50, 0x45, 0x5f, 0x53, 0x49, 0x4e, 0x54, 0x33, 0x32, 0x10, 0x11, 0x12,
+ 0x0f, 0x0a, 0x0b, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x53, 0x49, 0x4e, 0x54,
+ 0x36, 0x34, 0x10, 0x12, 0x22, 0x43, 0x0a, 0x05, 0x4c, 0x61, 0x62, 0x65,
+ 0x6c, 0x12, 0x12, 0x0a, 0x0e, 0x4c, 0x41, 0x42, 0x45, 0x4c, 0x5f, 0x4f,
+ 0x50, 0x54, 0x49, 0x4f, 0x4e, 0x41, 0x4c, 0x10, 0x01, 0x12, 0x12, 0x0a,
+ 0x0e, 0x4c, 0x41, 0x42, 0x45, 0x4c, 0x5f, 0x52, 0x45, 0x51, 0x55, 0x49,
+ 0x52, 0x45, 0x44, 0x10, 0x02, 0x12, 0x12, 0x0a, 0x0e, 0x4c, 0x41, 0x42,
+ 0x45, 0x4c, 0x5f, 0x52, 0x45, 0x50, 0x45, 0x41, 0x54, 0x45, 0x44, 0x10,
+ 0x03, 0x22, 0x63, 0x0a, 0x14, 0x4f, 0x6e, 0x65, 0x6f, 0x66, 0x44, 0x65,
+ 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x6f, 0x72, 0x50, 0x72, 0x6f, 0x74,
+ 0x6f, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20,
+ 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x37, 0x0a,
+ 0x07, 0x6f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x18, 0x02, 0x20, 0x01,
+ 0x28, 0x0b, 0x32, 0x1d, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e,
+ 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x4f, 0x6e, 0x65,
+ 0x6f, 0x66, 0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x52, 0x07, 0x6f,
+ 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x22, 0xe3, 0x02, 0x0a, 0x13, 0x45,
+ 0x6e, 0x75, 0x6d, 0x44, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x6f,
+ 0x72, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61,
+ 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61,
+ 0x6d, 0x65, 0x12, 0x3f, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18,
+ 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x29, 0x2e, 0x67, 0x6f, 0x6f, 0x67,
+ 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e,
+ 0x45, 0x6e, 0x75, 0x6d, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x44, 0x65, 0x73,
+ 0x63, 0x72, 0x69, 0x70, 0x74, 0x6f, 0x72, 0x50, 0x72, 0x6f, 0x74, 0x6f,
+ 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x12, 0x36, 0x0a, 0x07, 0x6f,
+ 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b,
+ 0x32, 0x1c, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72,
+ 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6e, 0x75, 0x6d, 0x4f,
+ 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x52, 0x07, 0x6f, 0x70, 0x74, 0x69,
+ 0x6f, 0x6e, 0x73, 0x12, 0x5d, 0x0a, 0x0e, 0x72, 0x65, 0x73, 0x65, 0x72,
+ 0x76, 0x65, 0x64, 0x5f, 0x72, 0x61, 0x6e, 0x67, 0x65, 0x18, 0x04, 0x20,
+ 0x03, 0x28, 0x0b, 0x32, 0x36, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65,
+ 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6e,
+ 0x75, 0x6d, 0x44, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x6f, 0x72,
+ 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x45, 0x6e, 0x75, 0x6d, 0x52, 0x65,
+ 0x73, 0x65, 0x72, 0x76, 0x65, 0x64, 0x52, 0x61, 0x6e, 0x67, 0x65, 0x52,
+ 0x0d, 0x72, 0x65, 0x73, 0x65, 0x72, 0x76, 0x65, 0x64, 0x52, 0x61, 0x6e,
+ 0x67, 0x65, 0x12, 0x23, 0x0a, 0x0d, 0x72, 0x65, 0x73, 0x65, 0x72, 0x76,
+ 0x65, 0x64, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x05, 0x20, 0x03, 0x28,
+ 0x09, 0x52, 0x0c, 0x72, 0x65, 0x73, 0x65, 0x72, 0x76, 0x65, 0x64, 0x4e,
+ 0x61, 0x6d, 0x65, 0x1a, 0x3b, 0x0a, 0x11, 0x45, 0x6e, 0x75, 0x6d, 0x52,
+ 0x65, 0x73, 0x65, 0x72, 0x76, 0x65, 0x64, 0x52, 0x61, 0x6e, 0x67, 0x65,
+ 0x12, 0x14, 0x0a, 0x05, 0x73, 0x74, 0x61, 0x72, 0x74, 0x18, 0x01, 0x20,
+ 0x01, 0x28, 0x05, 0x52, 0x05, 0x73, 0x74, 0x61, 0x72, 0x74, 0x12, 0x10,
+ 0x0a, 0x03, 0x65, 0x6e, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x05, 0x52,
+ 0x03, 0x65, 0x6e, 0x64, 0x22, 0x83, 0x01, 0x0a, 0x18, 0x45, 0x6e, 0x75,
+ 0x6d, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x44, 0x65, 0x73, 0x63, 0x72, 0x69,
+ 0x70, 0x74, 0x6f, 0x72, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x12, 0x0a,
+ 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52,
+ 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x16, 0x0a, 0x06, 0x6e, 0x75, 0x6d,
+ 0x62, 0x65, 0x72, 0x18, 0x02, 0x20, 0x01, 0x28, 0x05, 0x52, 0x06, 0x6e,
+ 0x75, 0x6d, 0x62, 0x65, 0x72, 0x12, 0x3b, 0x0a, 0x07, 0x6f, 0x70, 0x74,
+ 0x69, 0x6f, 0x6e, 0x73, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x21,
+ 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74,
+ 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6e, 0x75, 0x6d, 0x56, 0x61, 0x6c,
+ 0x75, 0x65, 0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x52, 0x07, 0x6f,
+ 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x22, 0xa7, 0x01, 0x0a, 0x16, 0x53,
+ 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x44, 0x65, 0x73, 0x63, 0x72, 0x69,
+ 0x70, 0x74, 0x6f, 0x72, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x12, 0x0a,
+ 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52,
+ 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x3e, 0x0a, 0x06, 0x6d, 0x65, 0x74,
+ 0x68, 0x6f, 0x64, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x26, 0x2e,
+ 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f,
+ 0x62, 0x75, 0x66, 0x2e, 0x4d, 0x65, 0x74, 0x68, 0x6f, 0x64, 0x44, 0x65,
+ 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x6f, 0x72, 0x50, 0x72, 0x6f, 0x74,
+ 0x6f, 0x52, 0x06, 0x6d, 0x65, 0x74, 0x68, 0x6f, 0x64, 0x12, 0x39, 0x0a,
+ 0x07, 0x6f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x18, 0x03, 0x20, 0x01,
+ 0x28, 0x0b, 0x32, 0x1f, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e,
+ 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x53, 0x65, 0x72,
+ 0x76, 0x69, 0x63, 0x65, 0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x52,
+ 0x07, 0x6f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x22, 0x89, 0x02, 0x0a,
+ 0x15, 0x4d, 0x65, 0x74, 0x68, 0x6f, 0x64, 0x44, 0x65, 0x73, 0x63, 0x72,
+ 0x69, 0x70, 0x74, 0x6f, 0x72, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x12,
+ 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09,
+ 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x1d, 0x0a, 0x0a, 0x69, 0x6e,
+ 0x70, 0x75, 0x74, 0x5f, 0x74, 0x79, 0x70, 0x65, 0x18, 0x02, 0x20, 0x01,
+ 0x28, 0x09, 0x52, 0x09, 0x69, 0x6e, 0x70, 0x75, 0x74, 0x54, 0x79, 0x70,
+ 0x65, 0x12, 0x1f, 0x0a, 0x0b, 0x6f, 0x75, 0x74, 0x70, 0x75, 0x74, 0x5f,
+ 0x74, 0x79, 0x70, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a,
+ 0x6f, 0x75, 0x74, 0x70, 0x75, 0x74, 0x54, 0x79, 0x70, 0x65, 0x12, 0x38,
+ 0x0a, 0x07, 0x6f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x18, 0x04, 0x20,
+ 0x01, 0x28, 0x0b, 0x32, 0x1e, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65,
+ 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x4d, 0x65,
+ 0x74, 0x68, 0x6f, 0x64, 0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x52,
+ 0x07, 0x6f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x12, 0x30, 0x0a, 0x10,
+ 0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x5f, 0x73, 0x74, 0x72, 0x65, 0x61,
+ 0x6d, 0x69, 0x6e, 0x67, 0x18, 0x05, 0x20, 0x01, 0x28, 0x08, 0x3a, 0x05,
+ 0x66, 0x61, 0x6c, 0x73, 0x65, 0x52, 0x0f, 0x63, 0x6c, 0x69, 0x65, 0x6e,
+ 0x74, 0x53, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x69, 0x6e, 0x67, 0x12, 0x30,
+ 0x0a, 0x10, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x5f, 0x73, 0x74, 0x72,
+ 0x65, 0x61, 0x6d, 0x69, 0x6e, 0x67, 0x18, 0x06, 0x20, 0x01, 0x28, 0x08,
+ 0x3a, 0x05, 0x66, 0x61, 0x6c, 0x73, 0x65, 0x52, 0x0f, 0x73, 0x65, 0x72,
+ 0x76, 0x65, 0x72, 0x53, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x69, 0x6e, 0x67,
+ 0x22, 0x92, 0x09, 0x0a, 0x0b, 0x46, 0x69, 0x6c, 0x65, 0x4f, 0x70, 0x74,
+ 0x69, 0x6f, 0x6e, 0x73, 0x12, 0x21, 0x0a, 0x0c, 0x6a, 0x61, 0x76, 0x61,
+ 0x5f, 0x70, 0x61, 0x63, 0x6b, 0x61, 0x67, 0x65, 0x18, 0x01, 0x20, 0x01,
+ 0x28, 0x09, 0x52, 0x0b, 0x6a, 0x61, 0x76, 0x61, 0x50, 0x61, 0x63, 0x6b,
+ 0x61, 0x67, 0x65, 0x12, 0x30, 0x0a, 0x14, 0x6a, 0x61, 0x76, 0x61, 0x5f,
+ 0x6f, 0x75, 0x74, 0x65, 0x72, 0x5f, 0x63, 0x6c, 0x61, 0x73, 0x73, 0x6e,
+ 0x61, 0x6d, 0x65, 0x18, 0x08, 0x20, 0x01, 0x28, 0x09, 0x52, 0x12, 0x6a,
+ 0x61, 0x76, 0x61, 0x4f, 0x75, 0x74, 0x65, 0x72, 0x43, 0x6c, 0x61, 0x73,
+ 0x73, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x35, 0x0a, 0x13, 0x6a, 0x61, 0x76,
+ 0x61, 0x5f, 0x6d, 0x75, 0x6c, 0x74, 0x69, 0x70, 0x6c, 0x65, 0x5f, 0x66,
+ 0x69, 0x6c, 0x65, 0x73, 0x18, 0x0a, 0x20, 0x01, 0x28, 0x08, 0x3a, 0x05,
+ 0x66, 0x61, 0x6c, 0x73, 0x65, 0x52, 0x11, 0x6a, 0x61, 0x76, 0x61, 0x4d,
+ 0x75, 0x6c, 0x74, 0x69, 0x70, 0x6c, 0x65, 0x46, 0x69, 0x6c, 0x65, 0x73,
+ 0x12, 0x44, 0x0a, 0x1d, 0x6a, 0x61, 0x76, 0x61, 0x5f, 0x67, 0x65, 0x6e,
+ 0x65, 0x72, 0x61, 0x74, 0x65, 0x5f, 0x65, 0x71, 0x75, 0x61, 0x6c, 0x73,
+ 0x5f, 0x61, 0x6e, 0x64, 0x5f, 0x68, 0x61, 0x73, 0x68, 0x18, 0x14, 0x20,
+ 0x01, 0x28, 0x08, 0x42, 0x02, 0x18, 0x01, 0x52, 0x19, 0x6a, 0x61, 0x76,
+ 0x61, 0x47, 0x65, 0x6e, 0x65, 0x72, 0x61, 0x74, 0x65, 0x45, 0x71, 0x75,
+ 0x61, 0x6c, 0x73, 0x41, 0x6e, 0x64, 0x48, 0x61, 0x73, 0x68, 0x12, 0x3a,
+ 0x0a, 0x16, 0x6a, 0x61, 0x76, 0x61, 0x5f, 0x73, 0x74, 0x72, 0x69, 0x6e,
+ 0x67, 0x5f, 0x63, 0x68, 0x65, 0x63, 0x6b, 0x5f, 0x75, 0x74, 0x66, 0x38,
+ 0x18, 0x1b, 0x20, 0x01, 0x28, 0x08, 0x3a, 0x05, 0x66, 0x61, 0x6c, 0x73,
+ 0x65, 0x52, 0x13, 0x6a, 0x61, 0x76, 0x61, 0x53, 0x74, 0x72, 0x69, 0x6e,
+ 0x67, 0x43, 0x68, 0x65, 0x63, 0x6b, 0x55, 0x74, 0x66, 0x38, 0x12, 0x53,
+ 0x0a, 0x0c, 0x6f, 0x70, 0x74, 0x69, 0x6d, 0x69, 0x7a, 0x65, 0x5f, 0x66,
+ 0x6f, 0x72, 0x18, 0x09, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x29, 0x2e, 0x67,
+ 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62,
+ 0x75, 0x66, 0x2e, 0x46, 0x69, 0x6c, 0x65, 0x4f, 0x70, 0x74, 0x69, 0x6f,
+ 0x6e, 0x73, 0x2e, 0x4f, 0x70, 0x74, 0x69, 0x6d, 0x69, 0x7a, 0x65, 0x4d,
+ 0x6f, 0x64, 0x65, 0x3a, 0x05, 0x53, 0x50, 0x45, 0x45, 0x44, 0x52, 0x0b,
+ 0x6f, 0x70, 0x74, 0x69, 0x6d, 0x69, 0x7a, 0x65, 0x46, 0x6f, 0x72, 0x12,
+ 0x1d, 0x0a, 0x0a, 0x67, 0x6f, 0x5f, 0x70, 0x61, 0x63, 0x6b, 0x61, 0x67,
+ 0x65, 0x18, 0x0b, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x67, 0x6f, 0x50,
+ 0x61, 0x63, 0x6b, 0x61, 0x67, 0x65, 0x12, 0x35, 0x0a, 0x13, 0x63, 0x63,
+ 0x5f, 0x67, 0x65, 0x6e, 0x65, 0x72, 0x69, 0x63, 0x5f, 0x73, 0x65, 0x72,
+ 0x76, 0x69, 0x63, 0x65, 0x73, 0x18, 0x10, 0x20, 0x01, 0x28, 0x08, 0x3a,
+ 0x05, 0x66, 0x61, 0x6c, 0x73, 0x65, 0x52, 0x11, 0x63, 0x63, 0x47, 0x65,
+ 0x6e, 0x65, 0x72, 0x69, 0x63, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65,
+ 0x73, 0x12, 0x39, 0x0a, 0x15, 0x6a, 0x61, 0x76, 0x61, 0x5f, 0x67, 0x65,
+ 0x6e, 0x65, 0x72, 0x69, 0x63, 0x5f, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63,
+ 0x65, 0x73, 0x18, 0x11, 0x20, 0x01, 0x28, 0x08, 0x3a, 0x05, 0x66, 0x61,
+ 0x6c, 0x73, 0x65, 0x52, 0x13, 0x6a, 0x61, 0x76, 0x61, 0x47, 0x65, 0x6e,
+ 0x65, 0x72, 0x69, 0x63, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73,
+ 0x12, 0x35, 0x0a, 0x13, 0x70, 0x79, 0x5f, 0x67, 0x65, 0x6e, 0x65, 0x72,
+ 0x69, 0x63, 0x5f, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x18,
+ 0x12, 0x20, 0x01, 0x28, 0x08, 0x3a, 0x05, 0x66, 0x61, 0x6c, 0x73, 0x65,
+ 0x52, 0x11, 0x70, 0x79, 0x47, 0x65, 0x6e, 0x65, 0x72, 0x69, 0x63, 0x53,
+ 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x12, 0x37, 0x0a, 0x14, 0x70,
+ 0x68, 0x70, 0x5f, 0x67, 0x65, 0x6e, 0x65, 0x72, 0x69, 0x63, 0x5f, 0x73,
+ 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x18, 0x2a, 0x20, 0x01, 0x28,
+ 0x08, 0x3a, 0x05, 0x66, 0x61, 0x6c, 0x73, 0x65, 0x52, 0x12, 0x70, 0x68,
+ 0x70, 0x47, 0x65, 0x6e, 0x65, 0x72, 0x69, 0x63, 0x53, 0x65, 0x72, 0x76,
+ 0x69, 0x63, 0x65, 0x73, 0x12, 0x25, 0x0a, 0x0a, 0x64, 0x65, 0x70, 0x72,
+ 0x65, 0x63, 0x61, 0x74, 0x65, 0x64, 0x18, 0x17, 0x20, 0x01, 0x28, 0x08,
+ 0x3a, 0x05, 0x66, 0x61, 0x6c, 0x73, 0x65, 0x52, 0x0a, 0x64, 0x65, 0x70,
+ 0x72, 0x65, 0x63, 0x61, 0x74, 0x65, 0x64, 0x12, 0x2f, 0x0a, 0x10, 0x63,
+ 0x63, 0x5f, 0x65, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x5f, 0x61, 0x72, 0x65,
+ 0x6e, 0x61, 0x73, 0x18, 0x1f, 0x20, 0x01, 0x28, 0x08, 0x3a, 0x05, 0x66,
+ 0x61, 0x6c, 0x73, 0x65, 0x52, 0x0e, 0x63, 0x63, 0x45, 0x6e, 0x61, 0x62,
+ 0x6c, 0x65, 0x41, 0x72, 0x65, 0x6e, 0x61, 0x73, 0x12, 0x2a, 0x0a, 0x11,
+ 0x6f, 0x62, 0x6a, 0x63, 0x5f, 0x63, 0x6c, 0x61, 0x73, 0x73, 0x5f, 0x70,
+ 0x72, 0x65, 0x66, 0x69, 0x78, 0x18, 0x24, 0x20, 0x01, 0x28, 0x09, 0x52,
+ 0x0f, 0x6f, 0x62, 0x6a, 0x63, 0x43, 0x6c, 0x61, 0x73, 0x73, 0x50, 0x72,
+ 0x65, 0x66, 0x69, 0x78, 0x12, 0x29, 0x0a, 0x10, 0x63, 0x73, 0x68, 0x61,
+ 0x72, 0x70, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65,
+ 0x18, 0x25, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0f, 0x63, 0x73, 0x68, 0x61,
+ 0x72, 0x70, 0x4e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x12,
+ 0x21, 0x0a, 0x0c, 0x73, 0x77, 0x69, 0x66, 0x74, 0x5f, 0x70, 0x72, 0x65,
+ 0x66, 0x69, 0x78, 0x18, 0x27, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x73,
+ 0x77, 0x69, 0x66, 0x74, 0x50, 0x72, 0x65, 0x66, 0x69, 0x78, 0x12, 0x28,
+ 0x0a, 0x10, 0x70, 0x68, 0x70, 0x5f, 0x63, 0x6c, 0x61, 0x73, 0x73, 0x5f,
+ 0x70, 0x72, 0x65, 0x66, 0x69, 0x78, 0x18, 0x28, 0x20, 0x01, 0x28, 0x09,
+ 0x52, 0x0e, 0x70, 0x68, 0x70, 0x43, 0x6c, 0x61, 0x73, 0x73, 0x50, 0x72,
+ 0x65, 0x66, 0x69, 0x78, 0x12, 0x23, 0x0a, 0x0d, 0x70, 0x68, 0x70, 0x5f,
+ 0x6e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x18, 0x29, 0x20,
+ 0x01, 0x28, 0x09, 0x52, 0x0c, 0x70, 0x68, 0x70, 0x4e, 0x61, 0x6d, 0x65,
+ 0x73, 0x70, 0x61, 0x63, 0x65, 0x12, 0x34, 0x0a, 0x16, 0x70, 0x68, 0x70,
+ 0x5f, 0x6d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x5f, 0x6e, 0x61,
+ 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x18, 0x2c, 0x20, 0x01, 0x28,
+ 0x09, 0x52, 0x14, 0x70, 0x68, 0x70, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61,
+ 0x74, 0x61, 0x4e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x12,
+ 0x21, 0x0a, 0x0c, 0x72, 0x75, 0x62, 0x79, 0x5f, 0x70, 0x61, 0x63, 0x6b,
+ 0x61, 0x67, 0x65, 0x18, 0x2d, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x72,
+ 0x75, 0x62, 0x79, 0x50, 0x61, 0x63, 0x6b, 0x61, 0x67, 0x65, 0x12, 0x58,
+ 0x0a, 0x14, 0x75, 0x6e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x70, 0x72, 0x65,
+ 0x74, 0x65, 0x64, 0x5f, 0x6f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0xe7,
+ 0x07, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x24, 0x2e, 0x67, 0x6f, 0x6f, 0x67,
+ 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e,
+ 0x55, 0x6e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x70, 0x72, 0x65, 0x74, 0x65,
+ 0x64, 0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x13, 0x75, 0x6e, 0x69,
+ 0x6e, 0x74, 0x65, 0x72, 0x70, 0x72, 0x65, 0x74, 0x65, 0x64, 0x4f, 0x70,
+ 0x74, 0x69, 0x6f, 0x6e, 0x22, 0x3a, 0x0a, 0x0c, 0x4f, 0x70, 0x74, 0x69,
+ 0x6d, 0x69, 0x7a, 0x65, 0x4d, 0x6f, 0x64, 0x65, 0x12, 0x09, 0x0a, 0x05,
+ 0x53, 0x50, 0x45, 0x45, 0x44, 0x10, 0x01, 0x12, 0x0d, 0x0a, 0x09, 0x43,
+ 0x4f, 0x44, 0x45, 0x5f, 0x53, 0x49, 0x5a, 0x45, 0x10, 0x02, 0x12, 0x10,
+ 0x0a, 0x0c, 0x4c, 0x49, 0x54, 0x45, 0x5f, 0x52, 0x55, 0x4e, 0x54, 0x49,
+ 0x4d, 0x45, 0x10, 0x03, 0x2a, 0x09, 0x08, 0xe8, 0x07, 0x10, 0x80, 0x80,
+ 0x80, 0x80, 0x02, 0x4a, 0x04, 0x08, 0x26, 0x10, 0x27, 0x22, 0xd1, 0x02,
+ 0x0a, 0x0e, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x4f, 0x70, 0x74,
+ 0x69, 0x6f, 0x6e, 0x73, 0x12, 0x3c, 0x0a, 0x17, 0x6d, 0x65, 0x73, 0x73,
+ 0x61, 0x67, 0x65, 0x5f, 0x73, 0x65, 0x74, 0x5f, 0x77, 0x69, 0x72, 0x65,
+ 0x5f, 0x66, 0x6f, 0x72, 0x6d, 0x61, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28,
+ 0x08, 0x3a, 0x05, 0x66, 0x61, 0x6c, 0x73, 0x65, 0x52, 0x14, 0x6d, 0x65,
+ 0x73, 0x73, 0x61, 0x67, 0x65, 0x53, 0x65, 0x74, 0x57, 0x69, 0x72, 0x65,
+ 0x46, 0x6f, 0x72, 0x6d, 0x61, 0x74, 0x12, 0x4c, 0x0a, 0x1f, 0x6e, 0x6f,
+ 0x5f, 0x73, 0x74, 0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, 0x5f, 0x64, 0x65,
+ 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x6f, 0x72, 0x5f, 0x61, 0x63, 0x63,
+ 0x65, 0x73, 0x73, 0x6f, 0x72, 0x18, 0x02, 0x20, 0x01, 0x28, 0x08, 0x3a,
+ 0x05, 0x66, 0x61, 0x6c, 0x73, 0x65, 0x52, 0x1c, 0x6e, 0x6f, 0x53, 0x74,
+ 0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, 0x44, 0x65, 0x73, 0x63, 0x72, 0x69,
+ 0x70, 0x74, 0x6f, 0x72, 0x41, 0x63, 0x63, 0x65, 0x73, 0x73, 0x6f, 0x72,
+ 0x12, 0x25, 0x0a, 0x0a, 0x64, 0x65, 0x70, 0x72, 0x65, 0x63, 0x61, 0x74,
+ 0x65, 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, 0x08, 0x3a, 0x05, 0x66, 0x61,
+ 0x6c, 0x73, 0x65, 0x52, 0x0a, 0x64, 0x65, 0x70, 0x72, 0x65, 0x63, 0x61,
+ 0x74, 0x65, 0x64, 0x12, 0x1b, 0x0a, 0x09, 0x6d, 0x61, 0x70, 0x5f, 0x65,
+ 0x6e, 0x74, 0x72, 0x79, 0x18, 0x07, 0x20, 0x01, 0x28, 0x08, 0x52, 0x08,
+ 0x6d, 0x61, 0x70, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x58, 0x0a, 0x14,
+ 0x75, 0x6e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x70, 0x72, 0x65, 0x74, 0x65,
+ 0x64, 0x5f, 0x6f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0xe7, 0x07, 0x20,
+ 0x03, 0x28, 0x0b, 0x32, 0x24, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65,
+ 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x55, 0x6e,
+ 0x69, 0x6e, 0x74, 0x65, 0x72, 0x70, 0x72, 0x65, 0x74, 0x65, 0x64, 0x4f,
+ 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x13, 0x75, 0x6e, 0x69, 0x6e, 0x74,
+ 0x65, 0x72, 0x70, 0x72, 0x65, 0x74, 0x65, 0x64, 0x4f, 0x70, 0x74, 0x69,
+ 0x6f, 0x6e, 0x2a, 0x09, 0x08, 0xe8, 0x07, 0x10, 0x80, 0x80, 0x80, 0x80,
+ 0x02, 0x4a, 0x04, 0x08, 0x08, 0x10, 0x09, 0x4a, 0x04, 0x08, 0x09, 0x10,
+ 0x0a, 0x22, 0xe2, 0x03, 0x0a, 0x0c, 0x46, 0x69, 0x65, 0x6c, 0x64, 0x4f,
+ 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x12, 0x41, 0x0a, 0x05, 0x63, 0x74,
+ 0x79, 0x70, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x23, 0x2e,
+ 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f,
+ 0x62, 0x75, 0x66, 0x2e, 0x46, 0x69, 0x65, 0x6c, 0x64, 0x4f, 0x70, 0x74,
+ 0x69, 0x6f, 0x6e, 0x73, 0x2e, 0x43, 0x54, 0x79, 0x70, 0x65, 0x3a, 0x06,
+ 0x53, 0x54, 0x52, 0x49, 0x4e, 0x47, 0x52, 0x05, 0x63, 0x74, 0x79, 0x70,
+ 0x65, 0x12, 0x16, 0x0a, 0x06, 0x70, 0x61, 0x63, 0x6b, 0x65, 0x64, 0x18,
+ 0x02, 0x20, 0x01, 0x28, 0x08, 0x52, 0x06, 0x70, 0x61, 0x63, 0x6b, 0x65,
+ 0x64, 0x12, 0x47, 0x0a, 0x06, 0x6a, 0x73, 0x74, 0x79, 0x70, 0x65, 0x18,
+ 0x06, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x24, 0x2e, 0x67, 0x6f, 0x6f, 0x67,
+ 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e,
+ 0x46, 0x69, 0x65, 0x6c, 0x64, 0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73,
+ 0x2e, 0x4a, 0x53, 0x54, 0x79, 0x70, 0x65, 0x3a, 0x09, 0x4a, 0x53, 0x5f,
+ 0x4e, 0x4f, 0x52, 0x4d, 0x41, 0x4c, 0x52, 0x06, 0x6a, 0x73, 0x74, 0x79,
+ 0x70, 0x65, 0x12, 0x19, 0x0a, 0x04, 0x6c, 0x61, 0x7a, 0x79, 0x18, 0x05,
+ 0x20, 0x01, 0x28, 0x08, 0x3a, 0x05, 0x66, 0x61, 0x6c, 0x73, 0x65, 0x52,
+ 0x04, 0x6c, 0x61, 0x7a, 0x79, 0x12, 0x25, 0x0a, 0x0a, 0x64, 0x65, 0x70,
+ 0x72, 0x65, 0x63, 0x61, 0x74, 0x65, 0x64, 0x18, 0x03, 0x20, 0x01, 0x28,
+ 0x08, 0x3a, 0x05, 0x66, 0x61, 0x6c, 0x73, 0x65, 0x52, 0x0a, 0x64, 0x65,
+ 0x70, 0x72, 0x65, 0x63, 0x61, 0x74, 0x65, 0x64, 0x12, 0x19, 0x0a, 0x04,
+ 0x77, 0x65, 0x61, 0x6b, 0x18, 0x0a, 0x20, 0x01, 0x28, 0x08, 0x3a, 0x05,
+ 0x66, 0x61, 0x6c, 0x73, 0x65, 0x52, 0x04, 0x77, 0x65, 0x61, 0x6b, 0x12,
+ 0x58, 0x0a, 0x14, 0x75, 0x6e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x70, 0x72,
+ 0x65, 0x74, 0x65, 0x64, 0x5f, 0x6f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x18,
+ 0xe7, 0x07, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x24, 0x2e, 0x67, 0x6f, 0x6f,
+ 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66,
+ 0x2e, 0x55, 0x6e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x70, 0x72, 0x65, 0x74,
+ 0x65, 0x64, 0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x13, 0x75, 0x6e,
+ 0x69, 0x6e, 0x74, 0x65, 0x72, 0x70, 0x72, 0x65, 0x74, 0x65, 0x64, 0x4f,
+ 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x22, 0x2f, 0x0a, 0x05, 0x43, 0x54, 0x79,
+ 0x70, 0x65, 0x12, 0x0a, 0x0a, 0x06, 0x53, 0x54, 0x52, 0x49, 0x4e, 0x47,
+ 0x10, 0x00, 0x12, 0x08, 0x0a, 0x04, 0x43, 0x4f, 0x52, 0x44, 0x10, 0x01,
+ 0x12, 0x10, 0x0a, 0x0c, 0x53, 0x54, 0x52, 0x49, 0x4e, 0x47, 0x5f, 0x50,
+ 0x49, 0x45, 0x43, 0x45, 0x10, 0x02, 0x22, 0x35, 0x0a, 0x06, 0x4a, 0x53,
+ 0x54, 0x79, 0x70, 0x65, 0x12, 0x0d, 0x0a, 0x09, 0x4a, 0x53, 0x5f, 0x4e,
+ 0x4f, 0x52, 0x4d, 0x41, 0x4c, 0x10, 0x00, 0x12, 0x0d, 0x0a, 0x09, 0x4a,
+ 0x53, 0x5f, 0x53, 0x54, 0x52, 0x49, 0x4e, 0x47, 0x10, 0x01, 0x12, 0x0d,
+ 0x0a, 0x09, 0x4a, 0x53, 0x5f, 0x4e, 0x55, 0x4d, 0x42, 0x45, 0x52, 0x10,
+ 0x02, 0x2a, 0x09, 0x08, 0xe8, 0x07, 0x10, 0x80, 0x80, 0x80, 0x80, 0x02,
+ 0x4a, 0x04, 0x08, 0x04, 0x10, 0x05, 0x22, 0x73, 0x0a, 0x0c, 0x4f, 0x6e,
+ 0x65, 0x6f, 0x66, 0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x12, 0x58,
+ 0x0a, 0x14, 0x75, 0x6e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x70, 0x72, 0x65,
+ 0x74, 0x65, 0x64, 0x5f, 0x6f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0xe7,
+ 0x07, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x24, 0x2e, 0x67, 0x6f, 0x6f, 0x67,
+ 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e,
+ 0x55, 0x6e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x70, 0x72, 0x65, 0x74, 0x65,
+ 0x64, 0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x13, 0x75, 0x6e, 0x69,
+ 0x6e, 0x74, 0x65, 0x72, 0x70, 0x72, 0x65, 0x74, 0x65, 0x64, 0x4f, 0x70,
+ 0x74, 0x69, 0x6f, 0x6e, 0x2a, 0x09, 0x08, 0xe8, 0x07, 0x10, 0x80, 0x80,
+ 0x80, 0x80, 0x02, 0x22, 0xc0, 0x01, 0x0a, 0x0b, 0x45, 0x6e, 0x75, 0x6d,
+ 0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x12, 0x1f, 0x0a, 0x0b, 0x61,
+ 0x6c, 0x6c, 0x6f, 0x77, 0x5f, 0x61, 0x6c, 0x69, 0x61, 0x73, 0x18, 0x02,
+ 0x20, 0x01, 0x28, 0x08, 0x52, 0x0a, 0x61, 0x6c, 0x6c, 0x6f, 0x77, 0x41,
+ 0x6c, 0x69, 0x61, 0x73, 0x12, 0x25, 0x0a, 0x0a, 0x64, 0x65, 0x70, 0x72,
+ 0x65, 0x63, 0x61, 0x74, 0x65, 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, 0x08,
+ 0x3a, 0x05, 0x66, 0x61, 0x6c, 0x73, 0x65, 0x52, 0x0a, 0x64, 0x65, 0x70,
+ 0x72, 0x65, 0x63, 0x61, 0x74, 0x65, 0x64, 0x12, 0x58, 0x0a, 0x14, 0x75,
+ 0x6e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x70, 0x72, 0x65, 0x74, 0x65, 0x64,
+ 0x5f, 0x6f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0xe7, 0x07, 0x20, 0x03,
+ 0x28, 0x0b, 0x32, 0x24, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e,
+ 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x55, 0x6e, 0x69,
+ 0x6e, 0x74, 0x65, 0x72, 0x70, 0x72, 0x65, 0x74, 0x65, 0x64, 0x4f, 0x70,
+ 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x13, 0x75, 0x6e, 0x69, 0x6e, 0x74, 0x65,
+ 0x72, 0x70, 0x72, 0x65, 0x74, 0x65, 0x64, 0x4f, 0x70, 0x74, 0x69, 0x6f,
+ 0x6e, 0x2a, 0x09, 0x08, 0xe8, 0x07, 0x10, 0x80, 0x80, 0x80, 0x80, 0x02,
+ 0x4a, 0x04, 0x08, 0x05, 0x10, 0x06, 0x22, 0x9e, 0x01, 0x0a, 0x10, 0x45,
+ 0x6e, 0x75, 0x6d, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x4f, 0x70, 0x74, 0x69,
+ 0x6f, 0x6e, 0x73, 0x12, 0x25, 0x0a, 0x0a, 0x64, 0x65, 0x70, 0x72, 0x65,
+ 0x63, 0x61, 0x74, 0x65, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x08, 0x3a,
+ 0x05, 0x66, 0x61, 0x6c, 0x73, 0x65, 0x52, 0x0a, 0x64, 0x65, 0x70, 0x72,
+ 0x65, 0x63, 0x61, 0x74, 0x65, 0x64, 0x12, 0x58, 0x0a, 0x14, 0x75, 0x6e,
+ 0x69, 0x6e, 0x74, 0x65, 0x72, 0x70, 0x72, 0x65, 0x74, 0x65, 0x64, 0x5f,
+ 0x6f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0xe7, 0x07, 0x20, 0x03, 0x28,
+ 0x0b, 0x32, 0x24, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70,
+ 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x55, 0x6e, 0x69, 0x6e,
+ 0x74, 0x65, 0x72, 0x70, 0x72, 0x65, 0x74, 0x65, 0x64, 0x4f, 0x70, 0x74,
+ 0x69, 0x6f, 0x6e, 0x52, 0x13, 0x75, 0x6e, 0x69, 0x6e, 0x74, 0x65, 0x72,
+ 0x70, 0x72, 0x65, 0x74, 0x65, 0x64, 0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e,
+ 0x2a, 0x09, 0x08, 0xe8, 0x07, 0x10, 0x80, 0x80, 0x80, 0x80, 0x02, 0x22,
+ 0x9c, 0x01, 0x0a, 0x0e, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x4f,
+ 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x12, 0x25, 0x0a, 0x0a, 0x64, 0x65,
+ 0x70, 0x72, 0x65, 0x63, 0x61, 0x74, 0x65, 0x64, 0x18, 0x21, 0x20, 0x01,
+ 0x28, 0x08, 0x3a, 0x05, 0x66, 0x61, 0x6c, 0x73, 0x65, 0x52, 0x0a, 0x64,
+ 0x65, 0x70, 0x72, 0x65, 0x63, 0x61, 0x74, 0x65, 0x64, 0x12, 0x58, 0x0a,
+ 0x14, 0x75, 0x6e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x70, 0x72, 0x65, 0x74,
+ 0x65, 0x64, 0x5f, 0x6f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0xe7, 0x07,
+ 0x20, 0x03, 0x28, 0x0b, 0x32, 0x24, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c,
+ 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x55,
+ 0x6e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x70, 0x72, 0x65, 0x74, 0x65, 0x64,
+ 0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x13, 0x75, 0x6e, 0x69, 0x6e,
+ 0x74, 0x65, 0x72, 0x70, 0x72, 0x65, 0x74, 0x65, 0x64, 0x4f, 0x70, 0x74,
+ 0x69, 0x6f, 0x6e, 0x2a, 0x09, 0x08, 0xe8, 0x07, 0x10, 0x80, 0x80, 0x80,
+ 0x80, 0x02, 0x22, 0xe0, 0x02, 0x0a, 0x0d, 0x4d, 0x65, 0x74, 0x68, 0x6f,
+ 0x64, 0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x12, 0x25, 0x0a, 0x0a,
+ 0x64, 0x65, 0x70, 0x72, 0x65, 0x63, 0x61, 0x74, 0x65, 0x64, 0x18, 0x21,
+ 0x20, 0x01, 0x28, 0x08, 0x3a, 0x05, 0x66, 0x61, 0x6c, 0x73, 0x65, 0x52,
+ 0x0a, 0x64, 0x65, 0x70, 0x72, 0x65, 0x63, 0x61, 0x74, 0x65, 0x64, 0x12,
+ 0x71, 0x0a, 0x11, 0x69, 0x64, 0x65, 0x6d, 0x70, 0x6f, 0x74, 0x65, 0x6e,
+ 0x63, 0x79, 0x5f, 0x6c, 0x65, 0x76, 0x65, 0x6c, 0x18, 0x22, 0x20, 0x01,
+ 0x28, 0x0e, 0x32, 0x2f, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e,
+ 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x4d, 0x65, 0x74,
+ 0x68, 0x6f, 0x64, 0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x2e, 0x49,
+ 0x64, 0x65, 0x6d, 0x70, 0x6f, 0x74, 0x65, 0x6e, 0x63, 0x79, 0x4c, 0x65,
+ 0x76, 0x65, 0x6c, 0x3a, 0x13, 0x49, 0x44, 0x45, 0x4d, 0x50, 0x4f, 0x54,
+ 0x45, 0x4e, 0x43, 0x59, 0x5f, 0x55, 0x4e, 0x4b, 0x4e, 0x4f, 0x57, 0x4e,
+ 0x52, 0x10, 0x69, 0x64, 0x65, 0x6d, 0x70, 0x6f, 0x74, 0x65, 0x6e, 0x63,
+ 0x79, 0x4c, 0x65, 0x76, 0x65, 0x6c, 0x12, 0x58, 0x0a, 0x14, 0x75, 0x6e,
+ 0x69, 0x6e, 0x74, 0x65, 0x72, 0x70, 0x72, 0x65, 0x74, 0x65, 0x64, 0x5f,
+ 0x6f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0xe7, 0x07, 0x20, 0x03, 0x28,
+ 0x0b, 0x32, 0x24, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70,
+ 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x55, 0x6e, 0x69, 0x6e,
+ 0x74, 0x65, 0x72, 0x70, 0x72, 0x65, 0x74, 0x65, 0x64, 0x4f, 0x70, 0x74,
+ 0x69, 0x6f, 0x6e, 0x52, 0x13, 0x75, 0x6e, 0x69, 0x6e, 0x74, 0x65, 0x72,
+ 0x70, 0x72, 0x65, 0x74, 0x65, 0x64, 0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e,
+ 0x22, 0x50, 0x0a, 0x10, 0x49, 0x64, 0x65, 0x6d, 0x70, 0x6f, 0x74, 0x65,
+ 0x6e, 0x63, 0x79, 0x4c, 0x65, 0x76, 0x65, 0x6c, 0x12, 0x17, 0x0a, 0x13,
+ 0x49, 0x44, 0x45, 0x4d, 0x50, 0x4f, 0x54, 0x45, 0x4e, 0x43, 0x59, 0x5f,
+ 0x55, 0x4e, 0x4b, 0x4e, 0x4f, 0x57, 0x4e, 0x10, 0x00, 0x12, 0x13, 0x0a,
+ 0x0f, 0x4e, 0x4f, 0x5f, 0x53, 0x49, 0x44, 0x45, 0x5f, 0x45, 0x46, 0x46,
+ 0x45, 0x43, 0x54, 0x53, 0x10, 0x01, 0x12, 0x0e, 0x0a, 0x0a, 0x49, 0x44,
+ 0x45, 0x4d, 0x50, 0x4f, 0x54, 0x45, 0x4e, 0x54, 0x10, 0x02, 0x2a, 0x09,
+ 0x08, 0xe8, 0x07, 0x10, 0x80, 0x80, 0x80, 0x80, 0x02, 0x22, 0x9a, 0x03,
+ 0x0a, 0x13, 0x55, 0x6e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x70, 0x72, 0x65,
+ 0x74, 0x65, 0x64, 0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x41, 0x0a,
+ 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32,
+ 0x2d, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f,
+ 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x55, 0x6e, 0x69, 0x6e, 0x74, 0x65,
+ 0x72, 0x70, 0x72, 0x65, 0x74, 0x65, 0x64, 0x4f, 0x70, 0x74, 0x69, 0x6f,
+ 0x6e, 0x2e, 0x4e, 0x61, 0x6d, 0x65, 0x50, 0x61, 0x72, 0x74, 0x52, 0x04,
+ 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x29, 0x0a, 0x10, 0x69, 0x64, 0x65, 0x6e,
+ 0x74, 0x69, 0x66, 0x69, 0x65, 0x72, 0x5f, 0x76, 0x61, 0x6c, 0x75, 0x65,
+ 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0f, 0x69, 0x64, 0x65, 0x6e,
+ 0x74, 0x69, 0x66, 0x69, 0x65, 0x72, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x12,
+ 0x2c, 0x0a, 0x12, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x69, 0x76, 0x65, 0x5f,
+ 0x69, 0x6e, 0x74, 0x5f, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x04, 0x20,
+ 0x01, 0x28, 0x04, 0x52, 0x10, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x69, 0x76,
+ 0x65, 0x49, 0x6e, 0x74, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x12, 0x2c, 0x0a,
+ 0x12, 0x6e, 0x65, 0x67, 0x61, 0x74, 0x69, 0x76, 0x65, 0x5f, 0x69, 0x6e,
+ 0x74, 0x5f, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x05, 0x20, 0x01, 0x28,
+ 0x03, 0x52, 0x10, 0x6e, 0x65, 0x67, 0x61, 0x74, 0x69, 0x76, 0x65, 0x49,
+ 0x6e, 0x74, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x12, 0x21, 0x0a, 0x0c, 0x64,
+ 0x6f, 0x75, 0x62, 0x6c, 0x65, 0x5f, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18,
+ 0x06, 0x20, 0x01, 0x28, 0x01, 0x52, 0x0b, 0x64, 0x6f, 0x75, 0x62, 0x6c,
+ 0x65, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x12, 0x21, 0x0a, 0x0c, 0x73, 0x74,
+ 0x72, 0x69, 0x6e, 0x67, 0x5f, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x07,
+ 0x20, 0x01, 0x28, 0x0c, 0x52, 0x0b, 0x73, 0x74, 0x72, 0x69, 0x6e, 0x67,
+ 0x56, 0x61, 0x6c, 0x75, 0x65, 0x12, 0x27, 0x0a, 0x0f, 0x61, 0x67, 0x67,
+ 0x72, 0x65, 0x67, 0x61, 0x74, 0x65, 0x5f, 0x76, 0x61, 0x6c, 0x75, 0x65,
+ 0x18, 0x08, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0e, 0x61, 0x67, 0x67, 0x72,
+ 0x65, 0x67, 0x61, 0x74, 0x65, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x1a, 0x4a,
+ 0x0a, 0x08, 0x4e, 0x61, 0x6d, 0x65, 0x50, 0x61, 0x72, 0x74, 0x12, 0x1b,
+ 0x0a, 0x09, 0x6e, 0x61, 0x6d, 0x65, 0x5f, 0x70, 0x61, 0x72, 0x74, 0x18,
+ 0x01, 0x20, 0x02, 0x28, 0x09, 0x52, 0x08, 0x6e, 0x61, 0x6d, 0x65, 0x50,
+ 0x61, 0x72, 0x74, 0x12, 0x21, 0x0a, 0x0c, 0x69, 0x73, 0x5f, 0x65, 0x78,
+ 0x74, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x02, 0x20, 0x02, 0x28,
+ 0x08, 0x52, 0x0b, 0x69, 0x73, 0x45, 0x78, 0x74, 0x65, 0x6e, 0x73, 0x69,
+ 0x6f, 0x6e, 0x22, 0xa7, 0x02, 0x0a, 0x0e, 0x53, 0x6f, 0x75, 0x72, 0x63,
+ 0x65, 0x43, 0x6f, 0x64, 0x65, 0x49, 0x6e, 0x66, 0x6f, 0x12, 0x44, 0x0a,
+ 0x08, 0x6c, 0x6f, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x01, 0x20,
+ 0x03, 0x28, 0x0b, 0x32, 0x28, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65,
+ 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x53, 0x6f,
+ 0x75, 0x72, 0x63, 0x65, 0x43, 0x6f, 0x64, 0x65, 0x49, 0x6e, 0x66, 0x6f,
+ 0x2e, 0x4c, 0x6f, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x08, 0x6c,
+ 0x6f, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x1a, 0xce, 0x01, 0x0a, 0x08,
+ 0x4c, 0x6f, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x16, 0x0a, 0x04,
+ 0x70, 0x61, 0x74, 0x68, 0x18, 0x01, 0x20, 0x03, 0x28, 0x05, 0x42, 0x02,
+ 0x10, 0x01, 0x52, 0x04, 0x70, 0x61, 0x74, 0x68, 0x12, 0x16, 0x0a, 0x04,
+ 0x73, 0x70, 0x61, 0x6e, 0x18, 0x02, 0x20, 0x03, 0x28, 0x05, 0x42, 0x02,
+ 0x10, 0x01, 0x52, 0x04, 0x73, 0x70, 0x61, 0x6e, 0x12, 0x29, 0x0a, 0x10,
+ 0x6c, 0x65, 0x61, 0x64, 0x69, 0x6e, 0x67, 0x5f, 0x63, 0x6f, 0x6d, 0x6d,
+ 0x65, 0x6e, 0x74, 0x73, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0f,
+ 0x6c, 0x65, 0x61, 0x64, 0x69, 0x6e, 0x67, 0x43, 0x6f, 0x6d, 0x6d, 0x65,
+ 0x6e, 0x74, 0x73, 0x12, 0x2b, 0x0a, 0x11, 0x74, 0x72, 0x61, 0x69, 0x6c,
+ 0x69, 0x6e, 0x67, 0x5f, 0x63, 0x6f, 0x6d, 0x6d, 0x65, 0x6e, 0x74, 0x73,
+ 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x10, 0x74, 0x72, 0x61, 0x69,
+ 0x6c, 0x69, 0x6e, 0x67, 0x43, 0x6f, 0x6d, 0x6d, 0x65, 0x6e, 0x74, 0x73,
+ 0x12, 0x3a, 0x0a, 0x19, 0x6c, 0x65, 0x61, 0x64, 0x69, 0x6e, 0x67, 0x5f,
+ 0x64, 0x65, 0x74, 0x61, 0x63, 0x68, 0x65, 0x64, 0x5f, 0x63, 0x6f, 0x6d,
+ 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x18, 0x06, 0x20, 0x03, 0x28, 0x09, 0x52,
+ 0x17, 0x6c, 0x65, 0x61, 0x64, 0x69, 0x6e, 0x67, 0x44, 0x65, 0x74, 0x61,
+ 0x63, 0x68, 0x65, 0x64, 0x43, 0x6f, 0x6d, 0x6d, 0x65, 0x6e, 0x74, 0x73,
+ 0x22, 0xd1, 0x01, 0x0a, 0x11, 0x47, 0x65, 0x6e, 0x65, 0x72, 0x61, 0x74,
+ 0x65, 0x64, 0x43, 0x6f, 0x64, 0x65, 0x49, 0x6e, 0x66, 0x6f, 0x12, 0x4d,
+ 0x0a, 0x0a, 0x61, 0x6e, 0x6e, 0x6f, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e,
+ 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x2d, 0x2e, 0x67, 0x6f, 0x6f,
+ 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66,
+ 0x2e, 0x47, 0x65, 0x6e, 0x65, 0x72, 0x61, 0x74, 0x65, 0x64, 0x43, 0x6f,
+ 0x64, 0x65, 0x49, 0x6e, 0x66, 0x6f, 0x2e, 0x41, 0x6e, 0x6e, 0x6f, 0x74,
+ 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x0a, 0x61, 0x6e, 0x6e, 0x6f, 0x74,
+ 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x1a, 0x6d, 0x0a, 0x0a, 0x41, 0x6e, 0x6e,
+ 0x6f, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x16, 0x0a, 0x04, 0x70,
+ 0x61, 0x74, 0x68, 0x18, 0x01, 0x20, 0x03, 0x28, 0x05, 0x42, 0x02, 0x10,
+ 0x01, 0x52, 0x04, 0x70, 0x61, 0x74, 0x68, 0x12, 0x1f, 0x0a, 0x0b, 0x73,
+ 0x6f, 0x75, 0x72, 0x63, 0x65, 0x5f, 0x66, 0x69, 0x6c, 0x65, 0x18, 0x02,
+ 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65,
+ 0x46, 0x69, 0x6c, 0x65, 0x12, 0x14, 0x0a, 0x05, 0x62, 0x65, 0x67, 0x69,
+ 0x6e, 0x18, 0x03, 0x20, 0x01, 0x28, 0x05, 0x52, 0x05, 0x62, 0x65, 0x67,
+ 0x69, 0x6e, 0x12, 0x10, 0x0a, 0x03, 0x65, 0x6e, 0x64, 0x18, 0x04, 0x20,
+ 0x01, 0x28, 0x05, 0x52, 0x03, 0x65, 0x6e, 0x64, 0x42, 0x8f, 0x01, 0x0a,
+ 0x13, 0x63, 0x6f, 0x6d, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e,
+ 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x42, 0x10, 0x44, 0x65,
+ 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x6f, 0x72, 0x50, 0x72, 0x6f, 0x74,
+ 0x6f, 0x73, 0x48, 0x01, 0x5a, 0x3e, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62,
+ 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x67, 0x6f, 0x6c, 0x61, 0x6e, 0x67, 0x2f,
+ 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2f, 0x70, 0x72, 0x6f,
+ 0x74, 0x6f, 0x63, 0x2d, 0x67, 0x65, 0x6e, 0x2d, 0x67, 0x6f, 0x2f, 0x64,
+ 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x6f, 0x72, 0x3b, 0x64, 0x65,
+ 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x6f, 0x72, 0xf8, 0x01, 0x01, 0xa2,
+ 0x02, 0x03, 0x47, 0x50, 0x42, 0xaa, 0x02, 0x1a, 0x47, 0x6f, 0x6f, 0x67,
+ 0x6c, 0x65, 0x2e, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e,
+ 0x52, 0x65, 0x66, 0x6c, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x0a, 0xda,
+ 0x01, 0x0a, 0x2c, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2f, 0x70, 0x65,
+ 0x72, 0x66, 0x65, 0x74, 0x74, 0x6f, 0x2f, 0x6d, 0x65, 0x74, 0x72, 0x69,
+ 0x63, 0x73, 0x2f, 0x63, 0x75, 0x73, 0x74, 0x6f, 0x6d, 0x5f, 0x6f, 0x70,
+ 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a,
+ 0x20, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2f, 0x70, 0x72, 0x6f, 0x74,
+ 0x6f, 0x62, 0x75, 0x66, 0x2f, 0x64, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70,
+ 0x74, 0x6f, 0x72, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x3a, 0x33, 0x0a,
+ 0x04, 0x75, 0x6e, 0x69, 0x74, 0x12, 0x1d, 0x2e, 0x67, 0x6f, 0x6f, 0x67,
+ 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e,
+ 0x46, 0x69, 0x65, 0x6c, 0x64, 0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73,
+ 0x18, 0xd1, 0x86, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x75, 0x6e,
+ 0x69, 0x74, 0x3a, 0x53, 0x0a, 0x14, 0x69, 0x6d, 0x70, 0x72, 0x6f, 0x76,
+ 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x44, 0x69, 0x72, 0x65, 0x63, 0x74, 0x69,
+ 0x6f, 0x6e, 0x12, 0x1d, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e,
+ 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x46, 0x69, 0x65,
+ 0x6c, 0x64, 0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x18, 0xd2, 0x86,
+ 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x14, 0x69, 0x6d, 0x70, 0x72, 0x6f,
+ 0x76, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x44, 0x69, 0x72, 0x65, 0x63, 0x74,
+ 0x69, 0x6f, 0x6e}};
+
+} // namespace perfetto
+
+#endif // SRC_TRACE_PROCESSOR_METRICS_CUSTOM_OPTIONS_DESCRIPTOR_H_
diff --git a/src/trace_processor/metrics/metrics.descriptor.h b/src/trace_processor/metrics/metrics.descriptor.h
index 6e19075..f703d36 100644
--- a/src/trace_processor/metrics/metrics.descriptor.h
+++ b/src/trace_processor/metrics/metrics.descriptor.h
@@ -25,17 +25,17 @@
// This file was autogenerated by tools/gen_binary_descriptors. Do not edit.
// SHA1(tools/gen_binary_descriptors)
-// f242f1ac484bbe7ba4c45e77b56ab588f8015196
+// d6628b15181dba5287e35b56b966b39ea93d42b1
// SHA1(protos/perfetto/metrics/metrics.proto)
-// 768c8fa5ed7f48eb644a1a45bb7295e32f8c771c
+// 29445577a551e8035ed8e99128ae38062fa77ee0
// This is the proto Metrics encoded as a ProtoFileDescriptor to allow
// for reflection without libprotobuf full/non-lite protos.
namespace perfetto {
-constexpr std::array<uint8_t, 12018> kMetricsDescriptor{
- {0x0a, 0x98, 0x03, 0x0a, 0x31, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2f,
+constexpr std::array<uint8_t, 14060> kMetricsDescriptor{
+ {0x0a, 0x94, 0x03, 0x0a, 0x31, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2f,
0x70, 0x65, 0x72, 0x66, 0x65, 0x74, 0x74, 0x6f, 0x2f, 0x6d, 0x65, 0x74,
0x72, 0x69, 0x63, 0x73, 0x2f, 0x61, 0x6e, 0x64, 0x72, 0x6f, 0x69, 0x64,
0x2f, 0x62, 0x61, 0x74, 0x74, 0x5f, 0x6d, 0x65, 0x74, 0x72, 0x69, 0x63,
@@ -68,75 +68,54 @@
0x63, 0x75, 0x72, 0x72, 0x65, 0x6e, 0x74, 0x55, 0x61, 0x12, 0x24, 0x0a,
0x0e, 0x63, 0x75, 0x72, 0x72, 0x65, 0x6e, 0x74, 0x5f, 0x61, 0x76, 0x67,
0x5f, 0x75, 0x61, 0x18, 0x05, 0x20, 0x01, 0x28, 0x01, 0x52, 0x0c, 0x63,
- 0x75, 0x72, 0x72, 0x65, 0x6e, 0x74, 0x41, 0x76, 0x67, 0x55, 0x61, 0x42,
- 0x02, 0x48, 0x03, 0x0a, 0xcb, 0x07, 0x0a, 0x30, 0x70, 0x72, 0x6f, 0x74,
- 0x6f, 0x73, 0x2f, 0x70, 0x65, 0x72, 0x66, 0x65, 0x74, 0x74, 0x6f, 0x2f,
- 0x6d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x73, 0x2f, 0x61, 0x6e, 0x64, 0x72,
- 0x6f, 0x69, 0x64, 0x2f, 0x63, 0x70, 0x75, 0x5f, 0x6d, 0x65, 0x74, 0x72,
- 0x69, 0x63, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x0f, 0x70, 0x65,
- 0x72, 0x66, 0x65, 0x74, 0x74, 0x6f, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f,
- 0x73, 0x22, 0x81, 0x07, 0x0a, 0x10, 0x41, 0x6e, 0x64, 0x72, 0x6f, 0x69,
- 0x64, 0x43, 0x70, 0x75, 0x4d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x12, 0x4c,
- 0x0a, 0x0c, 0x70, 0x72, 0x6f, 0x63, 0x65, 0x73, 0x73, 0x5f, 0x69, 0x6e,
- 0x66, 0x6f, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x29, 0x2e, 0x70,
- 0x65, 0x72, 0x66, 0x65, 0x74, 0x74, 0x6f, 0x2e, 0x70, 0x72, 0x6f, 0x74,
- 0x6f, 0x73, 0x2e, 0x41, 0x6e, 0x64, 0x72, 0x6f, 0x69, 0x64, 0x43, 0x70,
- 0x75, 0x4d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x2e, 0x50, 0x72, 0x6f, 0x63,
- 0x65, 0x73, 0x73, 0x52, 0x0b, 0x70, 0x72, 0x6f, 0x63, 0x65, 0x73, 0x73,
- 0x49, 0x6e, 0x66, 0x6f, 0x1a, 0xa8, 0x01, 0x0a, 0x07, 0x4d, 0x65, 0x74,
- 0x72, 0x69, 0x63, 0x73, 0x12, 0x18, 0x0a, 0x07, 0x6d, 0x63, 0x79, 0x63,
- 0x6c, 0x65, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x03, 0x52, 0x07, 0x6d,
- 0x63, 0x79, 0x63, 0x6c, 0x65, 0x73, 0x12, 0x1d, 0x0a, 0x0a, 0x72, 0x75,
- 0x6e, 0x74, 0x69, 0x6d, 0x65, 0x5f, 0x6e, 0x73, 0x18, 0x02, 0x20, 0x01,
- 0x28, 0x03, 0x52, 0x09, 0x72, 0x75, 0x6e, 0x74, 0x69, 0x6d, 0x65, 0x4e,
- 0x73, 0x12, 0x20, 0x0a, 0x0c, 0x6d, 0x69, 0x6e, 0x5f, 0x66, 0x72, 0x65,
- 0x71, 0x5f, 0x6b, 0x68, 0x7a, 0x18, 0x03, 0x20, 0x01, 0x28, 0x03, 0x52,
- 0x0a, 0x6d, 0x69, 0x6e, 0x46, 0x72, 0x65, 0x71, 0x4b, 0x68, 0x7a, 0x12,
- 0x20, 0x0a, 0x0c, 0x6d, 0x61, 0x78, 0x5f, 0x66, 0x72, 0x65, 0x71, 0x5f,
- 0x6b, 0x68, 0x7a, 0x18, 0x04, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0a, 0x6d,
- 0x61, 0x78, 0x46, 0x72, 0x65, 0x71, 0x4b, 0x68, 0x7a, 0x12, 0x20, 0x0a,
- 0x0c, 0x61, 0x76, 0x67, 0x5f, 0x66, 0x72, 0x65, 0x71, 0x5f, 0x6b, 0x68,
- 0x7a, 0x18, 0x05, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0a, 0x61, 0x76, 0x67,
- 0x46, 0x72, 0x65, 0x71, 0x4b, 0x68, 0x7a, 0x1a, 0x65, 0x0a, 0x08, 0x43,
- 0x6f, 0x72, 0x65, 0x44, 0x61, 0x74, 0x61, 0x12, 0x0e, 0x0a, 0x02, 0x69,
- 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x02, 0x69, 0x64, 0x12,
- 0x43, 0x0a, 0x07, 0x6d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x73, 0x18, 0x06,
- 0x20, 0x01, 0x28, 0x0b, 0x32, 0x29, 0x2e, 0x70, 0x65, 0x72, 0x66, 0x65,
+ 0x75, 0x72, 0x72, 0x65, 0x6e, 0x74, 0x41, 0x76, 0x67, 0x55, 0x61, 0x0a,
+ 0xc7, 0x07, 0x0a, 0x30, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2f, 0x70,
+ 0x65, 0x72, 0x66, 0x65, 0x74, 0x74, 0x6f, 0x2f, 0x6d, 0x65, 0x74, 0x72,
+ 0x69, 0x63, 0x73, 0x2f, 0x61, 0x6e, 0x64, 0x72, 0x6f, 0x69, 0x64, 0x2f,
+ 0x63, 0x70, 0x75, 0x5f, 0x6d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x2e, 0x70,
+ 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x0f, 0x70, 0x65, 0x72, 0x66, 0x65, 0x74,
+ 0x74, 0x6f, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x22, 0x81, 0x07,
+ 0x0a, 0x10, 0x41, 0x6e, 0x64, 0x72, 0x6f, 0x69, 0x64, 0x43, 0x70, 0x75,
+ 0x4d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x12, 0x4c, 0x0a, 0x0c, 0x70, 0x72,
+ 0x6f, 0x63, 0x65, 0x73, 0x73, 0x5f, 0x69, 0x6e, 0x66, 0x6f, 0x18, 0x01,
+ 0x20, 0x03, 0x28, 0x0b, 0x32, 0x29, 0x2e, 0x70, 0x65, 0x72, 0x66, 0x65,
0x74, 0x74, 0x6f, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2e, 0x41,
0x6e, 0x64, 0x72, 0x6f, 0x69, 0x64, 0x43, 0x70, 0x75, 0x4d, 0x65, 0x74,
- 0x72, 0x69, 0x63, 0x2e, 0x4d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x73, 0x52,
- 0x07, 0x6d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x73, 0x4a, 0x04, 0x08, 0x02,
- 0x10, 0x06, 0x1a, 0x67, 0x0a, 0x0c, 0x43, 0x6f, 0x72, 0x65, 0x54, 0x79,
- 0x70, 0x65, 0x44, 0x61, 0x74, 0x61, 0x12, 0x12, 0x0a, 0x04, 0x74, 0x79,
- 0x70, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x74, 0x79,
- 0x70, 0x65, 0x12, 0x43, 0x0a, 0x07, 0x6d, 0x65, 0x74, 0x72, 0x69, 0x63,
- 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x29, 0x2e, 0x70, 0x65,
- 0x72, 0x66, 0x65, 0x74, 0x74, 0x6f, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f,
- 0x73, 0x2e, 0x41, 0x6e, 0x64, 0x72, 0x6f, 0x69, 0x64, 0x43, 0x70, 0x75,
- 0x4d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x2e, 0x4d, 0x65, 0x74, 0x72, 0x69,
- 0x63, 0x73, 0x52, 0x07, 0x6d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x73, 0x1a,
- 0xf4, 0x01, 0x0a, 0x06, 0x54, 0x68, 0x72, 0x65, 0x61, 0x64, 0x12, 0x12,
- 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09,
- 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x43, 0x0a, 0x07, 0x6d, 0x65,
- 0x74, 0x72, 0x69, 0x63, 0x73, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32,
- 0x29, 0x2e, 0x70, 0x65, 0x72, 0x66, 0x65, 0x74, 0x74, 0x6f, 0x2e, 0x70,
- 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2e, 0x41, 0x6e, 0x64, 0x72, 0x6f, 0x69,
- 0x64, 0x43, 0x70, 0x75, 0x4d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x2e, 0x4d,
- 0x65, 0x74, 0x72, 0x69, 0x63, 0x73, 0x52, 0x07, 0x6d, 0x65, 0x74, 0x72,
- 0x69, 0x63, 0x73, 0x12, 0x3e, 0x0a, 0x04, 0x63, 0x6f, 0x72, 0x65, 0x18,
- 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x2a, 0x2e, 0x70, 0x65, 0x72, 0x66,
- 0x65, 0x74, 0x74, 0x6f, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2e,
- 0x41, 0x6e, 0x64, 0x72, 0x6f, 0x69, 0x64, 0x43, 0x70, 0x75, 0x4d, 0x65,
- 0x74, 0x72, 0x69, 0x63, 0x2e, 0x43, 0x6f, 0x72, 0x65, 0x44, 0x61, 0x74,
- 0x61, 0x52, 0x04, 0x63, 0x6f, 0x72, 0x65, 0x12, 0x4b, 0x0a, 0x09, 0x63,
- 0x6f, 0x72, 0x65, 0x5f, 0x74, 0x79, 0x70, 0x65, 0x18, 0x05, 0x20, 0x03,
- 0x28, 0x0b, 0x32, 0x2e, 0x2e, 0x70, 0x65, 0x72, 0x66, 0x65, 0x74, 0x74,
- 0x6f, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2e, 0x41, 0x6e, 0x64,
- 0x72, 0x6f, 0x69, 0x64, 0x43, 0x70, 0x75, 0x4d, 0x65, 0x74, 0x72, 0x69,
- 0x63, 0x2e, 0x43, 0x6f, 0x72, 0x65, 0x54, 0x79, 0x70, 0x65, 0x44, 0x61,
- 0x74, 0x61, 0x52, 0x08, 0x63, 0x6f, 0x72, 0x65, 0x54, 0x79, 0x70, 0x65,
- 0x4a, 0x04, 0x08, 0x03, 0x10, 0x04, 0x1a, 0xac, 0x01, 0x0a, 0x07, 0x50,
- 0x72, 0x6f, 0x63, 0x65, 0x73, 0x73, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61,
+ 0x72, 0x69, 0x63, 0x2e, 0x50, 0x72, 0x6f, 0x63, 0x65, 0x73, 0x73, 0x52,
+ 0x0b, 0x70, 0x72, 0x6f, 0x63, 0x65, 0x73, 0x73, 0x49, 0x6e, 0x66, 0x6f,
+ 0x1a, 0xa8, 0x01, 0x0a, 0x07, 0x4d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x73,
+ 0x12, 0x18, 0x0a, 0x07, 0x6d, 0x63, 0x79, 0x63, 0x6c, 0x65, 0x73, 0x18,
+ 0x01, 0x20, 0x01, 0x28, 0x03, 0x52, 0x07, 0x6d, 0x63, 0x79, 0x63, 0x6c,
+ 0x65, 0x73, 0x12, 0x1d, 0x0a, 0x0a, 0x72, 0x75, 0x6e, 0x74, 0x69, 0x6d,
+ 0x65, 0x5f, 0x6e, 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x03, 0x52, 0x09,
+ 0x72, 0x75, 0x6e, 0x74, 0x69, 0x6d, 0x65, 0x4e, 0x73, 0x12, 0x20, 0x0a,
+ 0x0c, 0x6d, 0x69, 0x6e, 0x5f, 0x66, 0x72, 0x65, 0x71, 0x5f, 0x6b, 0x68,
+ 0x7a, 0x18, 0x03, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0a, 0x6d, 0x69, 0x6e,
+ 0x46, 0x72, 0x65, 0x71, 0x4b, 0x68, 0x7a, 0x12, 0x20, 0x0a, 0x0c, 0x6d,
+ 0x61, 0x78, 0x5f, 0x66, 0x72, 0x65, 0x71, 0x5f, 0x6b, 0x68, 0x7a, 0x18,
+ 0x04, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0a, 0x6d, 0x61, 0x78, 0x46, 0x72,
+ 0x65, 0x71, 0x4b, 0x68, 0x7a, 0x12, 0x20, 0x0a, 0x0c, 0x61, 0x76, 0x67,
+ 0x5f, 0x66, 0x72, 0x65, 0x71, 0x5f, 0x6b, 0x68, 0x7a, 0x18, 0x05, 0x20,
+ 0x01, 0x28, 0x03, 0x52, 0x0a, 0x61, 0x76, 0x67, 0x46, 0x72, 0x65, 0x71,
+ 0x4b, 0x68, 0x7a, 0x1a, 0x65, 0x0a, 0x08, 0x43, 0x6f, 0x72, 0x65, 0x44,
+ 0x61, 0x74, 0x61, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, 0x20,
+ 0x01, 0x28, 0x0d, 0x52, 0x02, 0x69, 0x64, 0x12, 0x43, 0x0a, 0x07, 0x6d,
+ 0x65, 0x74, 0x72, 0x69, 0x63, 0x73, 0x18, 0x06, 0x20, 0x01, 0x28, 0x0b,
+ 0x32, 0x29, 0x2e, 0x70, 0x65, 0x72, 0x66, 0x65, 0x74, 0x74, 0x6f, 0x2e,
+ 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2e, 0x41, 0x6e, 0x64, 0x72, 0x6f,
+ 0x69, 0x64, 0x43, 0x70, 0x75, 0x4d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x2e,
+ 0x4d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x73, 0x52, 0x07, 0x6d, 0x65, 0x74,
+ 0x72, 0x69, 0x63, 0x73, 0x4a, 0x04, 0x08, 0x02, 0x10, 0x06, 0x1a, 0x67,
+ 0x0a, 0x0c, 0x43, 0x6f, 0x72, 0x65, 0x54, 0x79, 0x70, 0x65, 0x44, 0x61,
+ 0x74, 0x61, 0x12, 0x12, 0x0a, 0x04, 0x74, 0x79, 0x70, 0x65, 0x18, 0x01,
+ 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x74, 0x79, 0x70, 0x65, 0x12, 0x43,
+ 0x0a, 0x07, 0x6d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x73, 0x18, 0x02, 0x20,
+ 0x01, 0x28, 0x0b, 0x32, 0x29, 0x2e, 0x70, 0x65, 0x72, 0x66, 0x65, 0x74,
+ 0x74, 0x6f, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2e, 0x41, 0x6e,
+ 0x64, 0x72, 0x6f, 0x69, 0x64, 0x43, 0x70, 0x75, 0x4d, 0x65, 0x74, 0x72,
+ 0x69, 0x63, 0x2e, 0x4d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x73, 0x52, 0x07,
+ 0x6d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x73, 0x1a, 0xf4, 0x01, 0x0a, 0x06,
+ 0x54, 0x68, 0x72, 0x65, 0x61, 0x64, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61,
0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61,
0x6d, 0x65, 0x12, 0x43, 0x0a, 0x07, 0x6d, 0x65, 0x74, 0x72, 0x69, 0x63,
0x73, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x29, 0x2e, 0x70, 0x65,
@@ -144,100 +123,120 @@
0x73, 0x2e, 0x41, 0x6e, 0x64, 0x72, 0x6f, 0x69, 0x64, 0x43, 0x70, 0x75,
0x4d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x2e, 0x4d, 0x65, 0x74, 0x72, 0x69,
0x63, 0x73, 0x52, 0x07, 0x6d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x73, 0x12,
- 0x42, 0x0a, 0x07, 0x74, 0x68, 0x72, 0x65, 0x61, 0x64, 0x73, 0x18, 0x02,
- 0x20, 0x03, 0x28, 0x0b, 0x32, 0x28, 0x2e, 0x70, 0x65, 0x72, 0x66, 0x65,
- 0x74, 0x74, 0x6f, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2e, 0x41,
- 0x6e, 0x64, 0x72, 0x6f, 0x69, 0x64, 0x43, 0x70, 0x75, 0x4d, 0x65, 0x74,
- 0x72, 0x69, 0x63, 0x2e, 0x54, 0x68, 0x72, 0x65, 0x61, 0x64, 0x52, 0x07,
- 0x74, 0x68, 0x72, 0x65, 0x61, 0x64, 0x73, 0x4a, 0x04, 0x08, 0x03, 0x10,
- 0x04, 0x42, 0x02, 0x48, 0x03, 0x0a, 0x93, 0x08, 0x0a, 0x30, 0x70, 0x72,
- 0x6f, 0x74, 0x6f, 0x73, 0x2f, 0x70, 0x65, 0x72, 0x66, 0x65, 0x74, 0x74,
- 0x6f, 0x2f, 0x6d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x73, 0x2f, 0x61, 0x6e,
- 0x64, 0x72, 0x6f, 0x69, 0x64, 0x2f, 0x6d, 0x65, 0x6d, 0x5f, 0x6d, 0x65,
- 0x74, 0x72, 0x69, 0x63, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x0f,
- 0x70, 0x65, 0x72, 0x66, 0x65, 0x74, 0x74, 0x6f, 0x2e, 0x70, 0x72, 0x6f,
- 0x74, 0x6f, 0x73, 0x22, 0xc9, 0x07, 0x0a, 0x13, 0x41, 0x6e, 0x64, 0x72,
- 0x6f, 0x69, 0x64, 0x4d, 0x65, 0x6d, 0x6f, 0x72, 0x79, 0x4d, 0x65, 0x74,
- 0x72, 0x69, 0x63, 0x12, 0x5c, 0x0a, 0x0f, 0x70, 0x72, 0x6f, 0x63, 0x65,
- 0x73, 0x73, 0x5f, 0x6d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x73, 0x18, 0x01,
- 0x20, 0x03, 0x28, 0x0b, 0x32, 0x33, 0x2e, 0x70, 0x65, 0x72, 0x66, 0x65,
- 0x74, 0x74, 0x6f, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2e, 0x41,
- 0x6e, 0x64, 0x72, 0x6f, 0x69, 0x64, 0x4d, 0x65, 0x6d, 0x6f, 0x72, 0x79,
- 0x4d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x2e, 0x50, 0x72, 0x6f, 0x63, 0x65,
- 0x73, 0x73, 0x4d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x73, 0x52, 0x0e, 0x70,
- 0x72, 0x6f, 0x63, 0x65, 0x73, 0x73, 0x4d, 0x65, 0x74, 0x72, 0x69, 0x63,
- 0x73, 0x1a, 0xfd, 0x01, 0x0a, 0x0e, 0x50, 0x72, 0x6f, 0x63, 0x65, 0x73,
- 0x73, 0x4d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x73, 0x12, 0x21, 0x0a, 0x0c,
- 0x70, 0x72, 0x6f, 0x63, 0x65, 0x73, 0x73, 0x5f, 0x6e, 0x61, 0x6d, 0x65,
- 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x70, 0x72, 0x6f, 0x63,
- 0x65, 0x73, 0x73, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x61, 0x0a, 0x0e, 0x74,
- 0x6f, 0x74, 0x61, 0x6c, 0x5f, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x65, 0x72,
- 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x3a, 0x2e, 0x70, 0x65,
- 0x72, 0x66, 0x65, 0x74, 0x74, 0x6f, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f,
- 0x73, 0x2e, 0x41, 0x6e, 0x64, 0x72, 0x6f, 0x69, 0x64, 0x4d, 0x65, 0x6d,
- 0x6f, 0x72, 0x79, 0x4d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x2e, 0x50, 0x72,
- 0x6f, 0x63, 0x65, 0x73, 0x73, 0x4d, 0x65, 0x6d, 0x6f, 0x72, 0x79, 0x43,
- 0x6f, 0x75, 0x6e, 0x74, 0x65, 0x72, 0x73, 0x52, 0x0d, 0x74, 0x6f, 0x74,
- 0x61, 0x6c, 0x43, 0x6f, 0x75, 0x6e, 0x74, 0x65, 0x72, 0x73, 0x12, 0x65,
- 0x0a, 0x12, 0x70, 0x72, 0x69, 0x6f, 0x72, 0x69, 0x74, 0x79, 0x5f, 0x62,
- 0x72, 0x65, 0x61, 0x6b, 0x64, 0x6f, 0x77, 0x6e, 0x18, 0x03, 0x20, 0x03,
- 0x28, 0x0b, 0x32, 0x36, 0x2e, 0x70, 0x65, 0x72, 0x66, 0x65, 0x74, 0x74,
- 0x6f, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2e, 0x41, 0x6e, 0x64,
- 0x72, 0x6f, 0x69, 0x64, 0x4d, 0x65, 0x6d, 0x6f, 0x72, 0x79, 0x4d, 0x65,
- 0x74, 0x72, 0x69, 0x63, 0x2e, 0x50, 0x72, 0x69, 0x6f, 0x72, 0x69, 0x74,
- 0x79, 0x42, 0x72, 0x65, 0x61, 0x6b, 0x64, 0x6f, 0x77, 0x6e, 0x52, 0x11,
- 0x70, 0x72, 0x69, 0x6f, 0x72, 0x69, 0x74, 0x79, 0x42, 0x72, 0x65, 0x61,
- 0x6b, 0x64, 0x6f, 0x77, 0x6e, 0x1a, 0x87, 0x01, 0x0a, 0x11, 0x50, 0x72,
- 0x69, 0x6f, 0x72, 0x69, 0x74, 0x79, 0x42, 0x72, 0x65, 0x61, 0x6b, 0x64,
- 0x6f, 0x77, 0x6e, 0x12, 0x1a, 0x0a, 0x08, 0x70, 0x72, 0x69, 0x6f, 0x72,
- 0x69, 0x74, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x70,
- 0x72, 0x69, 0x6f, 0x72, 0x69, 0x74, 0x79, 0x12, 0x56, 0x0a, 0x08, 0x63,
- 0x6f, 0x75, 0x6e, 0x74, 0x65, 0x72, 0x73, 0x18, 0x02, 0x20, 0x01, 0x28,
- 0x0b, 0x32, 0x3a, 0x2e, 0x70, 0x65, 0x72, 0x66, 0x65, 0x74, 0x74, 0x6f,
+ 0x3e, 0x0a, 0x04, 0x63, 0x6f, 0x72, 0x65, 0x18, 0x02, 0x20, 0x03, 0x28,
+ 0x0b, 0x32, 0x2a, 0x2e, 0x70, 0x65, 0x72, 0x66, 0x65, 0x74, 0x74, 0x6f,
0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2e, 0x41, 0x6e, 0x64, 0x72,
- 0x6f, 0x69, 0x64, 0x4d, 0x65, 0x6d, 0x6f, 0x72, 0x79, 0x4d, 0x65, 0x74,
- 0x72, 0x69, 0x63, 0x2e, 0x50, 0x72, 0x6f, 0x63, 0x65, 0x73, 0x73, 0x4d,
- 0x65, 0x6d, 0x6f, 0x72, 0x79, 0x43, 0x6f, 0x75, 0x6e, 0x74, 0x65, 0x72,
- 0x73, 0x52, 0x08, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x65, 0x72, 0x73, 0x1a,
- 0x88, 0x03, 0x0a, 0x15, 0x50, 0x72, 0x6f, 0x63, 0x65, 0x73, 0x73, 0x4d,
- 0x65, 0x6d, 0x6f, 0x72, 0x79, 0x43, 0x6f, 0x75, 0x6e, 0x74, 0x65, 0x72,
- 0x73, 0x12, 0x47, 0x0a, 0x08, 0x61, 0x6e, 0x6f, 0x6e, 0x5f, 0x72, 0x73,
- 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2c, 0x2e, 0x70, 0x65,
- 0x72, 0x66, 0x65, 0x74, 0x74, 0x6f, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f,
- 0x73, 0x2e, 0x41, 0x6e, 0x64, 0x72, 0x6f, 0x69, 0x64, 0x4d, 0x65, 0x6d,
- 0x6f, 0x72, 0x79, 0x4d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x2e, 0x43, 0x6f,
- 0x75, 0x6e, 0x74, 0x65, 0x72, 0x52, 0x07, 0x61, 0x6e, 0x6f, 0x6e, 0x52,
- 0x73, 0x73, 0x12, 0x47, 0x0a, 0x08, 0x66, 0x69, 0x6c, 0x65, 0x5f, 0x72,
- 0x73, 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2c, 0x2e, 0x70,
+ 0x6f, 0x69, 0x64, 0x43, 0x70, 0x75, 0x4d, 0x65, 0x74, 0x72, 0x69, 0x63,
+ 0x2e, 0x43, 0x6f, 0x72, 0x65, 0x44, 0x61, 0x74, 0x61, 0x52, 0x04, 0x63,
+ 0x6f, 0x72, 0x65, 0x12, 0x4b, 0x0a, 0x09, 0x63, 0x6f, 0x72, 0x65, 0x5f,
+ 0x74, 0x79, 0x70, 0x65, 0x18, 0x05, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x2e,
+ 0x2e, 0x70, 0x65, 0x72, 0x66, 0x65, 0x74, 0x74, 0x6f, 0x2e, 0x70, 0x72,
+ 0x6f, 0x74, 0x6f, 0x73, 0x2e, 0x41, 0x6e, 0x64, 0x72, 0x6f, 0x69, 0x64,
+ 0x43, 0x70, 0x75, 0x4d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x2e, 0x43, 0x6f,
+ 0x72, 0x65, 0x54, 0x79, 0x70, 0x65, 0x44, 0x61, 0x74, 0x61, 0x52, 0x08,
+ 0x63, 0x6f, 0x72, 0x65, 0x54, 0x79, 0x70, 0x65, 0x4a, 0x04, 0x08, 0x03,
+ 0x10, 0x04, 0x1a, 0xac, 0x01, 0x0a, 0x07, 0x50, 0x72, 0x6f, 0x63, 0x65,
+ 0x73, 0x73, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01,
+ 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x43,
+ 0x0a, 0x07, 0x6d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x73, 0x18, 0x04, 0x20,
+ 0x01, 0x28, 0x0b, 0x32, 0x29, 0x2e, 0x70, 0x65, 0x72, 0x66, 0x65, 0x74,
+ 0x74, 0x6f, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2e, 0x41, 0x6e,
+ 0x64, 0x72, 0x6f, 0x69, 0x64, 0x43, 0x70, 0x75, 0x4d, 0x65, 0x74, 0x72,
+ 0x69, 0x63, 0x2e, 0x4d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x73, 0x52, 0x07,
+ 0x6d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x73, 0x12, 0x42, 0x0a, 0x07, 0x74,
+ 0x68, 0x72, 0x65, 0x61, 0x64, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b,
+ 0x32, 0x28, 0x2e, 0x70, 0x65, 0x72, 0x66, 0x65, 0x74, 0x74, 0x6f, 0x2e,
+ 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2e, 0x41, 0x6e, 0x64, 0x72, 0x6f,
+ 0x69, 0x64, 0x43, 0x70, 0x75, 0x4d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x2e,
+ 0x54, 0x68, 0x72, 0x65, 0x61, 0x64, 0x52, 0x07, 0x74, 0x68, 0x72, 0x65,
+ 0x61, 0x64, 0x73, 0x4a, 0x04, 0x08, 0x03, 0x10, 0x04, 0x0a, 0x8f, 0x08,
+ 0x0a, 0x30, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2f, 0x70, 0x65, 0x72,
+ 0x66, 0x65, 0x74, 0x74, 0x6f, 0x2f, 0x6d, 0x65, 0x74, 0x72, 0x69, 0x63,
+ 0x73, 0x2f, 0x61, 0x6e, 0x64, 0x72, 0x6f, 0x69, 0x64, 0x2f, 0x6d, 0x65,
+ 0x6d, 0x5f, 0x6d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x2e, 0x70, 0x72, 0x6f,
+ 0x74, 0x6f, 0x12, 0x0f, 0x70, 0x65, 0x72, 0x66, 0x65, 0x74, 0x74, 0x6f,
+ 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x22, 0xc9, 0x07, 0x0a, 0x13,
+ 0x41, 0x6e, 0x64, 0x72, 0x6f, 0x69, 0x64, 0x4d, 0x65, 0x6d, 0x6f, 0x72,
+ 0x79, 0x4d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x12, 0x5c, 0x0a, 0x0f, 0x70,
+ 0x72, 0x6f, 0x63, 0x65, 0x73, 0x73, 0x5f, 0x6d, 0x65, 0x74, 0x72, 0x69,
+ 0x63, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x33, 0x2e, 0x70,
0x65, 0x72, 0x66, 0x65, 0x74, 0x74, 0x6f, 0x2e, 0x70, 0x72, 0x6f, 0x74,
0x6f, 0x73, 0x2e, 0x41, 0x6e, 0x64, 0x72, 0x6f, 0x69, 0x64, 0x4d, 0x65,
- 0x6d, 0x6f, 0x72, 0x79, 0x4d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x2e, 0x43,
- 0x6f, 0x75, 0x6e, 0x74, 0x65, 0x72, 0x52, 0x07, 0x66, 0x69, 0x6c, 0x65,
- 0x52, 0x73, 0x73, 0x12, 0x40, 0x0a, 0x04, 0x73, 0x77, 0x61, 0x70, 0x18,
- 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2c, 0x2e, 0x70, 0x65, 0x72, 0x66,
+ 0x6d, 0x6f, 0x72, 0x79, 0x4d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x2e, 0x50,
+ 0x72, 0x6f, 0x63, 0x65, 0x73, 0x73, 0x4d, 0x65, 0x74, 0x72, 0x69, 0x63,
+ 0x73, 0x52, 0x0e, 0x70, 0x72, 0x6f, 0x63, 0x65, 0x73, 0x73, 0x4d, 0x65,
+ 0x74, 0x72, 0x69, 0x63, 0x73, 0x1a, 0xfd, 0x01, 0x0a, 0x0e, 0x50, 0x72,
+ 0x6f, 0x63, 0x65, 0x73, 0x73, 0x4d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x73,
+ 0x12, 0x21, 0x0a, 0x0c, 0x70, 0x72, 0x6f, 0x63, 0x65, 0x73, 0x73, 0x5f,
+ 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b,
+ 0x70, 0x72, 0x6f, 0x63, 0x65, 0x73, 0x73, 0x4e, 0x61, 0x6d, 0x65, 0x12,
+ 0x61, 0x0a, 0x0e, 0x74, 0x6f, 0x74, 0x61, 0x6c, 0x5f, 0x63, 0x6f, 0x75,
+ 0x6e, 0x74, 0x65, 0x72, 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32,
+ 0x3a, 0x2e, 0x70, 0x65, 0x72, 0x66, 0x65, 0x74, 0x74, 0x6f, 0x2e, 0x70,
+ 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2e, 0x41, 0x6e, 0x64, 0x72, 0x6f, 0x69,
+ 0x64, 0x4d, 0x65, 0x6d, 0x6f, 0x72, 0x79, 0x4d, 0x65, 0x74, 0x72, 0x69,
+ 0x63, 0x2e, 0x50, 0x72, 0x6f, 0x63, 0x65, 0x73, 0x73, 0x4d, 0x65, 0x6d,
+ 0x6f, 0x72, 0x79, 0x43, 0x6f, 0x75, 0x6e, 0x74, 0x65, 0x72, 0x73, 0x52,
+ 0x0d, 0x74, 0x6f, 0x74, 0x61, 0x6c, 0x43, 0x6f, 0x75, 0x6e, 0x74, 0x65,
+ 0x72, 0x73, 0x12, 0x65, 0x0a, 0x12, 0x70, 0x72, 0x69, 0x6f, 0x72, 0x69,
+ 0x74, 0x79, 0x5f, 0x62, 0x72, 0x65, 0x61, 0x6b, 0x64, 0x6f, 0x77, 0x6e,
+ 0x18, 0x03, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x36, 0x2e, 0x70, 0x65, 0x72,
+ 0x66, 0x65, 0x74, 0x74, 0x6f, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73,
+ 0x2e, 0x41, 0x6e, 0x64, 0x72, 0x6f, 0x69, 0x64, 0x4d, 0x65, 0x6d, 0x6f,
+ 0x72, 0x79, 0x4d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x2e, 0x50, 0x72, 0x69,
+ 0x6f, 0x72, 0x69, 0x74, 0x79, 0x42, 0x72, 0x65, 0x61, 0x6b, 0x64, 0x6f,
+ 0x77, 0x6e, 0x52, 0x11, 0x70, 0x72, 0x69, 0x6f, 0x72, 0x69, 0x74, 0x79,
+ 0x42, 0x72, 0x65, 0x61, 0x6b, 0x64, 0x6f, 0x77, 0x6e, 0x1a, 0x87, 0x01,
+ 0x0a, 0x11, 0x50, 0x72, 0x69, 0x6f, 0x72, 0x69, 0x74, 0x79, 0x42, 0x72,
+ 0x65, 0x61, 0x6b, 0x64, 0x6f, 0x77, 0x6e, 0x12, 0x1a, 0x0a, 0x08, 0x70,
+ 0x72, 0x69, 0x6f, 0x72, 0x69, 0x74, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28,
+ 0x09, 0x52, 0x08, 0x70, 0x72, 0x69, 0x6f, 0x72, 0x69, 0x74, 0x79, 0x12,
+ 0x56, 0x0a, 0x08, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x65, 0x72, 0x73, 0x18,
+ 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x3a, 0x2e, 0x70, 0x65, 0x72, 0x66,
0x65, 0x74, 0x74, 0x6f, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2e,
0x41, 0x6e, 0x64, 0x72, 0x6f, 0x69, 0x64, 0x4d, 0x65, 0x6d, 0x6f, 0x72,
- 0x79, 0x4d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x2e, 0x43, 0x6f, 0x75, 0x6e,
- 0x74, 0x65, 0x72, 0x52, 0x04, 0x73, 0x77, 0x61, 0x70, 0x12, 0x50, 0x0a,
- 0x0d, 0x61, 0x6e, 0x6f, 0x6e, 0x5f, 0x61, 0x6e, 0x64, 0x5f, 0x73, 0x77,
- 0x61, 0x70, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2c, 0x2e, 0x70,
- 0x65, 0x72, 0x66, 0x65, 0x74, 0x74, 0x6f, 0x2e, 0x70, 0x72, 0x6f, 0x74,
- 0x6f, 0x73, 0x2e, 0x41, 0x6e, 0x64, 0x72, 0x6f, 0x69, 0x64, 0x4d, 0x65,
- 0x6d, 0x6f, 0x72, 0x79, 0x4d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x2e, 0x43,
- 0x6f, 0x75, 0x6e, 0x74, 0x65, 0x72, 0x52, 0x0b, 0x61, 0x6e, 0x6f, 0x6e,
- 0x41, 0x6e, 0x64, 0x53, 0x77, 0x61, 0x70, 0x12, 0x49, 0x0a, 0x09, 0x6a,
- 0x61, 0x76, 0x61, 0x5f, 0x68, 0x65, 0x61, 0x70, 0x18, 0x05, 0x20, 0x01,
- 0x28, 0x0b, 0x32, 0x2c, 0x2e, 0x70, 0x65, 0x72, 0x66, 0x65, 0x74, 0x74,
- 0x6f, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2e, 0x41, 0x6e, 0x64,
- 0x72, 0x6f, 0x69, 0x64, 0x4d, 0x65, 0x6d, 0x6f, 0x72, 0x79, 0x4d, 0x65,
- 0x74, 0x72, 0x69, 0x63, 0x2e, 0x43, 0x6f, 0x75, 0x6e, 0x74, 0x65, 0x72,
- 0x52, 0x08, 0x6a, 0x61, 0x76, 0x61, 0x48, 0x65, 0x61, 0x70, 0x1a, 0x3f,
- 0x0a, 0x07, 0x43, 0x6f, 0x75, 0x6e, 0x74, 0x65, 0x72, 0x12, 0x10, 0x0a,
- 0x03, 0x6d, 0x69, 0x6e, 0x18, 0x01, 0x20, 0x01, 0x28, 0x01, 0x52, 0x03,
- 0x6d, 0x69, 0x6e, 0x12, 0x10, 0x0a, 0x03, 0x6d, 0x61, 0x78, 0x18, 0x02,
- 0x20, 0x01, 0x28, 0x01, 0x52, 0x03, 0x6d, 0x61, 0x78, 0x12, 0x10, 0x0a,
- 0x03, 0x61, 0x76, 0x67, 0x18, 0x03, 0x20, 0x01, 0x28, 0x01, 0x52, 0x03,
- 0x61, 0x76, 0x67, 0x42, 0x02, 0x48, 0x03, 0x0a, 0xa4, 0x06, 0x0a, 0x36,
+ 0x79, 0x4d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x2e, 0x50, 0x72, 0x6f, 0x63,
+ 0x65, 0x73, 0x73, 0x4d, 0x65, 0x6d, 0x6f, 0x72, 0x79, 0x43, 0x6f, 0x75,
+ 0x6e, 0x74, 0x65, 0x72, 0x73, 0x52, 0x08, 0x63, 0x6f, 0x75, 0x6e, 0x74,
+ 0x65, 0x72, 0x73, 0x1a, 0x88, 0x03, 0x0a, 0x15, 0x50, 0x72, 0x6f, 0x63,
+ 0x65, 0x73, 0x73, 0x4d, 0x65, 0x6d, 0x6f, 0x72, 0x79, 0x43, 0x6f, 0x75,
+ 0x6e, 0x74, 0x65, 0x72, 0x73, 0x12, 0x47, 0x0a, 0x08, 0x61, 0x6e, 0x6f,
+ 0x6e, 0x5f, 0x72, 0x73, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32,
+ 0x2c, 0x2e, 0x70, 0x65, 0x72, 0x66, 0x65, 0x74, 0x74, 0x6f, 0x2e, 0x70,
+ 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2e, 0x41, 0x6e, 0x64, 0x72, 0x6f, 0x69,
+ 0x64, 0x4d, 0x65, 0x6d, 0x6f, 0x72, 0x79, 0x4d, 0x65, 0x74, 0x72, 0x69,
+ 0x63, 0x2e, 0x43, 0x6f, 0x75, 0x6e, 0x74, 0x65, 0x72, 0x52, 0x07, 0x61,
+ 0x6e, 0x6f, 0x6e, 0x52, 0x73, 0x73, 0x12, 0x47, 0x0a, 0x08, 0x66, 0x69,
+ 0x6c, 0x65, 0x5f, 0x72, 0x73, 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b,
+ 0x32, 0x2c, 0x2e, 0x70, 0x65, 0x72, 0x66, 0x65, 0x74, 0x74, 0x6f, 0x2e,
+ 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2e, 0x41, 0x6e, 0x64, 0x72, 0x6f,
+ 0x69, 0x64, 0x4d, 0x65, 0x6d, 0x6f, 0x72, 0x79, 0x4d, 0x65, 0x74, 0x72,
+ 0x69, 0x63, 0x2e, 0x43, 0x6f, 0x75, 0x6e, 0x74, 0x65, 0x72, 0x52, 0x07,
+ 0x66, 0x69, 0x6c, 0x65, 0x52, 0x73, 0x73, 0x12, 0x40, 0x0a, 0x04, 0x73,
+ 0x77, 0x61, 0x70, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2c, 0x2e,
+ 0x70, 0x65, 0x72, 0x66, 0x65, 0x74, 0x74, 0x6f, 0x2e, 0x70, 0x72, 0x6f,
+ 0x74, 0x6f, 0x73, 0x2e, 0x41, 0x6e, 0x64, 0x72, 0x6f, 0x69, 0x64, 0x4d,
+ 0x65, 0x6d, 0x6f, 0x72, 0x79, 0x4d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x2e,
+ 0x43, 0x6f, 0x75, 0x6e, 0x74, 0x65, 0x72, 0x52, 0x04, 0x73, 0x77, 0x61,
+ 0x70, 0x12, 0x50, 0x0a, 0x0d, 0x61, 0x6e, 0x6f, 0x6e, 0x5f, 0x61, 0x6e,
+ 0x64, 0x5f, 0x73, 0x77, 0x61, 0x70, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b,
+ 0x32, 0x2c, 0x2e, 0x70, 0x65, 0x72, 0x66, 0x65, 0x74, 0x74, 0x6f, 0x2e,
+ 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2e, 0x41, 0x6e, 0x64, 0x72, 0x6f,
+ 0x69, 0x64, 0x4d, 0x65, 0x6d, 0x6f, 0x72, 0x79, 0x4d, 0x65, 0x74, 0x72,
+ 0x69, 0x63, 0x2e, 0x43, 0x6f, 0x75, 0x6e, 0x74, 0x65, 0x72, 0x52, 0x0b,
+ 0x61, 0x6e, 0x6f, 0x6e, 0x41, 0x6e, 0x64, 0x53, 0x77, 0x61, 0x70, 0x12,
+ 0x49, 0x0a, 0x09, 0x6a, 0x61, 0x76, 0x61, 0x5f, 0x68, 0x65, 0x61, 0x70,
+ 0x18, 0x05, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2c, 0x2e, 0x70, 0x65, 0x72,
+ 0x66, 0x65, 0x74, 0x74, 0x6f, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73,
+ 0x2e, 0x41, 0x6e, 0x64, 0x72, 0x6f, 0x69, 0x64, 0x4d, 0x65, 0x6d, 0x6f,
+ 0x72, 0x79, 0x4d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x2e, 0x43, 0x6f, 0x75,
+ 0x6e, 0x74, 0x65, 0x72, 0x52, 0x08, 0x6a, 0x61, 0x76, 0x61, 0x48, 0x65,
+ 0x61, 0x70, 0x1a, 0x3f, 0x0a, 0x07, 0x43, 0x6f, 0x75, 0x6e, 0x74, 0x65,
+ 0x72, 0x12, 0x10, 0x0a, 0x03, 0x6d, 0x69, 0x6e, 0x18, 0x01, 0x20, 0x01,
+ 0x28, 0x01, 0x52, 0x03, 0x6d, 0x69, 0x6e, 0x12, 0x10, 0x0a, 0x03, 0x6d,
+ 0x61, 0x78, 0x18, 0x02, 0x20, 0x01, 0x28, 0x01, 0x52, 0x03, 0x6d, 0x61,
+ 0x78, 0x12, 0x10, 0x0a, 0x03, 0x61, 0x76, 0x67, 0x18, 0x03, 0x20, 0x01,
+ 0x28, 0x01, 0x52, 0x03, 0x61, 0x76, 0x67, 0x0a, 0xa0, 0x06, 0x0a, 0x36,
0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2f, 0x70, 0x65, 0x72, 0x66, 0x65,
0x74, 0x74, 0x6f, 0x2f, 0x6d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x73, 0x2f,
0x61, 0x6e, 0x64, 0x72, 0x6f, 0x69, 0x64, 0x2f, 0x6d, 0x65, 0x6d, 0x5f,
@@ -304,56 +303,55 @@
0x63, 0x6f, 0x72, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x05, 0x52, 0x08,
0x6f, 0x6f, 0x6d, 0x53, 0x63, 0x6f, 0x72, 0x65, 0x12, 0x14, 0x0a, 0x05,
0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x01, 0x52,
- 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x42, 0x02, 0x48, 0x03, 0x0a, 0xaf,
- 0x02, 0x0a, 0x30, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2f, 0x70, 0x65,
- 0x72, 0x66, 0x65, 0x74, 0x74, 0x6f, 0x2f, 0x6d, 0x65, 0x74, 0x72, 0x69,
- 0x63, 0x73, 0x2f, 0x61, 0x6e, 0x64, 0x72, 0x6f, 0x69, 0x64, 0x2f, 0x69,
- 0x6f, 0x6e, 0x5f, 0x6d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x2e, 0x70, 0x72,
- 0x6f, 0x74, 0x6f, 0x12, 0x0f, 0x70, 0x65, 0x72, 0x66, 0x65, 0x74, 0x74,
- 0x6f, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x22, 0xe5, 0x01, 0x0a,
- 0x10, 0x41, 0x6e, 0x64, 0x72, 0x6f, 0x69, 0x64, 0x49, 0x6f, 0x6e, 0x4d,
- 0x65, 0x74, 0x72, 0x69, 0x63, 0x12, 0x40, 0x0a, 0x06, 0x62, 0x75, 0x66,
- 0x66, 0x65, 0x72, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x28, 0x2e,
- 0x70, 0x65, 0x72, 0x66, 0x65, 0x74, 0x74, 0x6f, 0x2e, 0x70, 0x72, 0x6f,
- 0x74, 0x6f, 0x73, 0x2e, 0x41, 0x6e, 0x64, 0x72, 0x6f, 0x69, 0x64, 0x49,
- 0x6f, 0x6e, 0x4d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x2e, 0x42, 0x75, 0x66,
- 0x66, 0x65, 0x72, 0x52, 0x06, 0x62, 0x75, 0x66, 0x66, 0x65, 0x72, 0x1a,
- 0x8e, 0x01, 0x0a, 0x06, 0x42, 0x75, 0x66, 0x66, 0x65, 0x72, 0x12, 0x12,
- 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09,
- 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x24, 0x0a, 0x0e, 0x61, 0x76,
- 0x67, 0x5f, 0x73, 0x69, 0x7a, 0x65, 0x5f, 0x62, 0x79, 0x74, 0x65, 0x73,
- 0x18, 0x02, 0x20, 0x01, 0x28, 0x01, 0x52, 0x0c, 0x61, 0x76, 0x67, 0x53,
- 0x69, 0x7a, 0x65, 0x42, 0x79, 0x74, 0x65, 0x73, 0x12, 0x24, 0x0a, 0x0e,
- 0x6d, 0x69, 0x6e, 0x5f, 0x73, 0x69, 0x7a, 0x65, 0x5f, 0x62, 0x79, 0x74,
- 0x65, 0x73, 0x18, 0x03, 0x20, 0x01, 0x28, 0x01, 0x52, 0x0c, 0x6d, 0x69,
- 0x6e, 0x53, 0x69, 0x7a, 0x65, 0x42, 0x79, 0x74, 0x65, 0x73, 0x12, 0x24,
- 0x0a, 0x0e, 0x6d, 0x61, 0x78, 0x5f, 0x73, 0x69, 0x7a, 0x65, 0x5f, 0x62,
- 0x79, 0x74, 0x65, 0x73, 0x18, 0x04, 0x20, 0x01, 0x28, 0x01, 0x52, 0x0c,
- 0x6d, 0x61, 0x78, 0x53, 0x69, 0x7a, 0x65, 0x42, 0x79, 0x74, 0x65, 0x73,
- 0x42, 0x02, 0x48, 0x03, 0x0a, 0x95, 0x02, 0x0a, 0x30, 0x70, 0x72, 0x6f,
- 0x74, 0x6f, 0x73, 0x2f, 0x70, 0x65, 0x72, 0x66, 0x65, 0x74, 0x74, 0x6f,
- 0x2f, 0x6d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x73, 0x2f, 0x61, 0x6e, 0x64,
- 0x72, 0x6f, 0x69, 0x64, 0x2f, 0x6c, 0x6d, 0x6b, 0x5f, 0x6d, 0x65, 0x74,
- 0x72, 0x69, 0x63, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x0f, 0x70,
- 0x65, 0x72, 0x66, 0x65, 0x74, 0x74, 0x6f, 0x2e, 0x70, 0x72, 0x6f, 0x74,
- 0x6f, 0x73, 0x22, 0xcb, 0x01, 0x0a, 0x10, 0x41, 0x6e, 0x64, 0x72, 0x6f,
- 0x69, 0x64, 0x4c, 0x6d, 0x6b, 0x4d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x12,
- 0x1f, 0x0a, 0x0b, 0x74, 0x6f, 0x74, 0x61, 0x6c, 0x5f, 0x63, 0x6f, 0x75,
- 0x6e, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x05, 0x52, 0x0a, 0x74, 0x6f,
- 0x74, 0x61, 0x6c, 0x43, 0x6f, 0x75, 0x6e, 0x74, 0x12, 0x4e, 0x0a, 0x0c,
- 0x62, 0x79, 0x5f, 0x6f, 0x6f, 0x6d, 0x5f, 0x73, 0x63, 0x6f, 0x72, 0x65,
- 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x2c, 0x2e, 0x70, 0x65, 0x72,
- 0x66, 0x65, 0x74, 0x74, 0x6f, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73,
- 0x2e, 0x41, 0x6e, 0x64, 0x72, 0x6f, 0x69, 0x64, 0x4c, 0x6d, 0x6b, 0x4d,
- 0x65, 0x74, 0x72, 0x69, 0x63, 0x2e, 0x42, 0x79, 0x4f, 0x6f, 0x6d, 0x53,
- 0x63, 0x6f, 0x72, 0x65, 0x52, 0x0a, 0x62, 0x79, 0x4f, 0x6f, 0x6d, 0x53,
- 0x63, 0x6f, 0x72, 0x65, 0x1a, 0x46, 0x0a, 0x0a, 0x42, 0x79, 0x4f, 0x6f,
- 0x6d, 0x53, 0x63, 0x6f, 0x72, 0x65, 0x12, 0x22, 0x0a, 0x0d, 0x6f, 0x6f,
- 0x6d, 0x5f, 0x73, 0x63, 0x6f, 0x72, 0x65, 0x5f, 0x61, 0x64, 0x6a, 0x18,
- 0x01, 0x20, 0x01, 0x28, 0x05, 0x52, 0x0b, 0x6f, 0x6f, 0x6d, 0x53, 0x63,
- 0x6f, 0x72, 0x65, 0x41, 0x64, 0x6a, 0x12, 0x14, 0x0a, 0x05, 0x63, 0x6f,
- 0x75, 0x6e, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x05, 0x52, 0x05, 0x63,
- 0x6f, 0x75, 0x6e, 0x74, 0x42, 0x02, 0x48, 0x03, 0x0a, 0xc4, 0x03, 0x0a,
+ 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x0a, 0xab, 0x02, 0x0a, 0x30, 0x70,
+ 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2f, 0x70, 0x65, 0x72, 0x66, 0x65, 0x74,
+ 0x74, 0x6f, 0x2f, 0x6d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x73, 0x2f, 0x61,
+ 0x6e, 0x64, 0x72, 0x6f, 0x69, 0x64, 0x2f, 0x69, 0x6f, 0x6e, 0x5f, 0x6d,
+ 0x65, 0x74, 0x72, 0x69, 0x63, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12,
+ 0x0f, 0x70, 0x65, 0x72, 0x66, 0x65, 0x74, 0x74, 0x6f, 0x2e, 0x70, 0x72,
+ 0x6f, 0x74, 0x6f, 0x73, 0x22, 0xe5, 0x01, 0x0a, 0x10, 0x41, 0x6e, 0x64,
+ 0x72, 0x6f, 0x69, 0x64, 0x49, 0x6f, 0x6e, 0x4d, 0x65, 0x74, 0x72, 0x69,
+ 0x63, 0x12, 0x40, 0x0a, 0x06, 0x62, 0x75, 0x66, 0x66, 0x65, 0x72, 0x18,
+ 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x28, 0x2e, 0x70, 0x65, 0x72, 0x66,
+ 0x65, 0x74, 0x74, 0x6f, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2e,
+ 0x41, 0x6e, 0x64, 0x72, 0x6f, 0x69, 0x64, 0x49, 0x6f, 0x6e, 0x4d, 0x65,
+ 0x74, 0x72, 0x69, 0x63, 0x2e, 0x42, 0x75, 0x66, 0x66, 0x65, 0x72, 0x52,
+ 0x06, 0x62, 0x75, 0x66, 0x66, 0x65, 0x72, 0x1a, 0x8e, 0x01, 0x0a, 0x06,
+ 0x42, 0x75, 0x66, 0x66, 0x65, 0x72, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61,
+ 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61,
+ 0x6d, 0x65, 0x12, 0x24, 0x0a, 0x0e, 0x61, 0x76, 0x67, 0x5f, 0x73, 0x69,
+ 0x7a, 0x65, 0x5f, 0x62, 0x79, 0x74, 0x65, 0x73, 0x18, 0x02, 0x20, 0x01,
+ 0x28, 0x01, 0x52, 0x0c, 0x61, 0x76, 0x67, 0x53, 0x69, 0x7a, 0x65, 0x42,
+ 0x79, 0x74, 0x65, 0x73, 0x12, 0x24, 0x0a, 0x0e, 0x6d, 0x69, 0x6e, 0x5f,
+ 0x73, 0x69, 0x7a, 0x65, 0x5f, 0x62, 0x79, 0x74, 0x65, 0x73, 0x18, 0x03,
+ 0x20, 0x01, 0x28, 0x01, 0x52, 0x0c, 0x6d, 0x69, 0x6e, 0x53, 0x69, 0x7a,
+ 0x65, 0x42, 0x79, 0x74, 0x65, 0x73, 0x12, 0x24, 0x0a, 0x0e, 0x6d, 0x61,
+ 0x78, 0x5f, 0x73, 0x69, 0x7a, 0x65, 0x5f, 0x62, 0x79, 0x74, 0x65, 0x73,
+ 0x18, 0x04, 0x20, 0x01, 0x28, 0x01, 0x52, 0x0c, 0x6d, 0x61, 0x78, 0x53,
+ 0x69, 0x7a, 0x65, 0x42, 0x79, 0x74, 0x65, 0x73, 0x0a, 0x91, 0x02, 0x0a,
+ 0x30, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2f, 0x70, 0x65, 0x72, 0x66,
+ 0x65, 0x74, 0x74, 0x6f, 0x2f, 0x6d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x73,
+ 0x2f, 0x61, 0x6e, 0x64, 0x72, 0x6f, 0x69, 0x64, 0x2f, 0x6c, 0x6d, 0x6b,
+ 0x5f, 0x6d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x2e, 0x70, 0x72, 0x6f, 0x74,
+ 0x6f, 0x12, 0x0f, 0x70, 0x65, 0x72, 0x66, 0x65, 0x74, 0x74, 0x6f, 0x2e,
+ 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x22, 0xcb, 0x01, 0x0a, 0x10, 0x41,
+ 0x6e, 0x64, 0x72, 0x6f, 0x69, 0x64, 0x4c, 0x6d, 0x6b, 0x4d, 0x65, 0x74,
+ 0x72, 0x69, 0x63, 0x12, 0x1f, 0x0a, 0x0b, 0x74, 0x6f, 0x74, 0x61, 0x6c,
+ 0x5f, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x05,
+ 0x52, 0x0a, 0x74, 0x6f, 0x74, 0x61, 0x6c, 0x43, 0x6f, 0x75, 0x6e, 0x74,
+ 0x12, 0x4e, 0x0a, 0x0c, 0x62, 0x79, 0x5f, 0x6f, 0x6f, 0x6d, 0x5f, 0x73,
+ 0x63, 0x6f, 0x72, 0x65, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x2c,
+ 0x2e, 0x70, 0x65, 0x72, 0x66, 0x65, 0x74, 0x74, 0x6f, 0x2e, 0x70, 0x72,
+ 0x6f, 0x74, 0x6f, 0x73, 0x2e, 0x41, 0x6e, 0x64, 0x72, 0x6f, 0x69, 0x64,
+ 0x4c, 0x6d, 0x6b, 0x4d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x2e, 0x42, 0x79,
+ 0x4f, 0x6f, 0x6d, 0x53, 0x63, 0x6f, 0x72, 0x65, 0x52, 0x0a, 0x62, 0x79,
+ 0x4f, 0x6f, 0x6d, 0x53, 0x63, 0x6f, 0x72, 0x65, 0x1a, 0x46, 0x0a, 0x0a,
+ 0x42, 0x79, 0x4f, 0x6f, 0x6d, 0x53, 0x63, 0x6f, 0x72, 0x65, 0x12, 0x22,
+ 0x0a, 0x0d, 0x6f, 0x6f, 0x6d, 0x5f, 0x73, 0x63, 0x6f, 0x72, 0x65, 0x5f,
+ 0x61, 0x64, 0x6a, 0x18, 0x01, 0x20, 0x01, 0x28, 0x05, 0x52, 0x0b, 0x6f,
+ 0x6f, 0x6d, 0x53, 0x63, 0x6f, 0x72, 0x65, 0x41, 0x64, 0x6a, 0x12, 0x14,
+ 0x0a, 0x05, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28,
+ 0x05, 0x52, 0x05, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x0a, 0xc0, 0x03, 0x0a,
0x36, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2f, 0x70, 0x65, 0x72, 0x66,
0x65, 0x74, 0x74, 0x6f, 0x2f, 0x6d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x73,
0x2f, 0x61, 0x6e, 0x64, 0x72, 0x6f, 0x69, 0x64, 0x2f, 0x70, 0x72, 0x6f,
@@ -391,83 +389,82 @@
0x01, 0x28, 0x08, 0x52, 0x0a, 0x64, 0x65, 0x62, 0x75, 0x67, 0x67, 0x61,
0x62, 0x6c, 0x65, 0x4a, 0x04, 0x08, 0x03, 0x10, 0x04, 0x4a, 0x04, 0x08,
0x04, 0x10, 0x05, 0x4a, 0x04, 0x08, 0x05, 0x10, 0x06, 0x4a, 0x04, 0x08,
- 0x06, 0x10, 0x07, 0x42, 0x02, 0x48, 0x03, 0x0a, 0x95, 0x04, 0x0a, 0x37,
- 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2f, 0x70, 0x65, 0x72, 0x66, 0x65,
- 0x74, 0x74, 0x6f, 0x2f, 0x6d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x73, 0x2f,
- 0x61, 0x6e, 0x64, 0x72, 0x6f, 0x69, 0x64, 0x2f, 0x6c, 0x6d, 0x6b, 0x5f,
- 0x72, 0x65, 0x61, 0x73, 0x6f, 0x6e, 0x5f, 0x6d, 0x65, 0x74, 0x72, 0x69,
- 0x63, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x0f, 0x70, 0x65, 0x72,
- 0x66, 0x65, 0x74, 0x74, 0x6f, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73,
- 0x1a, 0x36, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2f, 0x70, 0x65, 0x72,
- 0x66, 0x65, 0x74, 0x74, 0x6f, 0x2f, 0x6d, 0x65, 0x74, 0x72, 0x69, 0x63,
- 0x73, 0x2f, 0x61, 0x6e, 0x64, 0x72, 0x6f, 0x69, 0x64, 0x2f, 0x70, 0x72,
- 0x6f, 0x63, 0x65, 0x73, 0x73, 0x5f, 0x6d, 0x65, 0x74, 0x61, 0x64, 0x61,
- 0x74, 0x61, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x22, 0x8c, 0x03, 0x0a,
- 0x16, 0x41, 0x6e, 0x64, 0x72, 0x6f, 0x69, 0x64, 0x4c, 0x6d, 0x6b, 0x52,
- 0x65, 0x61, 0x73, 0x6f, 0x6e, 0x4d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x12,
- 0x3f, 0x0a, 0x04, 0x6c, 0x6d, 0x6b, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28,
- 0x0b, 0x32, 0x2b, 0x2e, 0x70, 0x65, 0x72, 0x66, 0x65, 0x74, 0x74, 0x6f,
- 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2e, 0x41, 0x6e, 0x64, 0x72,
- 0x6f, 0x69, 0x64, 0x4c, 0x6d, 0x6b, 0x52, 0x65, 0x61, 0x73, 0x6f, 0x6e,
- 0x4d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x2e, 0x4c, 0x6d, 0x6b, 0x52, 0x04,
- 0x6c, 0x6d, 0x6b, 0x73, 0x1a, 0x84, 0x01, 0x0a, 0x07, 0x50, 0x72, 0x6f,
- 0x63, 0x65, 0x73, 0x73, 0x12, 0x41, 0x0a, 0x07, 0x70, 0x72, 0x6f, 0x63,
- 0x65, 0x73, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x27, 0x2e,
- 0x70, 0x65, 0x72, 0x66, 0x65, 0x74, 0x74, 0x6f, 0x2e, 0x70, 0x72, 0x6f,
- 0x74, 0x6f, 0x73, 0x2e, 0x41, 0x6e, 0x64, 0x72, 0x6f, 0x69, 0x64, 0x50,
- 0x72, 0x6f, 0x63, 0x65, 0x73, 0x73, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61,
- 0x74, 0x61, 0x52, 0x07, 0x70, 0x72, 0x6f, 0x63, 0x65, 0x73, 0x73, 0x12,
- 0x22, 0x0a, 0x0d, 0x6f, 0x6f, 0x6d, 0x5f, 0x73, 0x63, 0x6f, 0x72, 0x65,
- 0x5f, 0x61, 0x64, 0x6a, 0x18, 0x02, 0x20, 0x01, 0x28, 0x05, 0x52, 0x0b,
- 0x6f, 0x6f, 0x6d, 0x53, 0x63, 0x6f, 0x72, 0x65, 0x41, 0x64, 0x6a, 0x12,
- 0x12, 0x0a, 0x04, 0x73, 0x69, 0x7a, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28,
- 0x03, 0x52, 0x04, 0x73, 0x69, 0x7a, 0x65, 0x1a, 0xa9, 0x01, 0x0a, 0x03,
- 0x4c, 0x6d, 0x6b, 0x12, 0x22, 0x0a, 0x0d, 0x6f, 0x6f, 0x6d, 0x5f, 0x73,
- 0x63, 0x6f, 0x72, 0x65, 0x5f, 0x61, 0x64, 0x6a, 0x18, 0x01, 0x20, 0x01,
- 0x28, 0x05, 0x52, 0x0b, 0x6f, 0x6f, 0x6d, 0x53, 0x63, 0x6f, 0x72, 0x65,
- 0x41, 0x64, 0x6a, 0x12, 0x2f, 0x0a, 0x14, 0x73, 0x79, 0x73, 0x74, 0x65,
- 0x6d, 0x5f, 0x69, 0x6f, 0x6e, 0x5f, 0x68, 0x65, 0x61, 0x70, 0x5f, 0x73,
- 0x69, 0x7a, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x03, 0x52, 0x11, 0x73,
- 0x79, 0x73, 0x74, 0x65, 0x6d, 0x49, 0x6f, 0x6e, 0x48, 0x65, 0x61, 0x70,
- 0x53, 0x69, 0x7a, 0x65, 0x12, 0x4d, 0x0a, 0x09, 0x70, 0x72, 0x6f, 0x63,
- 0x65, 0x73, 0x73, 0x65, 0x73, 0x18, 0x03, 0x20, 0x03, 0x28, 0x0b, 0x32,
- 0x2f, 0x2e, 0x70, 0x65, 0x72, 0x66, 0x65, 0x74, 0x74, 0x6f, 0x2e, 0x70,
- 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2e, 0x41, 0x6e, 0x64, 0x72, 0x6f, 0x69,
- 0x64, 0x4c, 0x6d, 0x6b, 0x52, 0x65, 0x61, 0x73, 0x6f, 0x6e, 0x4d, 0x65,
- 0x74, 0x72, 0x69, 0x63, 0x2e, 0x50, 0x72, 0x6f, 0x63, 0x65, 0x73, 0x73,
- 0x52, 0x09, 0x70, 0x72, 0x6f, 0x63, 0x65, 0x73, 0x73, 0x65, 0x73, 0x42,
- 0x02, 0x48, 0x03, 0x0a, 0xf4, 0x02, 0x0a, 0x35, 0x70, 0x72, 0x6f, 0x74,
+ 0x06, 0x10, 0x07, 0x0a, 0x91, 0x04, 0x0a, 0x37, 0x70, 0x72, 0x6f, 0x74,
0x6f, 0x73, 0x2f, 0x70, 0x65, 0x72, 0x66, 0x65, 0x74, 0x74, 0x6f, 0x2f,
0x6d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x73, 0x2f, 0x61, 0x6e, 0x64, 0x72,
- 0x6f, 0x69, 0x64, 0x2f, 0x70, 0x6f, 0x77, 0x72, 0x61, 0x69, 0x6c, 0x73,
- 0x5f, 0x6d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x2e, 0x70, 0x72, 0x6f, 0x74,
- 0x6f, 0x12, 0x0f, 0x70, 0x65, 0x72, 0x66, 0x65, 0x74, 0x74, 0x6f, 0x2e,
- 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x22, 0xa5, 0x02, 0x0a, 0x11, 0x41,
- 0x6e, 0x64, 0x72, 0x6f, 0x69, 0x64, 0x50, 0x6f, 0x77, 0x65, 0x72, 0x52,
- 0x61, 0x69, 0x6c, 0x73, 0x12, 0x4e, 0x0a, 0x0b, 0x70, 0x6f, 0x77, 0x65,
- 0x72, 0x5f, 0x72, 0x61, 0x69, 0x6c, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28,
- 0x0b, 0x32, 0x2d, 0x2e, 0x70, 0x65, 0x72, 0x66, 0x65, 0x74, 0x74, 0x6f,
- 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2e, 0x41, 0x6e, 0x64, 0x72,
- 0x6f, 0x69, 0x64, 0x50, 0x6f, 0x77, 0x65, 0x72, 0x52, 0x61, 0x69, 0x6c,
- 0x73, 0x2e, 0x50, 0x6f, 0x77, 0x65, 0x72, 0x52, 0x61, 0x69, 0x6c, 0x73,
- 0x52, 0x0a, 0x70, 0x6f, 0x77, 0x65, 0x72, 0x52, 0x61, 0x69, 0x6c, 0x73,
- 0x1a, 0x4e, 0x0a, 0x0a, 0x45, 0x6e, 0x65, 0x72, 0x67, 0x79, 0x44, 0x61,
- 0x74, 0x61, 0x12, 0x21, 0x0a, 0x0c, 0x74, 0x69, 0x6d, 0x65, 0x73, 0x74,
- 0x61, 0x6d, 0x70, 0x5f, 0x6d, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x03,
- 0x52, 0x0b, 0x74, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x4d,
- 0x73, 0x12, 0x1d, 0x0a, 0x0a, 0x65, 0x6e, 0x65, 0x72, 0x67, 0x79, 0x5f,
- 0x75, 0x77, 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x01, 0x52, 0x09, 0x65,
- 0x6e, 0x65, 0x72, 0x67, 0x79, 0x55, 0x77, 0x73, 0x1a, 0x70, 0x0a, 0x0a,
- 0x50, 0x6f, 0x77, 0x65, 0x72, 0x52, 0x61, 0x69, 0x6c, 0x73, 0x12, 0x12,
- 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09,
- 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x4e, 0x0a, 0x0b, 0x65, 0x6e,
- 0x65, 0x72, 0x67, 0x79, 0x5f, 0x64, 0x61, 0x74, 0x61, 0x18, 0x02, 0x20,
- 0x03, 0x28, 0x0b, 0x32, 0x2d, 0x2e, 0x70, 0x65, 0x72, 0x66, 0x65, 0x74,
- 0x74, 0x6f, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2e, 0x41, 0x6e,
- 0x64, 0x72, 0x6f, 0x69, 0x64, 0x50, 0x6f, 0x77, 0x65, 0x72, 0x52, 0x61,
- 0x69, 0x6c, 0x73, 0x2e, 0x45, 0x6e, 0x65, 0x72, 0x67, 0x79, 0x44, 0x61,
- 0x74, 0x61, 0x52, 0x0a, 0x65, 0x6e, 0x65, 0x72, 0x67, 0x79, 0x44, 0x61,
- 0x74, 0x61, 0x42, 0x02, 0x48, 0x03, 0x0a, 0xac, 0x0e, 0x0a, 0x34, 0x70,
+ 0x6f, 0x69, 0x64, 0x2f, 0x6c, 0x6d, 0x6b, 0x5f, 0x72, 0x65, 0x61, 0x73,
+ 0x6f, 0x6e, 0x5f, 0x6d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x2e, 0x70, 0x72,
+ 0x6f, 0x74, 0x6f, 0x12, 0x0f, 0x70, 0x65, 0x72, 0x66, 0x65, 0x74, 0x74,
+ 0x6f, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x1a, 0x36, 0x70, 0x72,
+ 0x6f, 0x74, 0x6f, 0x73, 0x2f, 0x70, 0x65, 0x72, 0x66, 0x65, 0x74, 0x74,
+ 0x6f, 0x2f, 0x6d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x73, 0x2f, 0x61, 0x6e,
+ 0x64, 0x72, 0x6f, 0x69, 0x64, 0x2f, 0x70, 0x72, 0x6f, 0x63, 0x65, 0x73,
+ 0x73, 0x5f, 0x6d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x2e, 0x70,
+ 0x72, 0x6f, 0x74, 0x6f, 0x22, 0x8c, 0x03, 0x0a, 0x16, 0x41, 0x6e, 0x64,
+ 0x72, 0x6f, 0x69, 0x64, 0x4c, 0x6d, 0x6b, 0x52, 0x65, 0x61, 0x73, 0x6f,
+ 0x6e, 0x4d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x12, 0x3f, 0x0a, 0x04, 0x6c,
+ 0x6d, 0x6b, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x2b, 0x2e,
+ 0x70, 0x65, 0x72, 0x66, 0x65, 0x74, 0x74, 0x6f, 0x2e, 0x70, 0x72, 0x6f,
+ 0x74, 0x6f, 0x73, 0x2e, 0x41, 0x6e, 0x64, 0x72, 0x6f, 0x69, 0x64, 0x4c,
+ 0x6d, 0x6b, 0x52, 0x65, 0x61, 0x73, 0x6f, 0x6e, 0x4d, 0x65, 0x74, 0x72,
+ 0x69, 0x63, 0x2e, 0x4c, 0x6d, 0x6b, 0x52, 0x04, 0x6c, 0x6d, 0x6b, 0x73,
+ 0x1a, 0x84, 0x01, 0x0a, 0x07, 0x50, 0x72, 0x6f, 0x63, 0x65, 0x73, 0x73,
+ 0x12, 0x41, 0x0a, 0x07, 0x70, 0x72, 0x6f, 0x63, 0x65, 0x73, 0x73, 0x18,
+ 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x27, 0x2e, 0x70, 0x65, 0x72, 0x66,
+ 0x65, 0x74, 0x74, 0x6f, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2e,
+ 0x41, 0x6e, 0x64, 0x72, 0x6f, 0x69, 0x64, 0x50, 0x72, 0x6f, 0x63, 0x65,
+ 0x73, 0x73, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x52, 0x07,
+ 0x70, 0x72, 0x6f, 0x63, 0x65, 0x73, 0x73, 0x12, 0x22, 0x0a, 0x0d, 0x6f,
+ 0x6f, 0x6d, 0x5f, 0x73, 0x63, 0x6f, 0x72, 0x65, 0x5f, 0x61, 0x64, 0x6a,
+ 0x18, 0x02, 0x20, 0x01, 0x28, 0x05, 0x52, 0x0b, 0x6f, 0x6f, 0x6d, 0x53,
+ 0x63, 0x6f, 0x72, 0x65, 0x41, 0x64, 0x6a, 0x12, 0x12, 0x0a, 0x04, 0x73,
+ 0x69, 0x7a, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x03, 0x52, 0x04, 0x73,
+ 0x69, 0x7a, 0x65, 0x1a, 0xa9, 0x01, 0x0a, 0x03, 0x4c, 0x6d, 0x6b, 0x12,
+ 0x22, 0x0a, 0x0d, 0x6f, 0x6f, 0x6d, 0x5f, 0x73, 0x63, 0x6f, 0x72, 0x65,
+ 0x5f, 0x61, 0x64, 0x6a, 0x18, 0x01, 0x20, 0x01, 0x28, 0x05, 0x52, 0x0b,
+ 0x6f, 0x6f, 0x6d, 0x53, 0x63, 0x6f, 0x72, 0x65, 0x41, 0x64, 0x6a, 0x12,
+ 0x2f, 0x0a, 0x14, 0x73, 0x79, 0x73, 0x74, 0x65, 0x6d, 0x5f, 0x69, 0x6f,
+ 0x6e, 0x5f, 0x68, 0x65, 0x61, 0x70, 0x5f, 0x73, 0x69, 0x7a, 0x65, 0x18,
+ 0x02, 0x20, 0x01, 0x28, 0x03, 0x52, 0x11, 0x73, 0x79, 0x73, 0x74, 0x65,
+ 0x6d, 0x49, 0x6f, 0x6e, 0x48, 0x65, 0x61, 0x70, 0x53, 0x69, 0x7a, 0x65,
+ 0x12, 0x4d, 0x0a, 0x09, 0x70, 0x72, 0x6f, 0x63, 0x65, 0x73, 0x73, 0x65,
+ 0x73, 0x18, 0x03, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x2f, 0x2e, 0x70, 0x65,
+ 0x72, 0x66, 0x65, 0x74, 0x74, 0x6f, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f,
+ 0x73, 0x2e, 0x41, 0x6e, 0x64, 0x72, 0x6f, 0x69, 0x64, 0x4c, 0x6d, 0x6b,
+ 0x52, 0x65, 0x61, 0x73, 0x6f, 0x6e, 0x4d, 0x65, 0x74, 0x72, 0x69, 0x63,
+ 0x2e, 0x50, 0x72, 0x6f, 0x63, 0x65, 0x73, 0x73, 0x52, 0x09, 0x70, 0x72,
+ 0x6f, 0x63, 0x65, 0x73, 0x73, 0x65, 0x73, 0x0a, 0xf0, 0x02, 0x0a, 0x35,
+ 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2f, 0x70, 0x65, 0x72, 0x66, 0x65,
+ 0x74, 0x74, 0x6f, 0x2f, 0x6d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x73, 0x2f,
+ 0x61, 0x6e, 0x64, 0x72, 0x6f, 0x69, 0x64, 0x2f, 0x70, 0x6f, 0x77, 0x72,
+ 0x61, 0x69, 0x6c, 0x73, 0x5f, 0x6d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x2e,
+ 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x0f, 0x70, 0x65, 0x72, 0x66, 0x65,
+ 0x74, 0x74, 0x6f, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x22, 0xa5,
+ 0x02, 0x0a, 0x11, 0x41, 0x6e, 0x64, 0x72, 0x6f, 0x69, 0x64, 0x50, 0x6f,
+ 0x77, 0x65, 0x72, 0x52, 0x61, 0x69, 0x6c, 0x73, 0x12, 0x4e, 0x0a, 0x0b,
+ 0x70, 0x6f, 0x77, 0x65, 0x72, 0x5f, 0x72, 0x61, 0x69, 0x6c, 0x73, 0x18,
+ 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x2d, 0x2e, 0x70, 0x65, 0x72, 0x66,
+ 0x65, 0x74, 0x74, 0x6f, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2e,
+ 0x41, 0x6e, 0x64, 0x72, 0x6f, 0x69, 0x64, 0x50, 0x6f, 0x77, 0x65, 0x72,
+ 0x52, 0x61, 0x69, 0x6c, 0x73, 0x2e, 0x50, 0x6f, 0x77, 0x65, 0x72, 0x52,
+ 0x61, 0x69, 0x6c, 0x73, 0x52, 0x0a, 0x70, 0x6f, 0x77, 0x65, 0x72, 0x52,
+ 0x61, 0x69, 0x6c, 0x73, 0x1a, 0x4e, 0x0a, 0x0a, 0x45, 0x6e, 0x65, 0x72,
+ 0x67, 0x79, 0x44, 0x61, 0x74, 0x61, 0x12, 0x21, 0x0a, 0x0c, 0x74, 0x69,
+ 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x5f, 0x6d, 0x73, 0x18, 0x01,
+ 0x20, 0x01, 0x28, 0x03, 0x52, 0x0b, 0x74, 0x69, 0x6d, 0x65, 0x73, 0x74,
+ 0x61, 0x6d, 0x70, 0x4d, 0x73, 0x12, 0x1d, 0x0a, 0x0a, 0x65, 0x6e, 0x65,
+ 0x72, 0x67, 0x79, 0x5f, 0x75, 0x77, 0x73, 0x18, 0x02, 0x20, 0x01, 0x28,
+ 0x01, 0x52, 0x09, 0x65, 0x6e, 0x65, 0x72, 0x67, 0x79, 0x55, 0x77, 0x73,
+ 0x1a, 0x70, 0x0a, 0x0a, 0x50, 0x6f, 0x77, 0x65, 0x72, 0x52, 0x61, 0x69,
+ 0x6c, 0x73, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01,
+ 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x4e,
+ 0x0a, 0x0b, 0x65, 0x6e, 0x65, 0x72, 0x67, 0x79, 0x5f, 0x64, 0x61, 0x74,
+ 0x61, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x2d, 0x2e, 0x70, 0x65,
+ 0x72, 0x66, 0x65, 0x74, 0x74, 0x6f, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f,
+ 0x73, 0x2e, 0x41, 0x6e, 0x64, 0x72, 0x6f, 0x69, 0x64, 0x50, 0x6f, 0x77,
+ 0x65, 0x72, 0x52, 0x61, 0x69, 0x6c, 0x73, 0x2e, 0x45, 0x6e, 0x65, 0x72,
+ 0x67, 0x79, 0x44, 0x61, 0x74, 0x61, 0x52, 0x0a, 0x65, 0x6e, 0x65, 0x72,
+ 0x67, 0x79, 0x44, 0x61, 0x74, 0x61, 0x0a, 0xa8, 0x0e, 0x0a, 0x34, 0x70,
0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2f, 0x70, 0x65, 0x72, 0x66, 0x65, 0x74,
0x74, 0x6f, 0x2f, 0x6d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x73, 0x2f, 0x61,
0x6e, 0x64, 0x72, 0x6f, 0x69, 0x64, 0x2f, 0x73, 0x74, 0x61, 0x72, 0x74,
@@ -620,268 +617,431 @@
0x64, 0x53, 0x74, 0x61, 0x72, 0x74, 0x75, 0x70, 0x4d, 0x65, 0x74, 0x72,
0x69, 0x63, 0x2e, 0x54, 0x6f, 0x46, 0x69, 0x72, 0x73, 0x74, 0x46, 0x72,
0x61, 0x6d, 0x65, 0x52, 0x0c, 0x74, 0x6f, 0x46, 0x69, 0x72, 0x73, 0x74,
- 0x46, 0x72, 0x61, 0x6d, 0x65, 0x42, 0x02, 0x48, 0x03, 0x0a, 0xb2, 0x08,
- 0x0a, 0x3c, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2f, 0x70, 0x65, 0x72,
- 0x66, 0x65, 0x74, 0x74, 0x6f, 0x2f, 0x6d, 0x65, 0x74, 0x72, 0x69, 0x63,
- 0x73, 0x2f, 0x61, 0x6e, 0x64, 0x72, 0x6f, 0x69, 0x64, 0x2f, 0x68, 0x65,
- 0x61, 0x70, 0x5f, 0x70, 0x72, 0x6f, 0x66, 0x69, 0x6c, 0x65, 0x5f, 0x63,
- 0x61, 0x6c, 0x6c, 0x73, 0x69, 0x74, 0x65, 0x73, 0x2e, 0x70, 0x72, 0x6f,
+ 0x46, 0x72, 0x61, 0x6d, 0x65, 0x0a, 0xae, 0x08, 0x0a, 0x3c, 0x70, 0x72,
+ 0x6f, 0x74, 0x6f, 0x73, 0x2f, 0x70, 0x65, 0x72, 0x66, 0x65, 0x74, 0x74,
+ 0x6f, 0x2f, 0x6d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x73, 0x2f, 0x61, 0x6e,
+ 0x64, 0x72, 0x6f, 0x69, 0x64, 0x2f, 0x68, 0x65, 0x61, 0x70, 0x5f, 0x70,
+ 0x72, 0x6f, 0x66, 0x69, 0x6c, 0x65, 0x5f, 0x63, 0x61, 0x6c, 0x6c, 0x73,
+ 0x69, 0x74, 0x65, 0x73, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x0f,
+ 0x70, 0x65, 0x72, 0x66, 0x65, 0x74, 0x74, 0x6f, 0x2e, 0x70, 0x72, 0x6f,
+ 0x74, 0x6f, 0x73, 0x1a, 0x36, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2f,
+ 0x70, 0x65, 0x72, 0x66, 0x65, 0x74, 0x74, 0x6f, 0x2f, 0x6d, 0x65, 0x74,
+ 0x72, 0x69, 0x63, 0x73, 0x2f, 0x61, 0x6e, 0x64, 0x72, 0x6f, 0x69, 0x64,
+ 0x2f, 0x70, 0x72, 0x6f, 0x63, 0x65, 0x73, 0x73, 0x5f, 0x6d, 0x65, 0x74,
+ 0x61, 0x64, 0x61, 0x74, 0x61, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x22,
+ 0xa4, 0x07, 0x0a, 0x14, 0x48, 0x65, 0x61, 0x70, 0x50, 0x72, 0x6f, 0x66,
+ 0x69, 0x6c, 0x65, 0x43, 0x61, 0x6c, 0x6c, 0x73, 0x69, 0x74, 0x65, 0x73,
+ 0x12, 0x5a, 0x0a, 0x0e, 0x69, 0x6e, 0x73, 0x74, 0x61, 0x6e, 0x63, 0x65,
+ 0x5f, 0x73, 0x74, 0x61, 0x74, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b,
+ 0x32, 0x33, 0x2e, 0x70, 0x65, 0x72, 0x66, 0x65, 0x74, 0x74, 0x6f, 0x2e,
+ 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2e, 0x48, 0x65, 0x61, 0x70, 0x50,
+ 0x72, 0x6f, 0x66, 0x69, 0x6c, 0x65, 0x43, 0x61, 0x6c, 0x6c, 0x73, 0x69,
+ 0x74, 0x65, 0x73, 0x2e, 0x49, 0x6e, 0x73, 0x74, 0x61, 0x6e, 0x63, 0x65,
+ 0x53, 0x74, 0x61, 0x74, 0x73, 0x52, 0x0d, 0x69, 0x6e, 0x73, 0x74, 0x61,
+ 0x6e, 0x63, 0x65, 0x53, 0x74, 0x61, 0x74, 0x73, 0x1a, 0x3e, 0x0a, 0x05,
+ 0x46, 0x72, 0x61, 0x6d, 0x65, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d,
+ 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d,
+ 0x65, 0x12, 0x21, 0x0a, 0x0c, 0x6d, 0x61, 0x70, 0x70, 0x69, 0x6e, 0x67,
+ 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52,
+ 0x0b, 0x6d, 0x61, 0x70, 0x70, 0x69, 0x6e, 0x67, 0x4e, 0x61, 0x6d, 0x65,
+ 0x1a, 0x8e, 0x01, 0x0a, 0x08, 0x43, 0x6f, 0x75, 0x6e, 0x74, 0x65, 0x72,
+ 0x73, 0x12, 0x1f, 0x0a, 0x0b, 0x74, 0x6f, 0x74, 0x61, 0x6c, 0x5f, 0x63,
+ 0x6f, 0x75, 0x6e, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0a,
+ 0x74, 0x6f, 0x74, 0x61, 0x6c, 0x43, 0x6f, 0x75, 0x6e, 0x74, 0x12, 0x1f,
+ 0x0a, 0x0b, 0x74, 0x6f, 0x74, 0x61, 0x6c, 0x5f, 0x62, 0x79, 0x74, 0x65,
+ 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0a, 0x74, 0x6f, 0x74,
+ 0x61, 0x6c, 0x42, 0x79, 0x74, 0x65, 0x73, 0x12, 0x1f, 0x0a, 0x0b, 0x64,
+ 0x65, 0x6c, 0x74, 0x61, 0x5f, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x18, 0x03,
+ 0x20, 0x01, 0x28, 0x03, 0x52, 0x0a, 0x64, 0x65, 0x6c, 0x74, 0x61, 0x43,
+ 0x6f, 0x75, 0x6e, 0x74, 0x12, 0x1f, 0x0a, 0x0b, 0x64, 0x65, 0x6c, 0x74,
+ 0x61, 0x5f, 0x62, 0x79, 0x74, 0x65, 0x73, 0x18, 0x04, 0x20, 0x01, 0x28,
+ 0x03, 0x52, 0x0a, 0x64, 0x65, 0x6c, 0x74, 0x61, 0x42, 0x79, 0x74, 0x65,
+ 0x73, 0x1a, 0xa6, 0x02, 0x0a, 0x08, 0x43, 0x61, 0x6c, 0x6c, 0x73, 0x69,
+ 0x74, 0x65, 0x12, 0x12, 0x0a, 0x04, 0x68, 0x61, 0x73, 0x68, 0x18, 0x01,
+ 0x20, 0x01, 0x28, 0x03, 0x52, 0x04, 0x68, 0x61, 0x73, 0x68, 0x12, 0x1f,
+ 0x0a, 0x0b, 0x70, 0x61, 0x72, 0x65, 0x6e, 0x74, 0x5f, 0x68, 0x61, 0x73,
+ 0x68, 0x18, 0x02, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0a, 0x70, 0x61, 0x72,
+ 0x65, 0x6e, 0x74, 0x48, 0x61, 0x73, 0x68, 0x12, 0x41, 0x0a, 0x05, 0x66,
+ 0x72, 0x61, 0x6d, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2b,
+ 0x2e, 0x70, 0x65, 0x72, 0x66, 0x65, 0x74, 0x74, 0x6f, 0x2e, 0x70, 0x72,
+ 0x6f, 0x74, 0x6f, 0x73, 0x2e, 0x48, 0x65, 0x61, 0x70, 0x50, 0x72, 0x6f,
+ 0x66, 0x69, 0x6c, 0x65, 0x43, 0x61, 0x6c, 0x6c, 0x73, 0x69, 0x74, 0x65,
+ 0x73, 0x2e, 0x46, 0x72, 0x61, 0x6d, 0x65, 0x52, 0x05, 0x66, 0x72, 0x61,
+ 0x6d, 0x65, 0x12, 0x4f, 0x0a, 0x0b, 0x73, 0x65, 0x6c, 0x66, 0x5f, 0x61,
+ 0x6c, 0x6c, 0x6f, 0x63, 0x73, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32,
+ 0x2e, 0x2e, 0x70, 0x65, 0x72, 0x66, 0x65, 0x74, 0x74, 0x6f, 0x2e, 0x70,
+ 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2e, 0x48, 0x65, 0x61, 0x70, 0x50, 0x72,
+ 0x6f, 0x66, 0x69, 0x6c, 0x65, 0x43, 0x61, 0x6c, 0x6c, 0x73, 0x69, 0x74,
+ 0x65, 0x73, 0x2e, 0x43, 0x6f, 0x75, 0x6e, 0x74, 0x65, 0x72, 0x73, 0x52,
+ 0x0a, 0x73, 0x65, 0x6c, 0x66, 0x41, 0x6c, 0x6c, 0x6f, 0x63, 0x73, 0x12,
+ 0x51, 0x0a, 0x0c, 0x63, 0x68, 0x69, 0x6c, 0x64, 0x5f, 0x61, 0x6c, 0x6c,
+ 0x6f, 0x63, 0x73, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2e, 0x2e,
+ 0x70, 0x65, 0x72, 0x66, 0x65, 0x74, 0x74, 0x6f, 0x2e, 0x70, 0x72, 0x6f,
+ 0x74, 0x6f, 0x73, 0x2e, 0x48, 0x65, 0x61, 0x70, 0x50, 0x72, 0x6f, 0x66,
+ 0x69, 0x6c, 0x65, 0x43, 0x61, 0x6c, 0x6c, 0x73, 0x69, 0x74, 0x65, 0x73,
+ 0x2e, 0x43, 0x6f, 0x75, 0x6e, 0x74, 0x65, 0x72, 0x73, 0x52, 0x0b, 0x63,
+ 0x68, 0x69, 0x6c, 0x64, 0x41, 0x6c, 0x6c, 0x6f, 0x63, 0x73, 0x1a, 0xb5,
+ 0x02, 0x0a, 0x0d, 0x49, 0x6e, 0x73, 0x74, 0x61, 0x6e, 0x63, 0x65, 0x53,
+ 0x74, 0x61, 0x74, 0x73, 0x12, 0x10, 0x0a, 0x03, 0x70, 0x69, 0x64, 0x18,
+ 0x01, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x03, 0x70, 0x69, 0x64, 0x12, 0x21,
+ 0x0a, 0x0c, 0x70, 0x72, 0x6f, 0x63, 0x65, 0x73, 0x73, 0x5f, 0x6e, 0x61,
+ 0x6d, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x70, 0x72,
+ 0x6f, 0x63, 0x65, 0x73, 0x73, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x41, 0x0a,
+ 0x07, 0x70, 0x72, 0x6f, 0x63, 0x65, 0x73, 0x73, 0x18, 0x06, 0x20, 0x01,
+ 0x28, 0x0b, 0x32, 0x27, 0x2e, 0x70, 0x65, 0x72, 0x66, 0x65, 0x74, 0x74,
+ 0x6f, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2e, 0x41, 0x6e, 0x64,
+ 0x72, 0x6f, 0x69, 0x64, 0x50, 0x72, 0x6f, 0x63, 0x65, 0x73, 0x73, 0x4d,
+ 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x52, 0x07, 0x70, 0x72, 0x6f,
+ 0x63, 0x65, 0x73, 0x73, 0x12, 0x4c, 0x0a, 0x09, 0x63, 0x61, 0x6c, 0x6c,
+ 0x73, 0x69, 0x74, 0x65, 0x73, 0x18, 0x03, 0x20, 0x03, 0x28, 0x0b, 0x32,
+ 0x2e, 0x2e, 0x70, 0x65, 0x72, 0x66, 0x65, 0x74, 0x74, 0x6f, 0x2e, 0x70,
+ 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2e, 0x48, 0x65, 0x61, 0x70, 0x50, 0x72,
+ 0x6f, 0x66, 0x69, 0x6c, 0x65, 0x43, 0x61, 0x6c, 0x6c, 0x73, 0x69, 0x74,
+ 0x65, 0x73, 0x2e, 0x43, 0x61, 0x6c, 0x6c, 0x73, 0x69, 0x74, 0x65, 0x52,
+ 0x09, 0x63, 0x61, 0x6c, 0x6c, 0x73, 0x69, 0x74, 0x65, 0x73, 0x12, 0x2e,
+ 0x0a, 0x13, 0x70, 0x72, 0x6f, 0x66, 0x69, 0x6c, 0x65, 0x5f, 0x64, 0x65,
+ 0x6c, 0x74, 0x61, 0x5f, 0x62, 0x79, 0x74, 0x65, 0x73, 0x18, 0x04, 0x20,
+ 0x01, 0x28, 0x03, 0x52, 0x11, 0x70, 0x72, 0x6f, 0x66, 0x69, 0x6c, 0x65,
+ 0x44, 0x65, 0x6c, 0x74, 0x61, 0x42, 0x79, 0x74, 0x65, 0x73, 0x12, 0x2e,
+ 0x0a, 0x13, 0x70, 0x72, 0x6f, 0x66, 0x69, 0x6c, 0x65, 0x5f, 0x74, 0x6f,
+ 0x74, 0x61, 0x6c, 0x5f, 0x62, 0x79, 0x74, 0x65, 0x73, 0x18, 0x05, 0x20,
+ 0x01, 0x28, 0x03, 0x52, 0x11, 0x70, 0x72, 0x6f, 0x66, 0x69, 0x6c, 0x65,
+ 0x54, 0x6f, 0x74, 0x61, 0x6c, 0x42, 0x79, 0x74, 0x65, 0x73, 0x0a, 0x86,
+ 0x0f, 0x0a, 0x31, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2f, 0x70, 0x65,
+ 0x72, 0x66, 0x65, 0x74, 0x74, 0x6f, 0x2f, 0x6d, 0x65, 0x74, 0x72, 0x69,
+ 0x63, 0x73, 0x2f, 0x61, 0x6e, 0x64, 0x72, 0x6f, 0x69, 0x64, 0x2f, 0x68,
+ 0x77, 0x75, 0x69, 0x5f, 0x6d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x2e, 0x70,
+ 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x0f, 0x70, 0x65, 0x72, 0x66, 0x65, 0x74,
+ 0x74, 0x6f, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x22, 0xe3, 0x0d,
+ 0x0a, 0x11, 0x50, 0x72, 0x6f, 0x63, 0x65, 0x73, 0x73, 0x52, 0x65, 0x6e,
+ 0x64, 0x65, 0x72, 0x49, 0x6e, 0x66, 0x6f, 0x12, 0x21, 0x0a, 0x0c, 0x70,
+ 0x72, 0x6f, 0x63, 0x65, 0x73, 0x73, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x18,
+ 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x70, 0x72, 0x6f, 0x63, 0x65,
+ 0x73, 0x73, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x23, 0x0a, 0x0e, 0x72, 0x74,
+ 0x5f, 0x63, 0x70, 0x75, 0x5f, 0x74, 0x69, 0x6d, 0x65, 0x5f, 0x6d, 0x73,
+ 0x18, 0x02, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0b, 0x72, 0x74, 0x43, 0x70,
+ 0x75, 0x54, 0x69, 0x6d, 0x65, 0x4d, 0x73, 0x12, 0x28, 0x0a, 0x10, 0x64,
+ 0x72, 0x61, 0x77, 0x5f, 0x66, 0x72, 0x61, 0x6d, 0x65, 0x5f, 0x63, 0x6f,
+ 0x75, 0x6e, 0x74, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x0e, 0x64,
+ 0x72, 0x61, 0x77, 0x46, 0x72, 0x61, 0x6d, 0x65, 0x43, 0x6f, 0x75, 0x6e,
+ 0x74, 0x12, 0x24, 0x0a, 0x0e, 0x64, 0x72, 0x61, 0x77, 0x5f, 0x66, 0x72,
+ 0x61, 0x6d, 0x65, 0x5f, 0x6d, 0x61, 0x78, 0x18, 0x04, 0x20, 0x01, 0x28,
+ 0x03, 0x52, 0x0c, 0x64, 0x72, 0x61, 0x77, 0x46, 0x72, 0x61, 0x6d, 0x65,
+ 0x4d, 0x61, 0x78, 0x12, 0x24, 0x0a, 0x0e, 0x64, 0x72, 0x61, 0x77, 0x5f,
+ 0x66, 0x72, 0x61, 0x6d, 0x65, 0x5f, 0x6d, 0x69, 0x6e, 0x18, 0x05, 0x20,
+ 0x01, 0x28, 0x03, 0x52, 0x0c, 0x64, 0x72, 0x61, 0x77, 0x46, 0x72, 0x61,
+ 0x6d, 0x65, 0x4d, 0x69, 0x6e, 0x12, 0x24, 0x0a, 0x0e, 0x64, 0x72, 0x61,
+ 0x77, 0x5f, 0x66, 0x72, 0x61, 0x6d, 0x65, 0x5f, 0x61, 0x76, 0x67, 0x18,
+ 0x06, 0x20, 0x01, 0x28, 0x01, 0x52, 0x0c, 0x64, 0x72, 0x61, 0x77, 0x46,
+ 0x72, 0x61, 0x6d, 0x65, 0x41, 0x76, 0x67, 0x12, 0x1f, 0x0a, 0x0b, 0x66,
+ 0x6c, 0x75, 0x73, 0x68, 0x5f, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x18, 0x07,
+ 0x20, 0x01, 0x28, 0x0d, 0x52, 0x0a, 0x66, 0x6c, 0x75, 0x73, 0x68, 0x43,
+ 0x6f, 0x75, 0x6e, 0x74, 0x12, 0x1b, 0x0a, 0x09, 0x66, 0x6c, 0x75, 0x73,
+ 0x68, 0x5f, 0x6d, 0x61, 0x78, 0x18, 0x08, 0x20, 0x01, 0x28, 0x03, 0x52,
+ 0x08, 0x66, 0x6c, 0x75, 0x73, 0x68, 0x4d, 0x61, 0x78, 0x12, 0x1b, 0x0a,
+ 0x09, 0x66, 0x6c, 0x75, 0x73, 0x68, 0x5f, 0x6d, 0x69, 0x6e, 0x18, 0x09,
+ 0x20, 0x01, 0x28, 0x03, 0x52, 0x08, 0x66, 0x6c, 0x75, 0x73, 0x68, 0x4d,
+ 0x69, 0x6e, 0x12, 0x1b, 0x0a, 0x09, 0x66, 0x6c, 0x75, 0x73, 0x68, 0x5f,
+ 0x61, 0x76, 0x67, 0x18, 0x0a, 0x20, 0x01, 0x28, 0x01, 0x52, 0x08, 0x66,
+ 0x6c, 0x75, 0x73, 0x68, 0x41, 0x76, 0x67, 0x12, 0x2c, 0x0a, 0x12, 0x70,
+ 0x72, 0x65, 0x70, 0x61, 0x72, 0x65, 0x5f, 0x74, 0x72, 0x65, 0x65, 0x5f,
+ 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x18, 0x0b, 0x20, 0x01, 0x28, 0x0d, 0x52,
+ 0x10, 0x70, 0x72, 0x65, 0x70, 0x61, 0x72, 0x65, 0x54, 0x72, 0x65, 0x65,
+ 0x43, 0x6f, 0x75, 0x6e, 0x74, 0x12, 0x28, 0x0a, 0x10, 0x70, 0x72, 0x65,
+ 0x70, 0x61, 0x72, 0x65, 0x5f, 0x74, 0x72, 0x65, 0x65, 0x5f, 0x6d, 0x61,
+ 0x78, 0x18, 0x0c, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0e, 0x70, 0x72, 0x65,
+ 0x70, 0x61, 0x72, 0x65, 0x54, 0x72, 0x65, 0x65, 0x4d, 0x61, 0x78, 0x12,
+ 0x28, 0x0a, 0x10, 0x70, 0x72, 0x65, 0x70, 0x61, 0x72, 0x65, 0x5f, 0x74,
+ 0x72, 0x65, 0x65, 0x5f, 0x6d, 0x69, 0x6e, 0x18, 0x0d, 0x20, 0x01, 0x28,
+ 0x03, 0x52, 0x0e, 0x70, 0x72, 0x65, 0x70, 0x61, 0x72, 0x65, 0x54, 0x72,
+ 0x65, 0x65, 0x4d, 0x69, 0x6e, 0x12, 0x28, 0x0a, 0x10, 0x70, 0x72, 0x65,
+ 0x70, 0x61, 0x72, 0x65, 0x5f, 0x74, 0x72, 0x65, 0x65, 0x5f, 0x61, 0x76,
+ 0x67, 0x18, 0x0e, 0x20, 0x01, 0x28, 0x01, 0x52, 0x0e, 0x70, 0x72, 0x65,
+ 0x70, 0x61, 0x72, 0x65, 0x54, 0x72, 0x65, 0x65, 0x41, 0x76, 0x67, 0x12,
+ 0x30, 0x0a, 0x14, 0x67, 0x70, 0x75, 0x5f, 0x63, 0x6f, 0x6d, 0x70, 0x6c,
+ 0x65, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x18,
+ 0x0f, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x12, 0x67, 0x70, 0x75, 0x43, 0x6f,
+ 0x6d, 0x70, 0x6c, 0x65, 0x74, 0x69, 0x6f, 0x6e, 0x43, 0x6f, 0x75, 0x6e,
+ 0x74, 0x12, 0x2c, 0x0a, 0x12, 0x67, 0x70, 0x75, 0x5f, 0x63, 0x6f, 0x6d,
+ 0x70, 0x6c, 0x65, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x6d, 0x61, 0x78, 0x18,
+ 0x10, 0x20, 0x01, 0x28, 0x03, 0x52, 0x10, 0x67, 0x70, 0x75, 0x43, 0x6f,
+ 0x6d, 0x70, 0x6c, 0x65, 0x74, 0x69, 0x6f, 0x6e, 0x4d, 0x61, 0x78, 0x12,
+ 0x2c, 0x0a, 0x12, 0x67, 0x70, 0x75, 0x5f, 0x63, 0x6f, 0x6d, 0x70, 0x6c,
+ 0x65, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x6d, 0x69, 0x6e, 0x18, 0x11, 0x20,
+ 0x01, 0x28, 0x03, 0x52, 0x10, 0x67, 0x70, 0x75, 0x43, 0x6f, 0x6d, 0x70,
+ 0x6c, 0x65, 0x74, 0x69, 0x6f, 0x6e, 0x4d, 0x69, 0x6e, 0x12, 0x2c, 0x0a,
+ 0x12, 0x67, 0x70, 0x75, 0x5f, 0x63, 0x6f, 0x6d, 0x70, 0x6c, 0x65, 0x74,
+ 0x69, 0x6f, 0x6e, 0x5f, 0x61, 0x76, 0x67, 0x18, 0x12, 0x20, 0x01, 0x28,
+ 0x01, 0x52, 0x10, 0x67, 0x70, 0x75, 0x43, 0x6f, 0x6d, 0x70, 0x6c, 0x65,
+ 0x74, 0x69, 0x6f, 0x6e, 0x41, 0x76, 0x67, 0x12, 0x26, 0x0a, 0x0f, 0x75,
+ 0x69, 0x5f, 0x72, 0x65, 0x63, 0x6f, 0x72, 0x64, 0x5f, 0x63, 0x6f, 0x75,
+ 0x6e, 0x74, 0x18, 0x13, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x0d, 0x75, 0x69,
+ 0x52, 0x65, 0x63, 0x6f, 0x72, 0x64, 0x43, 0x6f, 0x75, 0x6e, 0x74, 0x12,
+ 0x22, 0x0a, 0x0d, 0x75, 0x69, 0x5f, 0x72, 0x65, 0x63, 0x6f, 0x72, 0x64,
+ 0x5f, 0x6d, 0x61, 0x78, 0x18, 0x14, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0b,
+ 0x75, 0x69, 0x52, 0x65, 0x63, 0x6f, 0x72, 0x64, 0x4d, 0x61, 0x78, 0x12,
+ 0x22, 0x0a, 0x0d, 0x75, 0x69, 0x5f, 0x72, 0x65, 0x63, 0x6f, 0x72, 0x64,
+ 0x5f, 0x6d, 0x69, 0x6e, 0x18, 0x15, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0b,
+ 0x75, 0x69, 0x52, 0x65, 0x63, 0x6f, 0x72, 0x64, 0x4d, 0x69, 0x6e, 0x12,
+ 0x22, 0x0a, 0x0d, 0x75, 0x69, 0x5f, 0x72, 0x65, 0x63, 0x6f, 0x72, 0x64,
+ 0x5f, 0x61, 0x76, 0x67, 0x18, 0x16, 0x20, 0x01, 0x28, 0x01, 0x52, 0x0b,
+ 0x75, 0x69, 0x52, 0x65, 0x63, 0x6f, 0x72, 0x64, 0x41, 0x76, 0x67, 0x12,
+ 0x30, 0x0a, 0x14, 0x73, 0x68, 0x61, 0x64, 0x65, 0x72, 0x5f, 0x63, 0x6f,
+ 0x6d, 0x70, 0x69, 0x6c, 0x65, 0x5f, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x18,
+ 0x17, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x12, 0x73, 0x68, 0x61, 0x64, 0x65,
+ 0x72, 0x43, 0x6f, 0x6d, 0x70, 0x69, 0x6c, 0x65, 0x43, 0x6f, 0x75, 0x6e,
+ 0x74, 0x12, 0x2e, 0x0a, 0x13, 0x73, 0x68, 0x61, 0x64, 0x65, 0x72, 0x5f,
+ 0x63, 0x6f, 0x6d, 0x70, 0x69, 0x6c, 0x65, 0x5f, 0x74, 0x69, 0x6d, 0x65,
+ 0x18, 0x18, 0x20, 0x01, 0x28, 0x03, 0x52, 0x11, 0x73, 0x68, 0x61, 0x64,
+ 0x65, 0x72, 0x43, 0x6f, 0x6d, 0x70, 0x69, 0x6c, 0x65, 0x54, 0x69, 0x6d,
+ 0x65, 0x12, 0x2c, 0x0a, 0x12, 0x73, 0x68, 0x61, 0x64, 0x65, 0x72, 0x5f,
+ 0x63, 0x6f, 0x6d, 0x70, 0x69, 0x6c, 0x65, 0x5f, 0x61, 0x76, 0x67, 0x18,
+ 0x19, 0x20, 0x01, 0x28, 0x01, 0x52, 0x10, 0x73, 0x68, 0x61, 0x64, 0x65,
+ 0x72, 0x43, 0x6f, 0x6d, 0x70, 0x69, 0x6c, 0x65, 0x41, 0x76, 0x67, 0x12,
+ 0x26, 0x0a, 0x0f, 0x63, 0x61, 0x63, 0x68, 0x65, 0x5f, 0x68, 0x69, 0x74,
+ 0x5f, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x18, 0x1a, 0x20, 0x01, 0x28, 0x0d,
+ 0x52, 0x0d, 0x63, 0x61, 0x63, 0x68, 0x65, 0x48, 0x69, 0x74, 0x43, 0x6f,
+ 0x75, 0x6e, 0x74, 0x12, 0x24, 0x0a, 0x0e, 0x63, 0x61, 0x63, 0x68, 0x65,
+ 0x5f, 0x68, 0x69, 0x74, 0x5f, 0x74, 0x69, 0x6d, 0x65, 0x18, 0x1b, 0x20,
+ 0x01, 0x28, 0x03, 0x52, 0x0c, 0x63, 0x61, 0x63, 0x68, 0x65, 0x48, 0x69,
+ 0x74, 0x54, 0x69, 0x6d, 0x65, 0x12, 0x22, 0x0a, 0x0d, 0x63, 0x61, 0x63,
+ 0x68, 0x65, 0x5f, 0x68, 0x69, 0x74, 0x5f, 0x61, 0x76, 0x67, 0x18, 0x1c,
+ 0x20, 0x01, 0x28, 0x01, 0x52, 0x0b, 0x63, 0x61, 0x63, 0x68, 0x65, 0x48,
+ 0x69, 0x74, 0x41, 0x76, 0x67, 0x12, 0x28, 0x0a, 0x10, 0x63, 0x61, 0x63,
+ 0x68, 0x65, 0x5f, 0x6d, 0x69, 0x73, 0x73, 0x5f, 0x63, 0x6f, 0x75, 0x6e,
+ 0x74, 0x18, 0x1d, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x0e, 0x63, 0x61, 0x63,
+ 0x68, 0x65, 0x4d, 0x69, 0x73, 0x73, 0x43, 0x6f, 0x75, 0x6e, 0x74, 0x12,
+ 0x26, 0x0a, 0x0f, 0x63, 0x61, 0x63, 0x68, 0x65, 0x5f, 0x6d, 0x69, 0x73,
+ 0x73, 0x5f, 0x74, 0x69, 0x6d, 0x65, 0x18, 0x1e, 0x20, 0x01, 0x28, 0x03,
+ 0x52, 0x0d, 0x63, 0x61, 0x63, 0x68, 0x65, 0x4d, 0x69, 0x73, 0x73, 0x54,
+ 0x69, 0x6d, 0x65, 0x12, 0x24, 0x0a, 0x0e, 0x63, 0x61, 0x63, 0x68, 0x65,
+ 0x5f, 0x6d, 0x69, 0x73, 0x73, 0x5f, 0x61, 0x76, 0x67, 0x18, 0x1f, 0x20,
+ 0x01, 0x28, 0x01, 0x52, 0x0c, 0x63, 0x61, 0x63, 0x68, 0x65, 0x4d, 0x69,
+ 0x73, 0x73, 0x41, 0x76, 0x67, 0x12, 0x2f, 0x0a, 0x14, 0x67, 0x72, 0x61,
+ 0x70, 0x68, 0x69, 0x63, 0x73, 0x5f, 0x63, 0x70, 0x75, 0x5f, 0x6d, 0x65,
+ 0x6d, 0x5f, 0x6d, 0x61, 0x78, 0x18, 0x20, 0x20, 0x01, 0x28, 0x03, 0x52,
+ 0x11, 0x67, 0x72, 0x61, 0x70, 0x68, 0x69, 0x63, 0x73, 0x43, 0x70, 0x75,
+ 0x4d, 0x65, 0x6d, 0x4d, 0x61, 0x78, 0x12, 0x2f, 0x0a, 0x14, 0x67, 0x72,
+ 0x61, 0x70, 0x68, 0x69, 0x63, 0x73, 0x5f, 0x63, 0x70, 0x75, 0x5f, 0x6d,
+ 0x65, 0x6d, 0x5f, 0x6d, 0x69, 0x6e, 0x18, 0x21, 0x20, 0x01, 0x28, 0x03,
+ 0x52, 0x11, 0x67, 0x72, 0x61, 0x70, 0x68, 0x69, 0x63, 0x73, 0x43, 0x70,
+ 0x75, 0x4d, 0x65, 0x6d, 0x4d, 0x69, 0x6e, 0x12, 0x2f, 0x0a, 0x14, 0x67,
+ 0x72, 0x61, 0x70, 0x68, 0x69, 0x63, 0x73, 0x5f, 0x63, 0x70, 0x75, 0x5f,
+ 0x6d, 0x65, 0x6d, 0x5f, 0x61, 0x76, 0x67, 0x18, 0x22, 0x20, 0x01, 0x28,
+ 0x01, 0x52, 0x11, 0x67, 0x72, 0x61, 0x70, 0x68, 0x69, 0x63, 0x73, 0x43,
+ 0x70, 0x75, 0x4d, 0x65, 0x6d, 0x41, 0x76, 0x67, 0x12, 0x2f, 0x0a, 0x14,
+ 0x67, 0x72, 0x61, 0x70, 0x68, 0x69, 0x63, 0x73, 0x5f, 0x67, 0x70, 0x75,
+ 0x5f, 0x6d, 0x65, 0x6d, 0x5f, 0x6d, 0x61, 0x78, 0x18, 0x23, 0x20, 0x01,
+ 0x28, 0x03, 0x52, 0x11, 0x67, 0x72, 0x61, 0x70, 0x68, 0x69, 0x63, 0x73,
+ 0x47, 0x70, 0x75, 0x4d, 0x65, 0x6d, 0x4d, 0x61, 0x78, 0x12, 0x2f, 0x0a,
+ 0x14, 0x67, 0x72, 0x61, 0x70, 0x68, 0x69, 0x63, 0x73, 0x5f, 0x67, 0x70,
+ 0x75, 0x5f, 0x6d, 0x65, 0x6d, 0x5f, 0x6d, 0x69, 0x6e, 0x18, 0x24, 0x20,
+ 0x01, 0x28, 0x03, 0x52, 0x11, 0x67, 0x72, 0x61, 0x70, 0x68, 0x69, 0x63,
+ 0x73, 0x47, 0x70, 0x75, 0x4d, 0x65, 0x6d, 0x4d, 0x69, 0x6e, 0x12, 0x2f,
+ 0x0a, 0x14, 0x67, 0x72, 0x61, 0x70, 0x68, 0x69, 0x63, 0x73, 0x5f, 0x67,
+ 0x70, 0x75, 0x5f, 0x6d, 0x65, 0x6d, 0x5f, 0x61, 0x76, 0x67, 0x18, 0x25,
+ 0x20, 0x01, 0x28, 0x01, 0x52, 0x11, 0x67, 0x72, 0x61, 0x70, 0x68, 0x69,
+ 0x63, 0x73, 0x47, 0x70, 0x75, 0x4d, 0x65, 0x6d, 0x41, 0x76, 0x67, 0x12,
+ 0x26, 0x0a, 0x0f, 0x74, 0x65, 0x78, 0x74, 0x75, 0x72, 0x65, 0x5f, 0x6d,
+ 0x65, 0x6d, 0x5f, 0x6d, 0x61, 0x78, 0x18, 0x26, 0x20, 0x01, 0x28, 0x03,
+ 0x52, 0x0d, 0x74, 0x65, 0x78, 0x74, 0x75, 0x72, 0x65, 0x4d, 0x65, 0x6d,
+ 0x4d, 0x61, 0x78, 0x12, 0x26, 0x0a, 0x0f, 0x74, 0x65, 0x78, 0x74, 0x75,
+ 0x72, 0x65, 0x5f, 0x6d, 0x65, 0x6d, 0x5f, 0x6d, 0x69, 0x6e, 0x18, 0x27,
+ 0x20, 0x01, 0x28, 0x03, 0x52, 0x0d, 0x74, 0x65, 0x78, 0x74, 0x75, 0x72,
+ 0x65, 0x4d, 0x65, 0x6d, 0x4d, 0x69, 0x6e, 0x12, 0x26, 0x0a, 0x0f, 0x74,
+ 0x65, 0x78, 0x74, 0x75, 0x72, 0x65, 0x5f, 0x6d, 0x65, 0x6d, 0x5f, 0x61,
+ 0x76, 0x67, 0x18, 0x28, 0x20, 0x01, 0x28, 0x01, 0x52, 0x0d, 0x74, 0x65,
+ 0x78, 0x74, 0x75, 0x72, 0x65, 0x4d, 0x65, 0x6d, 0x41, 0x76, 0x67, 0x12,
+ 0x1e, 0x0a, 0x0b, 0x61, 0x6c, 0x6c, 0x5f, 0x6d, 0x65, 0x6d, 0x5f, 0x6d,
+ 0x61, 0x78, 0x18, 0x29, 0x20, 0x01, 0x28, 0x03, 0x52, 0x09, 0x61, 0x6c,
+ 0x6c, 0x4d, 0x65, 0x6d, 0x4d, 0x61, 0x78, 0x12, 0x1e, 0x0a, 0x0b, 0x61,
+ 0x6c, 0x6c, 0x5f, 0x6d, 0x65, 0x6d, 0x5f, 0x6d, 0x69, 0x6e, 0x18, 0x2a,
+ 0x20, 0x01, 0x28, 0x03, 0x52, 0x09, 0x61, 0x6c, 0x6c, 0x4d, 0x65, 0x6d,
+ 0x4d, 0x69, 0x6e, 0x12, 0x1e, 0x0a, 0x0b, 0x61, 0x6c, 0x6c, 0x5f, 0x6d,
+ 0x65, 0x6d, 0x5f, 0x61, 0x76, 0x67, 0x18, 0x2b, 0x20, 0x01, 0x28, 0x01,
+ 0x52, 0x09, 0x61, 0x6c, 0x6c, 0x4d, 0x65, 0x6d, 0x41, 0x76, 0x67, 0x22,
+ 0x5a, 0x0a, 0x11, 0x41, 0x6e, 0x64, 0x72, 0x6f, 0x69, 0x64, 0x48, 0x77,
+ 0x75, 0x69, 0x4d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x12, 0x45, 0x0a, 0x0c,
+ 0x70, 0x72, 0x6f, 0x63, 0x65, 0x73, 0x73, 0x5f, 0x69, 0x6e, 0x66, 0x6f,
+ 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x22, 0x2e, 0x70, 0x65, 0x72,
+ 0x66, 0x65, 0x74, 0x74, 0x6f, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73,
+ 0x2e, 0x50, 0x72, 0x6f, 0x63, 0x65, 0x73, 0x73, 0x52, 0x65, 0x6e, 0x64,
+ 0x65, 0x72, 0x49, 0x6e, 0x66, 0x6f, 0x52, 0x0b, 0x70, 0x72, 0x6f, 0x63,
+ 0x65, 0x73, 0x73, 0x49, 0x6e, 0x66, 0x6f, 0x0a, 0x88, 0x02, 0x0a, 0x32,
+ 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2f, 0x70, 0x65, 0x72, 0x66, 0x65,
+ 0x74, 0x74, 0x6f, 0x2f, 0x6d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x73, 0x2f,
+ 0x61, 0x6e, 0x64, 0x72, 0x6f, 0x69, 0x64, 0x2f, 0x70, 0x61, 0x63, 0x6b,
+ 0x61, 0x67, 0x65, 0x5f, 0x6c, 0x69, 0x73, 0x74, 0x2e, 0x70, 0x72, 0x6f,
+ 0x74, 0x6f, 0x12, 0x0f, 0x70, 0x65, 0x72, 0x66, 0x65, 0x74, 0x74, 0x6f,
+ 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x22, 0xc0, 0x01, 0x0a, 0x12,
+ 0x41, 0x6e, 0x64, 0x72, 0x6f, 0x69, 0x64, 0x50, 0x61, 0x63, 0x6b, 0x61,
+ 0x67, 0x65, 0x4c, 0x69, 0x73, 0x74, 0x12, 0x47, 0x0a, 0x08, 0x70, 0x61,
+ 0x63, 0x6b, 0x61, 0x67, 0x65, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b,
+ 0x32, 0x2b, 0x2e, 0x70, 0x65, 0x72, 0x66, 0x65, 0x74, 0x74, 0x6f, 0x2e,
+ 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2e, 0x41, 0x6e, 0x64, 0x72, 0x6f,
+ 0x69, 0x64, 0x50, 0x61, 0x63, 0x6b, 0x61, 0x67, 0x65, 0x4c, 0x69, 0x73,
+ 0x74, 0x2e, 0x50, 0x61, 0x63, 0x6b, 0x61, 0x67, 0x65, 0x52, 0x08, 0x70,
+ 0x61, 0x63, 0x6b, 0x61, 0x67, 0x65, 0x73, 0x1a, 0x61, 0x0a, 0x07, 0x50,
+ 0x61, 0x63, 0x6b, 0x61, 0x67, 0x65, 0x12, 0x21, 0x0a, 0x0c, 0x70, 0x61,
+ 0x63, 0x6b, 0x61, 0x67, 0x65, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01,
+ 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x70, 0x61, 0x63, 0x6b, 0x61, 0x67,
+ 0x65, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x10, 0x0a, 0x03, 0x75, 0x69, 0x64,
+ 0x18, 0x02, 0x20, 0x01, 0x28, 0x03, 0x52, 0x03, 0x75, 0x69, 0x64, 0x12,
+ 0x21, 0x0a, 0x0c, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x5f, 0x63,
+ 0x6f, 0x64, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0b, 0x76,
+ 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x43, 0x6f, 0x64, 0x65, 0x0a, 0x9f,
+ 0x03, 0x0a, 0x3b, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2f, 0x70, 0x65,
+ 0x72, 0x66, 0x65, 0x74, 0x74, 0x6f, 0x2f, 0x6d, 0x65, 0x74, 0x72, 0x69,
+ 0x63, 0x73, 0x2f, 0x61, 0x6e, 0x64, 0x72, 0x6f, 0x69, 0x64, 0x2f, 0x75,
+ 0x6e, 0x6d, 0x61, 0x70, 0x70, 0x65, 0x64, 0x5f, 0x6a, 0x61, 0x76, 0x61,
+ 0x5f, 0x73, 0x79, 0x6d, 0x62, 0x6f, 0x6c, 0x73, 0x2e, 0x70, 0x72, 0x6f,
0x74, 0x6f, 0x12, 0x0f, 0x70, 0x65, 0x72, 0x66, 0x65, 0x74, 0x74, 0x6f,
0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x1a, 0x36, 0x70, 0x72, 0x6f,
0x74, 0x6f, 0x73, 0x2f, 0x70, 0x65, 0x72, 0x66, 0x65, 0x74, 0x74, 0x6f,
0x2f, 0x6d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x73, 0x2f, 0x61, 0x6e, 0x64,
0x72, 0x6f, 0x69, 0x64, 0x2f, 0x70, 0x72, 0x6f, 0x63, 0x65, 0x73, 0x73,
0x5f, 0x6d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x2e, 0x70, 0x72,
- 0x6f, 0x74, 0x6f, 0x22, 0xa4, 0x07, 0x0a, 0x14, 0x48, 0x65, 0x61, 0x70,
- 0x50, 0x72, 0x6f, 0x66, 0x69, 0x6c, 0x65, 0x43, 0x61, 0x6c, 0x6c, 0x73,
- 0x69, 0x74, 0x65, 0x73, 0x12, 0x5a, 0x0a, 0x0e, 0x69, 0x6e, 0x73, 0x74,
- 0x61, 0x6e, 0x63, 0x65, 0x5f, 0x73, 0x74, 0x61, 0x74, 0x73, 0x18, 0x01,
+ 0x6f, 0x74, 0x6f, 0x22, 0x96, 0x02, 0x0a, 0x13, 0x55, 0x6e, 0x6d, 0x61,
+ 0x70, 0x70, 0x65, 0x64, 0x4a, 0x61, 0x76, 0x61, 0x53, 0x79, 0x6d, 0x62,
+ 0x6f, 0x6c, 0x73, 0x12, 0x5c, 0x0a, 0x0f, 0x70, 0x72, 0x6f, 0x63, 0x65,
+ 0x73, 0x73, 0x5f, 0x73, 0x79, 0x6d, 0x62, 0x6f, 0x6c, 0x73, 0x18, 0x01,
0x20, 0x03, 0x28, 0x0b, 0x32, 0x33, 0x2e, 0x70, 0x65, 0x72, 0x66, 0x65,
- 0x74, 0x74, 0x6f, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2e, 0x48,
- 0x65, 0x61, 0x70, 0x50, 0x72, 0x6f, 0x66, 0x69, 0x6c, 0x65, 0x43, 0x61,
- 0x6c, 0x6c, 0x73, 0x69, 0x74, 0x65, 0x73, 0x2e, 0x49, 0x6e, 0x73, 0x74,
- 0x61, 0x6e, 0x63, 0x65, 0x53, 0x74, 0x61, 0x74, 0x73, 0x52, 0x0d, 0x69,
- 0x6e, 0x73, 0x74, 0x61, 0x6e, 0x63, 0x65, 0x53, 0x74, 0x61, 0x74, 0x73,
- 0x1a, 0x3e, 0x0a, 0x05, 0x46, 0x72, 0x61, 0x6d, 0x65, 0x12, 0x12, 0x0a,
- 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52,
- 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x21, 0x0a, 0x0c, 0x6d, 0x61, 0x70,
- 0x70, 0x69, 0x6e, 0x67, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x02, 0x20,
- 0x01, 0x28, 0x09, 0x52, 0x0b, 0x6d, 0x61, 0x70, 0x70, 0x69, 0x6e, 0x67,
- 0x4e, 0x61, 0x6d, 0x65, 0x1a, 0x8e, 0x01, 0x0a, 0x08, 0x43, 0x6f, 0x75,
- 0x6e, 0x74, 0x65, 0x72, 0x73, 0x12, 0x1f, 0x0a, 0x0b, 0x74, 0x6f, 0x74,
- 0x61, 0x6c, 0x5f, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x18, 0x01, 0x20, 0x01,
- 0x28, 0x03, 0x52, 0x0a, 0x74, 0x6f, 0x74, 0x61, 0x6c, 0x43, 0x6f, 0x75,
- 0x6e, 0x74, 0x12, 0x1f, 0x0a, 0x0b, 0x74, 0x6f, 0x74, 0x61, 0x6c, 0x5f,
- 0x62, 0x79, 0x74, 0x65, 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x03, 0x52,
- 0x0a, 0x74, 0x6f, 0x74, 0x61, 0x6c, 0x42, 0x79, 0x74, 0x65, 0x73, 0x12,
- 0x1f, 0x0a, 0x0b, 0x64, 0x65, 0x6c, 0x74, 0x61, 0x5f, 0x63, 0x6f, 0x75,
- 0x6e, 0x74, 0x18, 0x03, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0a, 0x64, 0x65,
- 0x6c, 0x74, 0x61, 0x43, 0x6f, 0x75, 0x6e, 0x74, 0x12, 0x1f, 0x0a, 0x0b,
- 0x64, 0x65, 0x6c, 0x74, 0x61, 0x5f, 0x62, 0x79, 0x74, 0x65, 0x73, 0x18,
- 0x04, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0a, 0x64, 0x65, 0x6c, 0x74, 0x61,
- 0x42, 0x79, 0x74, 0x65, 0x73, 0x1a, 0xa6, 0x02, 0x0a, 0x08, 0x43, 0x61,
- 0x6c, 0x6c, 0x73, 0x69, 0x74, 0x65, 0x12, 0x12, 0x0a, 0x04, 0x68, 0x61,
- 0x73, 0x68, 0x18, 0x01, 0x20, 0x01, 0x28, 0x03, 0x52, 0x04, 0x68, 0x61,
- 0x73, 0x68, 0x12, 0x1f, 0x0a, 0x0b, 0x70, 0x61, 0x72, 0x65, 0x6e, 0x74,
- 0x5f, 0x68, 0x61, 0x73, 0x68, 0x18, 0x02, 0x20, 0x01, 0x28, 0x03, 0x52,
- 0x0a, 0x70, 0x61, 0x72, 0x65, 0x6e, 0x74, 0x48, 0x61, 0x73, 0x68, 0x12,
- 0x41, 0x0a, 0x05, 0x66, 0x72, 0x61, 0x6d, 0x65, 0x18, 0x03, 0x20, 0x01,
- 0x28, 0x0b, 0x32, 0x2b, 0x2e, 0x70, 0x65, 0x72, 0x66, 0x65, 0x74, 0x74,
- 0x6f, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2e, 0x48, 0x65, 0x61,
- 0x70, 0x50, 0x72, 0x6f, 0x66, 0x69, 0x6c, 0x65, 0x43, 0x61, 0x6c, 0x6c,
- 0x73, 0x69, 0x74, 0x65, 0x73, 0x2e, 0x46, 0x72, 0x61, 0x6d, 0x65, 0x52,
- 0x05, 0x66, 0x72, 0x61, 0x6d, 0x65, 0x12, 0x4f, 0x0a, 0x0b, 0x73, 0x65,
- 0x6c, 0x66, 0x5f, 0x61, 0x6c, 0x6c, 0x6f, 0x63, 0x73, 0x18, 0x04, 0x20,
- 0x01, 0x28, 0x0b, 0x32, 0x2e, 0x2e, 0x70, 0x65, 0x72, 0x66, 0x65, 0x74,
- 0x74, 0x6f, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2e, 0x48, 0x65,
- 0x61, 0x70, 0x50, 0x72, 0x6f, 0x66, 0x69, 0x6c, 0x65, 0x43, 0x61, 0x6c,
- 0x6c, 0x73, 0x69, 0x74, 0x65, 0x73, 0x2e, 0x43, 0x6f, 0x75, 0x6e, 0x74,
- 0x65, 0x72, 0x73, 0x52, 0x0a, 0x73, 0x65, 0x6c, 0x66, 0x41, 0x6c, 0x6c,
- 0x6f, 0x63, 0x73, 0x12, 0x51, 0x0a, 0x0c, 0x63, 0x68, 0x69, 0x6c, 0x64,
- 0x5f, 0x61, 0x6c, 0x6c, 0x6f, 0x63, 0x73, 0x18, 0x05, 0x20, 0x01, 0x28,
- 0x0b, 0x32, 0x2e, 0x2e, 0x70, 0x65, 0x72, 0x66, 0x65, 0x74, 0x74, 0x6f,
- 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2e, 0x48, 0x65, 0x61, 0x70,
- 0x50, 0x72, 0x6f, 0x66, 0x69, 0x6c, 0x65, 0x43, 0x61, 0x6c, 0x6c, 0x73,
- 0x69, 0x74, 0x65, 0x73, 0x2e, 0x43, 0x6f, 0x75, 0x6e, 0x74, 0x65, 0x72,
- 0x73, 0x52, 0x0b, 0x63, 0x68, 0x69, 0x6c, 0x64, 0x41, 0x6c, 0x6c, 0x6f,
- 0x63, 0x73, 0x1a, 0xb5, 0x02, 0x0a, 0x0d, 0x49, 0x6e, 0x73, 0x74, 0x61,
- 0x6e, 0x63, 0x65, 0x53, 0x74, 0x61, 0x74, 0x73, 0x12, 0x10, 0x0a, 0x03,
- 0x70, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x03, 0x70,
- 0x69, 0x64, 0x12, 0x21, 0x0a, 0x0c, 0x70, 0x72, 0x6f, 0x63, 0x65, 0x73,
- 0x73, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09,
- 0x52, 0x0b, 0x70, 0x72, 0x6f, 0x63, 0x65, 0x73, 0x73, 0x4e, 0x61, 0x6d,
- 0x65, 0x12, 0x41, 0x0a, 0x07, 0x70, 0x72, 0x6f, 0x63, 0x65, 0x73, 0x73,
- 0x18, 0x06, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x27, 0x2e, 0x70, 0x65, 0x72,
+ 0x74, 0x74, 0x6f, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2e, 0x55,
+ 0x6e, 0x6d, 0x61, 0x70, 0x70, 0x65, 0x64, 0x4a, 0x61, 0x76, 0x61, 0x53,
+ 0x79, 0x6d, 0x62, 0x6f, 0x6c, 0x73, 0x2e, 0x50, 0x72, 0x6f, 0x63, 0x65,
+ 0x73, 0x73, 0x53, 0x79, 0x6d, 0x62, 0x6f, 0x6c, 0x73, 0x52, 0x0e, 0x70,
+ 0x72, 0x6f, 0x63, 0x65, 0x73, 0x73, 0x53, 0x79, 0x6d, 0x62, 0x6f, 0x6c,
+ 0x73, 0x1a, 0xa0, 0x01, 0x0a, 0x0e, 0x50, 0x72, 0x6f, 0x63, 0x65, 0x73,
+ 0x73, 0x53, 0x79, 0x6d, 0x62, 0x6f, 0x6c, 0x73, 0x12, 0x52, 0x0a, 0x10,
+ 0x70, 0x72, 0x6f, 0x63, 0x65, 0x73, 0x73, 0x5f, 0x6d, 0x65, 0x74, 0x61,
+ 0x64, 0x61, 0x74, 0x61, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x27,
+ 0x2e, 0x70, 0x65, 0x72, 0x66, 0x65, 0x74, 0x74, 0x6f, 0x2e, 0x70, 0x72,
+ 0x6f, 0x74, 0x6f, 0x73, 0x2e, 0x41, 0x6e, 0x64, 0x72, 0x6f, 0x69, 0x64,
+ 0x50, 0x72, 0x6f, 0x63, 0x65, 0x73, 0x73, 0x4d, 0x65, 0x74, 0x61, 0x64,
+ 0x61, 0x74, 0x61, 0x52, 0x0f, 0x70, 0x72, 0x6f, 0x63, 0x65, 0x73, 0x73,
+ 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x12, 0x1b, 0x0a, 0x09,
+ 0x74, 0x79, 0x70, 0x65, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x02, 0x20,
+ 0x03, 0x28, 0x09, 0x52, 0x08, 0x74, 0x79, 0x70, 0x65, 0x4e, 0x61, 0x6d,
+ 0x65, 0x12, 0x1d, 0x0a, 0x0a, 0x66, 0x69, 0x65, 0x6c, 0x64, 0x5f, 0x6e,
+ 0x61, 0x6d, 0x65, 0x18, 0x03, 0x20, 0x03, 0x28, 0x09, 0x52, 0x09, 0x66,
+ 0x69, 0x65, 0x6c, 0x64, 0x4e, 0x61, 0x6d, 0x65, 0x0a, 0xfc, 0x01, 0x0a,
+ 0x39, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2f, 0x70, 0x65, 0x72, 0x66,
+ 0x65, 0x74, 0x74, 0x6f, 0x2f, 0x6d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x73,
+ 0x2f, 0x61, 0x6e, 0x64, 0x72, 0x6f, 0x69, 0x64, 0x2f, 0x75, 0x6e, 0x73,
+ 0x79, 0x6d, 0x62, 0x6f, 0x6c, 0x69, 0x7a, 0x65, 0x64, 0x5f, 0x66, 0x72,
+ 0x61, 0x6d, 0x65, 0x73, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x0f,
+ 0x70, 0x65, 0x72, 0x66, 0x65, 0x74, 0x74, 0x6f, 0x2e, 0x70, 0x72, 0x6f,
+ 0x74, 0x6f, 0x73, 0x22, 0xad, 0x01, 0x0a, 0x12, 0x55, 0x6e, 0x73, 0x79,
+ 0x6d, 0x62, 0x6f, 0x6c, 0x69, 0x7a, 0x65, 0x64, 0x46, 0x72, 0x61, 0x6d,
+ 0x65, 0x73, 0x12, 0x41, 0x0a, 0x06, 0x66, 0x72, 0x61, 0x6d, 0x65, 0x73,
+ 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x29, 0x2e, 0x70, 0x65, 0x72,
0x66, 0x65, 0x74, 0x74, 0x6f, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73,
- 0x2e, 0x41, 0x6e, 0x64, 0x72, 0x6f, 0x69, 0x64, 0x50, 0x72, 0x6f, 0x63,
- 0x65, 0x73, 0x73, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x52,
- 0x07, 0x70, 0x72, 0x6f, 0x63, 0x65, 0x73, 0x73, 0x12, 0x4c, 0x0a, 0x09,
- 0x63, 0x61, 0x6c, 0x6c, 0x73, 0x69, 0x74, 0x65, 0x73, 0x18, 0x03, 0x20,
- 0x03, 0x28, 0x0b, 0x32, 0x2e, 0x2e, 0x70, 0x65, 0x72, 0x66, 0x65, 0x74,
- 0x74, 0x6f, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2e, 0x48, 0x65,
- 0x61, 0x70, 0x50, 0x72, 0x6f, 0x66, 0x69, 0x6c, 0x65, 0x43, 0x61, 0x6c,
- 0x6c, 0x73, 0x69, 0x74, 0x65, 0x73, 0x2e, 0x43, 0x61, 0x6c, 0x6c, 0x73,
- 0x69, 0x74, 0x65, 0x52, 0x09, 0x63, 0x61, 0x6c, 0x6c, 0x73, 0x69, 0x74,
- 0x65, 0x73, 0x12, 0x2e, 0x0a, 0x13, 0x70, 0x72, 0x6f, 0x66, 0x69, 0x6c,
- 0x65, 0x5f, 0x64, 0x65, 0x6c, 0x74, 0x61, 0x5f, 0x62, 0x79, 0x74, 0x65,
- 0x73, 0x18, 0x04, 0x20, 0x01, 0x28, 0x03, 0x52, 0x11, 0x70, 0x72, 0x6f,
- 0x66, 0x69, 0x6c, 0x65, 0x44, 0x65, 0x6c, 0x74, 0x61, 0x42, 0x79, 0x74,
- 0x65, 0x73, 0x12, 0x2e, 0x0a, 0x13, 0x70, 0x72, 0x6f, 0x66, 0x69, 0x6c,
- 0x65, 0x5f, 0x74, 0x6f, 0x74, 0x61, 0x6c, 0x5f, 0x62, 0x79, 0x74, 0x65,
- 0x73, 0x18, 0x05, 0x20, 0x01, 0x28, 0x03, 0x52, 0x11, 0x70, 0x72, 0x6f,
- 0x66, 0x69, 0x6c, 0x65, 0x54, 0x6f, 0x74, 0x61, 0x6c, 0x42, 0x79, 0x74,
- 0x65, 0x73, 0x42, 0x02, 0x48, 0x03, 0x0a, 0x8c, 0x02, 0x0a, 0x32, 0x70,
- 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2f, 0x70, 0x65, 0x72, 0x66, 0x65, 0x74,
- 0x74, 0x6f, 0x2f, 0x6d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x73, 0x2f, 0x61,
- 0x6e, 0x64, 0x72, 0x6f, 0x69, 0x64, 0x2f, 0x70, 0x61, 0x63, 0x6b, 0x61,
- 0x67, 0x65, 0x5f, 0x6c, 0x69, 0x73, 0x74, 0x2e, 0x70, 0x72, 0x6f, 0x74,
- 0x6f, 0x12, 0x0f, 0x70, 0x65, 0x72, 0x66, 0x65, 0x74, 0x74, 0x6f, 0x2e,
- 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x22, 0xc0, 0x01, 0x0a, 0x12, 0x41,
- 0x6e, 0x64, 0x72, 0x6f, 0x69, 0x64, 0x50, 0x61, 0x63, 0x6b, 0x61, 0x67,
- 0x65, 0x4c, 0x69, 0x73, 0x74, 0x12, 0x47, 0x0a, 0x08, 0x70, 0x61, 0x63,
- 0x6b, 0x61, 0x67, 0x65, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32,
- 0x2b, 0x2e, 0x70, 0x65, 0x72, 0x66, 0x65, 0x74, 0x74, 0x6f, 0x2e, 0x70,
- 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2e, 0x41, 0x6e, 0x64, 0x72, 0x6f, 0x69,
- 0x64, 0x50, 0x61, 0x63, 0x6b, 0x61, 0x67, 0x65, 0x4c, 0x69, 0x73, 0x74,
- 0x2e, 0x50, 0x61, 0x63, 0x6b, 0x61, 0x67, 0x65, 0x52, 0x08, 0x70, 0x61,
- 0x63, 0x6b, 0x61, 0x67, 0x65, 0x73, 0x1a, 0x61, 0x0a, 0x07, 0x50, 0x61,
- 0x63, 0x6b, 0x61, 0x67, 0x65, 0x12, 0x21, 0x0a, 0x0c, 0x70, 0x61, 0x63,
- 0x6b, 0x61, 0x67, 0x65, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20,
- 0x01, 0x28, 0x09, 0x52, 0x0b, 0x70, 0x61, 0x63, 0x6b, 0x61, 0x67, 0x65,
- 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x10, 0x0a, 0x03, 0x75, 0x69, 0x64, 0x18,
- 0x02, 0x20, 0x01, 0x28, 0x03, 0x52, 0x03, 0x75, 0x69, 0x64, 0x12, 0x21,
- 0x0a, 0x0c, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x5f, 0x63, 0x6f,
- 0x64, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0b, 0x76, 0x65,
- 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x43, 0x6f, 0x64, 0x65, 0x42, 0x02, 0x48,
- 0x03, 0x0a, 0xa3, 0x03, 0x0a, 0x3b, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73,
+ 0x2e, 0x55, 0x6e, 0x73, 0x79, 0x6d, 0x62, 0x6f, 0x6c, 0x69, 0x7a, 0x65,
+ 0x64, 0x46, 0x72, 0x61, 0x6d, 0x65, 0x73, 0x2e, 0x46, 0x72, 0x61, 0x6d,
+ 0x65, 0x52, 0x06, 0x66, 0x72, 0x61, 0x6d, 0x65, 0x73, 0x1a, 0x54, 0x0a,
+ 0x05, 0x46, 0x72, 0x61, 0x6d, 0x65, 0x12, 0x16, 0x0a, 0x06, 0x6d, 0x6f,
+ 0x64, 0x75, 0x6c, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06,
+ 0x6d, 0x6f, 0x64, 0x75, 0x6c, 0x65, 0x12, 0x19, 0x0a, 0x08, 0x62, 0x75,
+ 0x69, 0x6c, 0x64, 0x5f, 0x69, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09,
+ 0x52, 0x07, 0x62, 0x75, 0x69, 0x6c, 0x64, 0x49, 0x64, 0x12, 0x18, 0x0a,
+ 0x07, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x18, 0x03, 0x20, 0x01,
+ 0x28, 0x03, 0x52, 0x07, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x0a,
+ 0xf8, 0x03, 0x0a, 0x35, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2f, 0x70,
+ 0x65, 0x72, 0x66, 0x65, 0x74, 0x74, 0x6f, 0x2f, 0x6d, 0x65, 0x74, 0x72,
+ 0x69, 0x63, 0x73, 0x2f, 0x61, 0x6e, 0x64, 0x72, 0x6f, 0x69, 0x64, 0x2f,
+ 0x6a, 0x61, 0x76, 0x61, 0x5f, 0x68, 0x65, 0x61, 0x70, 0x5f, 0x73, 0x74,
+ 0x61, 0x74, 0x73, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x0f, 0x70,
+ 0x65, 0x72, 0x66, 0x65, 0x74, 0x74, 0x6f, 0x2e, 0x70, 0x72, 0x6f, 0x74,
+ 0x6f, 0x73, 0x1a, 0x36, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2f, 0x70,
+ 0x65, 0x72, 0x66, 0x65, 0x74, 0x74, 0x6f, 0x2f, 0x6d, 0x65, 0x74, 0x72,
+ 0x69, 0x63, 0x73, 0x2f, 0x61, 0x6e, 0x64, 0x72, 0x6f, 0x69, 0x64, 0x2f,
+ 0x70, 0x72, 0x6f, 0x63, 0x65, 0x73, 0x73, 0x5f, 0x6d, 0x65, 0x74, 0x61,
+ 0x64, 0x61, 0x74, 0x61, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x22, 0xf5,
+ 0x02, 0x0a, 0x0d, 0x4a, 0x61, 0x76, 0x61, 0x48, 0x65, 0x61, 0x70, 0x53,
+ 0x74, 0x61, 0x74, 0x73, 0x12, 0x53, 0x0a, 0x0e, 0x69, 0x6e, 0x73, 0x74,
+ 0x61, 0x6e, 0x63, 0x65, 0x5f, 0x73, 0x74, 0x61, 0x74, 0x73, 0x18, 0x01,
+ 0x20, 0x03, 0x28, 0x0b, 0x32, 0x2c, 0x2e, 0x70, 0x65, 0x72, 0x66, 0x65,
+ 0x74, 0x74, 0x6f, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2e, 0x4a,
+ 0x61, 0x76, 0x61, 0x48, 0x65, 0x61, 0x70, 0x53, 0x74, 0x61, 0x74, 0x73,
+ 0x2e, 0x49, 0x6e, 0x73, 0x74, 0x61, 0x6e, 0x63, 0x65, 0x53, 0x74, 0x61,
+ 0x74, 0x73, 0x52, 0x0d, 0x69, 0x6e, 0x73, 0x74, 0x61, 0x6e, 0x63, 0x65,
+ 0x53, 0x74, 0x61, 0x74, 0x73, 0x1a, 0x65, 0x0a, 0x06, 0x53, 0x61, 0x6d,
+ 0x70, 0x6c, 0x65, 0x12, 0x0e, 0x0a, 0x02, 0x74, 0x73, 0x18, 0x01, 0x20,
+ 0x01, 0x28, 0x03, 0x52, 0x02, 0x74, 0x73, 0x12, 0x1b, 0x0a, 0x09, 0x68,
+ 0x65, 0x61, 0x70, 0x5f, 0x73, 0x69, 0x7a, 0x65, 0x18, 0x02, 0x20, 0x01,
+ 0x28, 0x03, 0x52, 0x08, 0x68, 0x65, 0x61, 0x70, 0x53, 0x69, 0x7a, 0x65,
+ 0x12, 0x2e, 0x0a, 0x13, 0x72, 0x65, 0x61, 0x63, 0x68, 0x61, 0x62, 0x6c,
+ 0x65, 0x5f, 0x68, 0x65, 0x61, 0x70, 0x5f, 0x73, 0x69, 0x7a, 0x65, 0x18,
+ 0x03, 0x20, 0x01, 0x28, 0x03, 0x52, 0x11, 0x72, 0x65, 0x61, 0x63, 0x68,
+ 0x61, 0x62, 0x6c, 0x65, 0x48, 0x65, 0x61, 0x70, 0x53, 0x69, 0x7a, 0x65,
+ 0x1a, 0xa7, 0x01, 0x0a, 0x0d, 0x49, 0x6e, 0x73, 0x74, 0x61, 0x6e, 0x63,
+ 0x65, 0x53, 0x74, 0x61, 0x74, 0x73, 0x12, 0x12, 0x0a, 0x04, 0x75, 0x70,
+ 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x04, 0x75, 0x70,
+ 0x69, 0x64, 0x12, 0x41, 0x0a, 0x07, 0x70, 0x72, 0x6f, 0x63, 0x65, 0x73,
+ 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x27, 0x2e, 0x70, 0x65,
+ 0x72, 0x66, 0x65, 0x74, 0x74, 0x6f, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f,
+ 0x73, 0x2e, 0x41, 0x6e, 0x64, 0x72, 0x6f, 0x69, 0x64, 0x50, 0x72, 0x6f,
+ 0x63, 0x65, 0x73, 0x73, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61,
+ 0x52, 0x07, 0x70, 0x72, 0x6f, 0x63, 0x65, 0x73, 0x73, 0x12, 0x3f, 0x0a,
+ 0x07, 0x73, 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x73, 0x18, 0x03, 0x20, 0x03,
+ 0x28, 0x0b, 0x32, 0x25, 0x2e, 0x70, 0x65, 0x72, 0x66, 0x65, 0x74, 0x74,
+ 0x6f, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2e, 0x4a, 0x61, 0x76,
+ 0x61, 0x48, 0x65, 0x61, 0x70, 0x53, 0x74, 0x61, 0x74, 0x73, 0x2e, 0x53,
+ 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x52, 0x07, 0x73, 0x61, 0x6d, 0x70, 0x6c,
+ 0x65, 0x73, 0x0a, 0xbb, 0x14, 0x0a, 0x25, 0x70, 0x72, 0x6f, 0x74, 0x6f,
+ 0x73, 0x2f, 0x70, 0x65, 0x72, 0x66, 0x65, 0x74, 0x74, 0x6f, 0x2f, 0x6d,
+ 0x65, 0x74, 0x72, 0x69, 0x63, 0x73, 0x2f, 0x6d, 0x65, 0x74, 0x72, 0x69,
+ 0x63, 0x73, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x0f, 0x70, 0x65,
+ 0x72, 0x66, 0x65, 0x74, 0x74, 0x6f, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f,
+ 0x73, 0x1a, 0x31, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2f, 0x70, 0x65,
+ 0x72, 0x66, 0x65, 0x74, 0x74, 0x6f, 0x2f, 0x6d, 0x65, 0x74, 0x72, 0x69,
+ 0x63, 0x73, 0x2f, 0x61, 0x6e, 0x64, 0x72, 0x6f, 0x69, 0x64, 0x2f, 0x62,
+ 0x61, 0x74, 0x74, 0x5f, 0x6d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x2e, 0x70,
+ 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x30, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73,
0x2f, 0x70, 0x65, 0x72, 0x66, 0x65, 0x74, 0x74, 0x6f, 0x2f, 0x6d, 0x65,
0x74, 0x72, 0x69, 0x63, 0x73, 0x2f, 0x61, 0x6e, 0x64, 0x72, 0x6f, 0x69,
- 0x64, 0x2f, 0x75, 0x6e, 0x6d, 0x61, 0x70, 0x70, 0x65, 0x64, 0x5f, 0x6a,
- 0x61, 0x76, 0x61, 0x5f, 0x73, 0x79, 0x6d, 0x62, 0x6f, 0x6c, 0x73, 0x2e,
- 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x0f, 0x70, 0x65, 0x72, 0x66, 0x65,
- 0x74, 0x74, 0x6f, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x1a, 0x36,
- 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2f, 0x70, 0x65, 0x72, 0x66, 0x65,
- 0x74, 0x74, 0x6f, 0x2f, 0x6d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x73, 0x2f,
- 0x61, 0x6e, 0x64, 0x72, 0x6f, 0x69, 0x64, 0x2f, 0x70, 0x72, 0x6f, 0x63,
- 0x65, 0x73, 0x73, 0x5f, 0x6d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61,
- 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x22, 0x96, 0x02, 0x0a, 0x13, 0x55,
- 0x6e, 0x6d, 0x61, 0x70, 0x70, 0x65, 0x64, 0x4a, 0x61, 0x76, 0x61, 0x53,
- 0x79, 0x6d, 0x62, 0x6f, 0x6c, 0x73, 0x12, 0x5c, 0x0a, 0x0f, 0x70, 0x72,
- 0x6f, 0x63, 0x65, 0x73, 0x73, 0x5f, 0x73, 0x79, 0x6d, 0x62, 0x6f, 0x6c,
- 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x33, 0x2e, 0x70, 0x65,
- 0x72, 0x66, 0x65, 0x74, 0x74, 0x6f, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f,
- 0x73, 0x2e, 0x55, 0x6e, 0x6d, 0x61, 0x70, 0x70, 0x65, 0x64, 0x4a, 0x61,
- 0x76, 0x61, 0x53, 0x79, 0x6d, 0x62, 0x6f, 0x6c, 0x73, 0x2e, 0x50, 0x72,
- 0x6f, 0x63, 0x65, 0x73, 0x73, 0x53, 0x79, 0x6d, 0x62, 0x6f, 0x6c, 0x73,
- 0x52, 0x0e, 0x70, 0x72, 0x6f, 0x63, 0x65, 0x73, 0x73, 0x53, 0x79, 0x6d,
- 0x62, 0x6f, 0x6c, 0x73, 0x1a, 0xa0, 0x01, 0x0a, 0x0e, 0x50, 0x72, 0x6f,
- 0x63, 0x65, 0x73, 0x73, 0x53, 0x79, 0x6d, 0x62, 0x6f, 0x6c, 0x73, 0x12,
- 0x52, 0x0a, 0x10, 0x70, 0x72, 0x6f, 0x63, 0x65, 0x73, 0x73, 0x5f, 0x6d,
- 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x18, 0x01, 0x20, 0x01, 0x28,
- 0x0b, 0x32, 0x27, 0x2e, 0x70, 0x65, 0x72, 0x66, 0x65, 0x74, 0x74, 0x6f,
- 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2e, 0x41, 0x6e, 0x64, 0x72,
- 0x6f, 0x69, 0x64, 0x50, 0x72, 0x6f, 0x63, 0x65, 0x73, 0x73, 0x4d, 0x65,
- 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x52, 0x0f, 0x70, 0x72, 0x6f, 0x63,
- 0x65, 0x73, 0x73, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x12,
- 0x1b, 0x0a, 0x09, 0x74, 0x79, 0x70, 0x65, 0x5f, 0x6e, 0x61, 0x6d, 0x65,
- 0x18, 0x02, 0x20, 0x03, 0x28, 0x09, 0x52, 0x08, 0x74, 0x79, 0x70, 0x65,
- 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x1d, 0x0a, 0x0a, 0x66, 0x69, 0x65, 0x6c,
- 0x64, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x03, 0x20, 0x03, 0x28, 0x09,
- 0x52, 0x09, 0x66, 0x69, 0x65, 0x6c, 0x64, 0x4e, 0x61, 0x6d, 0x65, 0x42,
- 0x02, 0x48, 0x03, 0x0a, 0x80, 0x02, 0x0a, 0x39, 0x70, 0x72, 0x6f, 0x74,
+ 0x64, 0x2f, 0x63, 0x70, 0x75, 0x5f, 0x6d, 0x65, 0x74, 0x72, 0x69, 0x63,
+ 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x30, 0x70, 0x72, 0x6f, 0x74,
0x6f, 0x73, 0x2f, 0x70, 0x65, 0x72, 0x66, 0x65, 0x74, 0x74, 0x6f, 0x2f,
0x6d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x73, 0x2f, 0x61, 0x6e, 0x64, 0x72,
- 0x6f, 0x69, 0x64, 0x2f, 0x75, 0x6e, 0x73, 0x79, 0x6d, 0x62, 0x6f, 0x6c,
- 0x69, 0x7a, 0x65, 0x64, 0x5f, 0x66, 0x72, 0x61, 0x6d, 0x65, 0x73, 0x2e,
- 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x0f, 0x70, 0x65, 0x72, 0x66, 0x65,
- 0x74, 0x74, 0x6f, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x22, 0xad,
- 0x01, 0x0a, 0x12, 0x55, 0x6e, 0x73, 0x79, 0x6d, 0x62, 0x6f, 0x6c, 0x69,
- 0x7a, 0x65, 0x64, 0x46, 0x72, 0x61, 0x6d, 0x65, 0x73, 0x12, 0x41, 0x0a,
- 0x06, 0x66, 0x72, 0x61, 0x6d, 0x65, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28,
- 0x0b, 0x32, 0x29, 0x2e, 0x70, 0x65, 0x72, 0x66, 0x65, 0x74, 0x74, 0x6f,
- 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2e, 0x55, 0x6e, 0x73, 0x79,
- 0x6d, 0x62, 0x6f, 0x6c, 0x69, 0x7a, 0x65, 0x64, 0x46, 0x72, 0x61, 0x6d,
- 0x65, 0x73, 0x2e, 0x46, 0x72, 0x61, 0x6d, 0x65, 0x52, 0x06, 0x66, 0x72,
- 0x61, 0x6d, 0x65, 0x73, 0x1a, 0x54, 0x0a, 0x05, 0x46, 0x72, 0x61, 0x6d,
- 0x65, 0x12, 0x16, 0x0a, 0x06, 0x6d, 0x6f, 0x64, 0x75, 0x6c, 0x65, 0x18,
- 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x6d, 0x6f, 0x64, 0x75, 0x6c,
- 0x65, 0x12, 0x19, 0x0a, 0x08, 0x62, 0x75, 0x69, 0x6c, 0x64, 0x5f, 0x69,
- 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x62, 0x75, 0x69,
- 0x6c, 0x64, 0x49, 0x64, 0x12, 0x18, 0x0a, 0x07, 0x61, 0x64, 0x64, 0x72,
- 0x65, 0x73, 0x73, 0x18, 0x03, 0x20, 0x01, 0x28, 0x03, 0x52, 0x07, 0x61,
- 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x42, 0x02, 0x48, 0x03, 0x0a, 0xfc,
- 0x03, 0x0a, 0x35, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2f, 0x70, 0x65,
- 0x72, 0x66, 0x65, 0x74, 0x74, 0x6f, 0x2f, 0x6d, 0x65, 0x74, 0x72, 0x69,
- 0x63, 0x73, 0x2f, 0x61, 0x6e, 0x64, 0x72, 0x6f, 0x69, 0x64, 0x2f, 0x6a,
- 0x61, 0x76, 0x61, 0x5f, 0x68, 0x65, 0x61, 0x70, 0x5f, 0x73, 0x74, 0x61,
- 0x74, 0x73, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x0f, 0x70, 0x65,
- 0x72, 0x66, 0x65, 0x74, 0x74, 0x6f, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f,
- 0x73, 0x1a, 0x36, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2f, 0x70, 0x65,
- 0x72, 0x66, 0x65, 0x74, 0x74, 0x6f, 0x2f, 0x6d, 0x65, 0x74, 0x72, 0x69,
- 0x63, 0x73, 0x2f, 0x61, 0x6e, 0x64, 0x72, 0x6f, 0x69, 0x64, 0x2f, 0x70,
- 0x72, 0x6f, 0x63, 0x65, 0x73, 0x73, 0x5f, 0x6d, 0x65, 0x74, 0x61, 0x64,
- 0x61, 0x74, 0x61, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x22, 0xf5, 0x02,
- 0x0a, 0x0d, 0x4a, 0x61, 0x76, 0x61, 0x48, 0x65, 0x61, 0x70, 0x53, 0x74,
- 0x61, 0x74, 0x73, 0x12, 0x53, 0x0a, 0x0e, 0x69, 0x6e, 0x73, 0x74, 0x61,
- 0x6e, 0x63, 0x65, 0x5f, 0x73, 0x74, 0x61, 0x74, 0x73, 0x18, 0x01, 0x20,
- 0x03, 0x28, 0x0b, 0x32, 0x2c, 0x2e, 0x70, 0x65, 0x72, 0x66, 0x65, 0x74,
- 0x74, 0x6f, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2e, 0x4a, 0x61,
- 0x76, 0x61, 0x48, 0x65, 0x61, 0x70, 0x53, 0x74, 0x61, 0x74, 0x73, 0x2e,
- 0x49, 0x6e, 0x73, 0x74, 0x61, 0x6e, 0x63, 0x65, 0x53, 0x74, 0x61, 0x74,
- 0x73, 0x52, 0x0d, 0x69, 0x6e, 0x73, 0x74, 0x61, 0x6e, 0x63, 0x65, 0x53,
- 0x74, 0x61, 0x74, 0x73, 0x1a, 0x65, 0x0a, 0x06, 0x53, 0x61, 0x6d, 0x70,
- 0x6c, 0x65, 0x12, 0x0e, 0x0a, 0x02, 0x74, 0x73, 0x18, 0x01, 0x20, 0x01,
- 0x28, 0x03, 0x52, 0x02, 0x74, 0x73, 0x12, 0x1b, 0x0a, 0x09, 0x68, 0x65,
- 0x61, 0x70, 0x5f, 0x73, 0x69, 0x7a, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28,
- 0x03, 0x52, 0x08, 0x68, 0x65, 0x61, 0x70, 0x53, 0x69, 0x7a, 0x65, 0x12,
- 0x2e, 0x0a, 0x13, 0x72, 0x65, 0x61, 0x63, 0x68, 0x61, 0x62, 0x6c, 0x65,
- 0x5f, 0x68, 0x65, 0x61, 0x70, 0x5f, 0x73, 0x69, 0x7a, 0x65, 0x18, 0x03,
- 0x20, 0x01, 0x28, 0x03, 0x52, 0x11, 0x72, 0x65, 0x61, 0x63, 0x68, 0x61,
- 0x62, 0x6c, 0x65, 0x48, 0x65, 0x61, 0x70, 0x53, 0x69, 0x7a, 0x65, 0x1a,
- 0xa7, 0x01, 0x0a, 0x0d, 0x49, 0x6e, 0x73, 0x74, 0x61, 0x6e, 0x63, 0x65,
- 0x53, 0x74, 0x61, 0x74, 0x73, 0x12, 0x12, 0x0a, 0x04, 0x75, 0x70, 0x69,
- 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x04, 0x75, 0x70, 0x69,
- 0x64, 0x12, 0x41, 0x0a, 0x07, 0x70, 0x72, 0x6f, 0x63, 0x65, 0x73, 0x73,
- 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x27, 0x2e, 0x70, 0x65, 0x72,
- 0x66, 0x65, 0x74, 0x74, 0x6f, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73,
- 0x2e, 0x41, 0x6e, 0x64, 0x72, 0x6f, 0x69, 0x64, 0x50, 0x72, 0x6f, 0x63,
- 0x65, 0x73, 0x73, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x52,
- 0x07, 0x70, 0x72, 0x6f, 0x63, 0x65, 0x73, 0x73, 0x12, 0x3f, 0x0a, 0x07,
- 0x73, 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x73, 0x18, 0x03, 0x20, 0x03, 0x28,
- 0x0b, 0x32, 0x25, 0x2e, 0x70, 0x65, 0x72, 0x66, 0x65, 0x74, 0x74, 0x6f,
- 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2e, 0x4a, 0x61, 0x76, 0x61,
- 0x48, 0x65, 0x61, 0x70, 0x53, 0x74, 0x61, 0x74, 0x73, 0x2e, 0x53, 0x61,
- 0x6d, 0x70, 0x6c, 0x65, 0x52, 0x07, 0x73, 0x61, 0x6d, 0x70, 0x6c, 0x65,
- 0x73, 0x42, 0x02, 0x48, 0x03, 0x0a, 0x8e, 0x13, 0x0a, 0x25, 0x70, 0x72,
- 0x6f, 0x74, 0x6f, 0x73, 0x2f, 0x70, 0x65, 0x72, 0x66, 0x65, 0x74, 0x74,
- 0x6f, 0x2f, 0x6d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x73, 0x2f, 0x6d, 0x65,
- 0x74, 0x72, 0x69, 0x63, 0x73, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12,
- 0x0f, 0x70, 0x65, 0x72, 0x66, 0x65, 0x74, 0x74, 0x6f, 0x2e, 0x70, 0x72,
- 0x6f, 0x74, 0x6f, 0x73, 0x1a, 0x31, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73,
- 0x2f, 0x70, 0x65, 0x72, 0x66, 0x65, 0x74, 0x74, 0x6f, 0x2f, 0x6d, 0x65,
- 0x74, 0x72, 0x69, 0x63, 0x73, 0x2f, 0x61, 0x6e, 0x64, 0x72, 0x6f, 0x69,
- 0x64, 0x2f, 0x62, 0x61, 0x74, 0x74, 0x5f, 0x6d, 0x65, 0x74, 0x72, 0x69,
- 0x63, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x30, 0x70, 0x72, 0x6f,
- 0x74, 0x6f, 0x73, 0x2f, 0x70, 0x65, 0x72, 0x66, 0x65, 0x74, 0x74, 0x6f,
- 0x2f, 0x6d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x73, 0x2f, 0x61, 0x6e, 0x64,
- 0x72, 0x6f, 0x69, 0x64, 0x2f, 0x63, 0x70, 0x75, 0x5f, 0x6d, 0x65, 0x74,
- 0x72, 0x69, 0x63, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x30, 0x70,
- 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2f, 0x70, 0x65, 0x72, 0x66, 0x65, 0x74,
- 0x74, 0x6f, 0x2f, 0x6d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x73, 0x2f, 0x61,
- 0x6e, 0x64, 0x72, 0x6f, 0x69, 0x64, 0x2f, 0x6d, 0x65, 0x6d, 0x5f, 0x6d,
- 0x65, 0x74, 0x72, 0x69, 0x63, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a,
- 0x36, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2f, 0x70, 0x65, 0x72, 0x66,
- 0x65, 0x74, 0x74, 0x6f, 0x2f, 0x6d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x73,
- 0x2f, 0x61, 0x6e, 0x64, 0x72, 0x6f, 0x69, 0x64, 0x2f, 0x6d, 0x65, 0x6d,
- 0x5f, 0x75, 0x6e, 0x61, 0x67, 0x67, 0x5f, 0x6d, 0x65, 0x74, 0x72, 0x69,
- 0x63, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x30, 0x70, 0x72, 0x6f,
- 0x74, 0x6f, 0x73, 0x2f, 0x70, 0x65, 0x72, 0x66, 0x65, 0x74, 0x74, 0x6f,
- 0x2f, 0x6d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x73, 0x2f, 0x61, 0x6e, 0x64,
- 0x72, 0x6f, 0x69, 0x64, 0x2f, 0x69, 0x6f, 0x6e, 0x5f, 0x6d, 0x65, 0x74,
- 0x72, 0x69, 0x63, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x30, 0x70,
- 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2f, 0x70, 0x65, 0x72, 0x66, 0x65, 0x74,
- 0x74, 0x6f, 0x2f, 0x6d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x73, 0x2f, 0x61,
- 0x6e, 0x64, 0x72, 0x6f, 0x69, 0x64, 0x2f, 0x6c, 0x6d, 0x6b, 0x5f, 0x6d,
- 0x65, 0x74, 0x72, 0x69, 0x63, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a,
- 0x37, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2f, 0x70, 0x65, 0x72, 0x66,
- 0x65, 0x74, 0x74, 0x6f, 0x2f, 0x6d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x73,
- 0x2f, 0x61, 0x6e, 0x64, 0x72, 0x6f, 0x69, 0x64, 0x2f, 0x6c, 0x6d, 0x6b,
- 0x5f, 0x72, 0x65, 0x61, 0x73, 0x6f, 0x6e, 0x5f, 0x6d, 0x65, 0x74, 0x72,
- 0x69, 0x63, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x35, 0x70, 0x72,
+ 0x6f, 0x69, 0x64, 0x2f, 0x6d, 0x65, 0x6d, 0x5f, 0x6d, 0x65, 0x74, 0x72,
+ 0x69, 0x63, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x36, 0x70, 0x72,
0x6f, 0x74, 0x6f, 0x73, 0x2f, 0x70, 0x65, 0x72, 0x66, 0x65, 0x74, 0x74,
0x6f, 0x2f, 0x6d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x73, 0x2f, 0x61, 0x6e,
- 0x64, 0x72, 0x6f, 0x69, 0x64, 0x2f, 0x70, 0x6f, 0x77, 0x72, 0x61, 0x69,
- 0x6c, 0x73, 0x5f, 0x6d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x2e, 0x70, 0x72,
- 0x6f, 0x74, 0x6f, 0x1a, 0x34, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2f,
- 0x70, 0x65, 0x72, 0x66, 0x65, 0x74, 0x74, 0x6f, 0x2f, 0x6d, 0x65, 0x74,
- 0x72, 0x69, 0x63, 0x73, 0x2f, 0x61, 0x6e, 0x64, 0x72, 0x6f, 0x69, 0x64,
- 0x2f, 0x73, 0x74, 0x61, 0x72, 0x74, 0x75, 0x70, 0x5f, 0x6d, 0x65, 0x74,
- 0x72, 0x69, 0x63, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x3c, 0x70,
- 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2f, 0x70, 0x65, 0x72, 0x66, 0x65, 0x74,
- 0x74, 0x6f, 0x2f, 0x6d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x73, 0x2f, 0x61,
- 0x6e, 0x64, 0x72, 0x6f, 0x69, 0x64, 0x2f, 0x68, 0x65, 0x61, 0x70, 0x5f,
- 0x70, 0x72, 0x6f, 0x66, 0x69, 0x6c, 0x65, 0x5f, 0x63, 0x61, 0x6c, 0x6c,
- 0x73, 0x69, 0x74, 0x65, 0x73, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a,
+ 0x64, 0x72, 0x6f, 0x69, 0x64, 0x2f, 0x6d, 0x65, 0x6d, 0x5f, 0x75, 0x6e,
+ 0x61, 0x67, 0x67, 0x5f, 0x6d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x2e, 0x70,
+ 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x30, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73,
+ 0x2f, 0x70, 0x65, 0x72, 0x66, 0x65, 0x74, 0x74, 0x6f, 0x2f, 0x6d, 0x65,
+ 0x74, 0x72, 0x69, 0x63, 0x73, 0x2f, 0x61, 0x6e, 0x64, 0x72, 0x6f, 0x69,
+ 0x64, 0x2f, 0x69, 0x6f, 0x6e, 0x5f, 0x6d, 0x65, 0x74, 0x72, 0x69, 0x63,
+ 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x30, 0x70, 0x72, 0x6f, 0x74,
+ 0x6f, 0x73, 0x2f, 0x70, 0x65, 0x72, 0x66, 0x65, 0x74, 0x74, 0x6f, 0x2f,
+ 0x6d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x73, 0x2f, 0x61, 0x6e, 0x64, 0x72,
+ 0x6f, 0x69, 0x64, 0x2f, 0x6c, 0x6d, 0x6b, 0x5f, 0x6d, 0x65, 0x74, 0x72,
+ 0x69, 0x63, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x37, 0x70, 0x72,
+ 0x6f, 0x74, 0x6f, 0x73, 0x2f, 0x70, 0x65, 0x72, 0x66, 0x65, 0x74, 0x74,
+ 0x6f, 0x2f, 0x6d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x73, 0x2f, 0x61, 0x6e,
+ 0x64, 0x72, 0x6f, 0x69, 0x64, 0x2f, 0x6c, 0x6d, 0x6b, 0x5f, 0x72, 0x65,
+ 0x61, 0x73, 0x6f, 0x6e, 0x5f, 0x6d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x2e,
+ 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x35, 0x70, 0x72, 0x6f, 0x74, 0x6f,
+ 0x73, 0x2f, 0x70, 0x65, 0x72, 0x66, 0x65, 0x74, 0x74, 0x6f, 0x2f, 0x6d,
+ 0x65, 0x74, 0x72, 0x69, 0x63, 0x73, 0x2f, 0x61, 0x6e, 0x64, 0x72, 0x6f,
+ 0x69, 0x64, 0x2f, 0x70, 0x6f, 0x77, 0x72, 0x61, 0x69, 0x6c, 0x73, 0x5f,
+ 0x6d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f,
+ 0x1a, 0x34, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2f, 0x70, 0x65, 0x72,
+ 0x66, 0x65, 0x74, 0x74, 0x6f, 0x2f, 0x6d, 0x65, 0x74, 0x72, 0x69, 0x63,
+ 0x73, 0x2f, 0x61, 0x6e, 0x64, 0x72, 0x6f, 0x69, 0x64, 0x2f, 0x73, 0x74,
+ 0x61, 0x72, 0x74, 0x75, 0x70, 0x5f, 0x6d, 0x65, 0x74, 0x72, 0x69, 0x63,
+ 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x3c, 0x70, 0x72, 0x6f, 0x74,
+ 0x6f, 0x73, 0x2f, 0x70, 0x65, 0x72, 0x66, 0x65, 0x74, 0x74, 0x6f, 0x2f,
+ 0x6d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x73, 0x2f, 0x61, 0x6e, 0x64, 0x72,
+ 0x6f, 0x69, 0x64, 0x2f, 0x68, 0x65, 0x61, 0x70, 0x5f, 0x70, 0x72, 0x6f,
+ 0x66, 0x69, 0x6c, 0x65, 0x5f, 0x63, 0x61, 0x6c, 0x6c, 0x73, 0x69, 0x74,
+ 0x65, 0x73, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x31, 0x70, 0x72,
+ 0x6f, 0x74, 0x6f, 0x73, 0x2f, 0x70, 0x65, 0x72, 0x66, 0x65, 0x74, 0x74,
+ 0x6f, 0x2f, 0x6d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x73, 0x2f, 0x61, 0x6e,
+ 0x64, 0x72, 0x6f, 0x69, 0x64, 0x2f, 0x68, 0x77, 0x75, 0x69, 0x5f, 0x6d,
+ 0x65, 0x74, 0x72, 0x69, 0x63, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a,
0x32, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2f, 0x70, 0x65, 0x72, 0x66,
0x65, 0x74, 0x74, 0x6f, 0x2f, 0x6d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x73,
0x2f, 0x61, 0x6e, 0x64, 0x72, 0x6f, 0x69, 0x64, 0x2f, 0x70, 0x61, 0x63,
@@ -900,8 +1060,8 @@
0x70, 0x65, 0x72, 0x66, 0x65, 0x74, 0x74, 0x6f, 0x2f, 0x6d, 0x65, 0x74,
0x72, 0x69, 0x63, 0x73, 0x2f, 0x61, 0x6e, 0x64, 0x72, 0x6f, 0x69, 0x64,
0x2f, 0x6a, 0x61, 0x76, 0x61, 0x5f, 0x68, 0x65, 0x61, 0x70, 0x5f, 0x73,
- 0x74, 0x61, 0x74, 0x73, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x22, 0xf8,
- 0x02, 0x0a, 0x0d, 0x54, 0x72, 0x61, 0x63, 0x65, 0x4d, 0x65, 0x74, 0x61,
+ 0x74, 0x61, 0x74, 0x73, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x22, 0xa2,
+ 0x03, 0x0a, 0x0d, 0x54, 0x72, 0x61, 0x63, 0x65, 0x4d, 0x65, 0x74, 0x61,
0x64, 0x61, 0x74, 0x61, 0x12, 0x50, 0x0a, 0x11, 0x65, 0x72, 0x72, 0x6f,
0x72, 0x5f, 0x73, 0x74, 0x61, 0x74, 0x73, 0x5f, 0x65, 0x6e, 0x74, 0x72,
0x79, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x24, 0x2e, 0x70, 0x65,
@@ -926,117 +1086,127 @@
0x69, 0x6f, 0x6e, 0x5f, 0x69, 0x64, 0x18, 0x05, 0x20, 0x01, 0x28, 0x03,
0x52, 0x1e, 0x73, 0x74, 0x61, 0x74, 0x73, 0x64, 0x54, 0x72, 0x69, 0x67,
0x67, 0x65, 0x72, 0x69, 0x6e, 0x67, 0x53, 0x75, 0x62, 0x73, 0x63, 0x72,
- 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x49, 0x64, 0x1a, 0x43, 0x0a, 0x05,
- 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d,
- 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d,
- 0x65, 0x12, 0x10, 0x0a, 0x03, 0x69, 0x64, 0x78, 0x18, 0x02, 0x20, 0x01,
- 0x28, 0x0d, 0x52, 0x03, 0x69, 0x64, 0x78, 0x12, 0x14, 0x0a, 0x05, 0x76,
- 0x61, 0x6c, 0x75, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x03, 0x52, 0x05,
- 0x76, 0x61, 0x6c, 0x75, 0x65, 0x22, 0xda, 0x09, 0x0a, 0x0c, 0x54, 0x72,
- 0x61, 0x63, 0x65, 0x4d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x73, 0x12, 0x48,
- 0x0a, 0x0c, 0x61, 0x6e, 0x64, 0x72, 0x6f, 0x69, 0x64, 0x5f, 0x62, 0x61,
- 0x74, 0x74, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x25, 0x2e, 0x70,
- 0x65, 0x72, 0x66, 0x65, 0x74, 0x74, 0x6f, 0x2e, 0x70, 0x72, 0x6f, 0x74,
- 0x6f, 0x73, 0x2e, 0x41, 0x6e, 0x64, 0x72, 0x6f, 0x69, 0x64, 0x42, 0x61,
- 0x74, 0x74, 0x65, 0x72, 0x79, 0x4d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x52,
- 0x0b, 0x61, 0x6e, 0x64, 0x72, 0x6f, 0x69, 0x64, 0x42, 0x61, 0x74, 0x74,
- 0x12, 0x42, 0x0a, 0x0b, 0x61, 0x6e, 0x64, 0x72, 0x6f, 0x69, 0x64, 0x5f,
- 0x63, 0x70, 0x75, 0x18, 0x06, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x21, 0x2e,
- 0x70, 0x65, 0x72, 0x66, 0x65, 0x74, 0x74, 0x6f, 0x2e, 0x70, 0x72, 0x6f,
- 0x74, 0x6f, 0x73, 0x2e, 0x41, 0x6e, 0x64, 0x72, 0x6f, 0x69, 0x64, 0x43,
- 0x70, 0x75, 0x4d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x52, 0x0a, 0x61, 0x6e,
- 0x64, 0x72, 0x6f, 0x69, 0x64, 0x43, 0x70, 0x75, 0x12, 0x45, 0x0a, 0x0b,
- 0x61, 0x6e, 0x64, 0x72, 0x6f, 0x69, 0x64, 0x5f, 0x6d, 0x65, 0x6d, 0x18,
- 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x24, 0x2e, 0x70, 0x65, 0x72, 0x66,
- 0x65, 0x74, 0x74, 0x6f, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2e,
- 0x41, 0x6e, 0x64, 0x72, 0x6f, 0x69, 0x64, 0x4d, 0x65, 0x6d, 0x6f, 0x72,
- 0x79, 0x4d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x52, 0x0a, 0x61, 0x6e, 0x64,
- 0x72, 0x6f, 0x69, 0x64, 0x4d, 0x65, 0x6d, 0x12, 0x5c, 0x0a, 0x11, 0x61,
- 0x6e, 0x64, 0x72, 0x6f, 0x69, 0x64, 0x5f, 0x6d, 0x65, 0x6d, 0x5f, 0x75,
- 0x6e, 0x61, 0x67, 0x67, 0x18, 0x0b, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x30,
- 0x2e, 0x70, 0x65, 0x72, 0x66, 0x65, 0x74, 0x74, 0x6f, 0x2e, 0x70, 0x72,
- 0x6f, 0x74, 0x6f, 0x73, 0x2e, 0x41, 0x6e, 0x64, 0x72, 0x6f, 0x69, 0x64,
- 0x4d, 0x65, 0x6d, 0x6f, 0x72, 0x79, 0x55, 0x6e, 0x61, 0x67, 0x67, 0x72,
- 0x65, 0x67, 0x61, 0x74, 0x65, 0x64, 0x4d, 0x65, 0x74, 0x72, 0x69, 0x63,
- 0x52, 0x0f, 0x61, 0x6e, 0x64, 0x72, 0x6f, 0x69, 0x64, 0x4d, 0x65, 0x6d,
- 0x55, 0x6e, 0x61, 0x67, 0x67, 0x12, 0x55, 0x0a, 0x14, 0x61, 0x6e, 0x64,
- 0x72, 0x6f, 0x69, 0x64, 0x5f, 0x70, 0x61, 0x63, 0x6b, 0x61, 0x67, 0x65,
- 0x5f, 0x6c, 0x69, 0x73, 0x74, 0x18, 0x0c, 0x20, 0x01, 0x28, 0x0b, 0x32,
- 0x23, 0x2e, 0x70, 0x65, 0x72, 0x66, 0x65, 0x74, 0x74, 0x6f, 0x2e, 0x70,
- 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2e, 0x41, 0x6e, 0x64, 0x72, 0x6f, 0x69,
- 0x64, 0x50, 0x61, 0x63, 0x6b, 0x61, 0x67, 0x65, 0x4c, 0x69, 0x73, 0x74,
- 0x52, 0x12, 0x61, 0x6e, 0x64, 0x72, 0x6f, 0x69, 0x64, 0x50, 0x61, 0x63,
- 0x6b, 0x61, 0x67, 0x65, 0x4c, 0x69, 0x73, 0x74, 0x12, 0x42, 0x0a, 0x0b,
- 0x61, 0x6e, 0x64, 0x72, 0x6f, 0x69, 0x64, 0x5f, 0x69, 0x6f, 0x6e, 0x18,
- 0x09, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x21, 0x2e, 0x70, 0x65, 0x72, 0x66,
- 0x65, 0x74, 0x74, 0x6f, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2e,
- 0x41, 0x6e, 0x64, 0x72, 0x6f, 0x69, 0x64, 0x49, 0x6f, 0x6e, 0x4d, 0x65,
- 0x74, 0x72, 0x69, 0x63, 0x52, 0x0a, 0x61, 0x6e, 0x64, 0x72, 0x6f, 0x69,
- 0x64, 0x49, 0x6f, 0x6e, 0x12, 0x42, 0x0a, 0x0b, 0x61, 0x6e, 0x64, 0x72,
- 0x6f, 0x69, 0x64, 0x5f, 0x6c, 0x6d, 0x6b, 0x18, 0x08, 0x20, 0x01, 0x28,
- 0x0b, 0x32, 0x21, 0x2e, 0x70, 0x65, 0x72, 0x66, 0x65, 0x74, 0x74, 0x6f,
- 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2e, 0x41, 0x6e, 0x64, 0x72,
- 0x6f, 0x69, 0x64, 0x4c, 0x6d, 0x6b, 0x4d, 0x65, 0x74, 0x72, 0x69, 0x63,
- 0x52, 0x0a, 0x61, 0x6e, 0x64, 0x72, 0x6f, 0x69, 0x64, 0x4c, 0x6d, 0x6b,
- 0x12, 0x4d, 0x0a, 0x10, 0x61, 0x6e, 0x64, 0x72, 0x6f, 0x69, 0x64, 0x5f,
- 0x70, 0x6f, 0x77, 0x72, 0x61, 0x69, 0x6c, 0x73, 0x18, 0x07, 0x20, 0x01,
- 0x28, 0x0b, 0x32, 0x22, 0x2e, 0x70, 0x65, 0x72, 0x66, 0x65, 0x74, 0x74,
+ 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x49, 0x64, 0x12, 0x28, 0x0a, 0x10,
+ 0x74, 0x72, 0x61, 0x63, 0x65, 0x5f, 0x73, 0x69, 0x7a, 0x65, 0x5f, 0x62,
+ 0x79, 0x74, 0x65, 0x73, 0x18, 0x06, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0e,
+ 0x74, 0x72, 0x61, 0x63, 0x65, 0x53, 0x69, 0x7a, 0x65, 0x42, 0x79, 0x74,
+ 0x65, 0x73, 0x1a, 0x43, 0x0a, 0x05, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12,
+ 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28,
+ 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x10, 0x0a, 0x03, 0x69,
+ 0x64, 0x78, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x03, 0x69, 0x64,
+ 0x78, 0x12, 0x14, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x03,
+ 0x20, 0x01, 0x28, 0x03, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x22,
+ 0xae, 0x0a, 0x0a, 0x0c, 0x54, 0x72, 0x61, 0x63, 0x65, 0x4d, 0x65, 0x74,
+ 0x72, 0x69, 0x63, 0x73, 0x12, 0x48, 0x0a, 0x0c, 0x61, 0x6e, 0x64, 0x72,
+ 0x6f, 0x69, 0x64, 0x5f, 0x62, 0x61, 0x74, 0x74, 0x18, 0x05, 0x20, 0x01,
+ 0x28, 0x0b, 0x32, 0x25, 0x2e, 0x70, 0x65, 0x72, 0x66, 0x65, 0x74, 0x74,
0x6f, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2e, 0x41, 0x6e, 0x64,
- 0x72, 0x6f, 0x69, 0x64, 0x50, 0x6f, 0x77, 0x65, 0x72, 0x52, 0x61, 0x69,
- 0x6c, 0x73, 0x52, 0x0f, 0x61, 0x6e, 0x64, 0x72, 0x6f, 0x69, 0x64, 0x50,
- 0x6f, 0x77, 0x72, 0x61, 0x69, 0x6c, 0x73, 0x12, 0x4e, 0x0a, 0x0f, 0x61,
- 0x6e, 0x64, 0x72, 0x6f, 0x69, 0x64, 0x5f, 0x73, 0x74, 0x61, 0x72, 0x74,
- 0x75, 0x70, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x25, 0x2e, 0x70,
- 0x65, 0x72, 0x66, 0x65, 0x74, 0x74, 0x6f, 0x2e, 0x70, 0x72, 0x6f, 0x74,
- 0x6f, 0x73, 0x2e, 0x41, 0x6e, 0x64, 0x72, 0x6f, 0x69, 0x64, 0x53, 0x74,
- 0x61, 0x72, 0x74, 0x75, 0x70, 0x4d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x52,
- 0x0e, 0x61, 0x6e, 0x64, 0x72, 0x6f, 0x69, 0x64, 0x53, 0x74, 0x61, 0x72,
- 0x74, 0x75, 0x70, 0x12, 0x5b, 0x0a, 0x16, 0x68, 0x65, 0x61, 0x70, 0x5f,
- 0x70, 0x72, 0x6f, 0x66, 0x69, 0x6c, 0x65, 0x5f, 0x63, 0x61, 0x6c, 0x6c,
- 0x73, 0x69, 0x74, 0x65, 0x73, 0x18, 0x10, 0x20, 0x01, 0x28, 0x0b, 0x32,
- 0x25, 0x2e, 0x70, 0x65, 0x72, 0x66, 0x65, 0x74, 0x74, 0x6f, 0x2e, 0x70,
- 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2e, 0x48, 0x65, 0x61, 0x70, 0x50, 0x72,
- 0x6f, 0x66, 0x69, 0x6c, 0x65, 0x43, 0x61, 0x6c, 0x6c, 0x73, 0x69, 0x74,
- 0x65, 0x73, 0x52, 0x14, 0x68, 0x65, 0x61, 0x70, 0x50, 0x72, 0x6f, 0x66,
- 0x69, 0x6c, 0x65, 0x43, 0x61, 0x6c, 0x6c, 0x73, 0x69, 0x74, 0x65, 0x73,
- 0x12, 0x45, 0x0a, 0x0e, 0x74, 0x72, 0x61, 0x63, 0x65, 0x5f, 0x6d, 0x65,
- 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b,
- 0x32, 0x1e, 0x2e, 0x70, 0x65, 0x72, 0x66, 0x65, 0x74, 0x74, 0x6f, 0x2e,
- 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2e, 0x54, 0x72, 0x61, 0x63, 0x65,
- 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x52, 0x0d, 0x74, 0x72,
- 0x61, 0x63, 0x65, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x12,
- 0x54, 0x0a, 0x13, 0x75, 0x6e, 0x73, 0x79, 0x6d, 0x62, 0x6f, 0x6c, 0x69,
- 0x7a, 0x65, 0x64, 0x5f, 0x66, 0x72, 0x61, 0x6d, 0x65, 0x73, 0x18, 0x0f,
- 0x20, 0x01, 0x28, 0x0b, 0x32, 0x23, 0x2e, 0x70, 0x65, 0x72, 0x66, 0x65,
- 0x74, 0x74, 0x6f, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2e, 0x55,
- 0x6e, 0x73, 0x79, 0x6d, 0x62, 0x6f, 0x6c, 0x69, 0x7a, 0x65, 0x64, 0x46,
- 0x72, 0x61, 0x6d, 0x65, 0x73, 0x52, 0x12, 0x75, 0x6e, 0x73, 0x79, 0x6d,
- 0x62, 0x6f, 0x6c, 0x69, 0x7a, 0x65, 0x64, 0x46, 0x72, 0x61, 0x6d, 0x65,
- 0x73, 0x12, 0x46, 0x0a, 0x0f, 0x6a, 0x61, 0x76, 0x61, 0x5f, 0x68, 0x65,
- 0x61, 0x70, 0x5f, 0x73, 0x74, 0x61, 0x74, 0x73, 0x18, 0x11, 0x20, 0x01,
- 0x28, 0x0b, 0x32, 0x1e, 0x2e, 0x70, 0x65, 0x72, 0x66, 0x65, 0x74, 0x74,
- 0x6f, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2e, 0x4a, 0x61, 0x76,
- 0x61, 0x48, 0x65, 0x61, 0x70, 0x53, 0x74, 0x61, 0x74, 0x73, 0x52, 0x0d,
- 0x6a, 0x61, 0x76, 0x61, 0x48, 0x65, 0x61, 0x70, 0x53, 0x74, 0x61, 0x74,
- 0x73, 0x12, 0x55, 0x0a, 0x12, 0x61, 0x6e, 0x64, 0x72, 0x6f, 0x69, 0x64,
- 0x5f, 0x6c, 0x6d, 0x6b, 0x5f, 0x72, 0x65, 0x61, 0x73, 0x6f, 0x6e, 0x18,
- 0x12, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x27, 0x2e, 0x70, 0x65, 0x72, 0x66,
- 0x65, 0x74, 0x74, 0x6f, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2e,
- 0x41, 0x6e, 0x64, 0x72, 0x6f, 0x69, 0x64, 0x4c, 0x6d, 0x6b, 0x52, 0x65,
- 0x61, 0x73, 0x6f, 0x6e, 0x4d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x52, 0x10,
- 0x61, 0x6e, 0x64, 0x72, 0x6f, 0x69, 0x64, 0x4c, 0x6d, 0x6b, 0x52, 0x65,
- 0x61, 0x73, 0x6f, 0x6e, 0x12, 0x58, 0x0a, 0x15, 0x75, 0x6e, 0x6d, 0x61,
- 0x70, 0x70, 0x65, 0x64, 0x5f, 0x6a, 0x61, 0x76, 0x61, 0x5f, 0x73, 0x79,
- 0x6d, 0x62, 0x6f, 0x6c, 0x73, 0x18, 0x13, 0x20, 0x01, 0x28, 0x0b, 0x32,
+ 0x72, 0x6f, 0x69, 0x64, 0x42, 0x61, 0x74, 0x74, 0x65, 0x72, 0x79, 0x4d,
+ 0x65, 0x74, 0x72, 0x69, 0x63, 0x52, 0x0b, 0x61, 0x6e, 0x64, 0x72, 0x6f,
+ 0x69, 0x64, 0x42, 0x61, 0x74, 0x74, 0x12, 0x42, 0x0a, 0x0b, 0x61, 0x6e,
+ 0x64, 0x72, 0x6f, 0x69, 0x64, 0x5f, 0x63, 0x70, 0x75, 0x18, 0x06, 0x20,
+ 0x01, 0x28, 0x0b, 0x32, 0x21, 0x2e, 0x70, 0x65, 0x72, 0x66, 0x65, 0x74,
+ 0x74, 0x6f, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2e, 0x41, 0x6e,
+ 0x64, 0x72, 0x6f, 0x69, 0x64, 0x43, 0x70, 0x75, 0x4d, 0x65, 0x74, 0x72,
+ 0x69, 0x63, 0x52, 0x0a, 0x61, 0x6e, 0x64, 0x72, 0x6f, 0x69, 0x64, 0x43,
+ 0x70, 0x75, 0x12, 0x45, 0x0a, 0x0b, 0x61, 0x6e, 0x64, 0x72, 0x6f, 0x69,
+ 0x64, 0x5f, 0x6d, 0x65, 0x6d, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32,
0x24, 0x2e, 0x70, 0x65, 0x72, 0x66, 0x65, 0x74, 0x74, 0x6f, 0x2e, 0x70,
- 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2e, 0x55, 0x6e, 0x6d, 0x61, 0x70, 0x70,
- 0x65, 0x64, 0x4a, 0x61, 0x76, 0x61, 0x53, 0x79, 0x6d, 0x62, 0x6f, 0x6c,
- 0x73, 0x52, 0x13, 0x75, 0x6e, 0x6d, 0x61, 0x70, 0x70, 0x65, 0x64, 0x4a,
- 0x61, 0x76, 0x61, 0x53, 0x79, 0x6d, 0x62, 0x6f, 0x6c, 0x73, 0x2a, 0x06,
- 0x08, 0xc2, 0x03, 0x10, 0xf4, 0x03, 0x2a, 0x06, 0x08, 0xf4, 0x03, 0x10,
- 0xe9, 0x07, 0x4a, 0x04, 0x08, 0x04, 0x10, 0x05, 0x4a, 0x04, 0x08, 0x0a,
- 0x10, 0x0b, 0x4a, 0x04, 0x08, 0x0d, 0x10, 0x0e, 0x4a, 0x04, 0x08, 0x0e,
- 0x10, 0x0f, 0x42, 0x02, 0x48, 0x03}};
+ 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2e, 0x41, 0x6e, 0x64, 0x72, 0x6f, 0x69,
+ 0x64, 0x4d, 0x65, 0x6d, 0x6f, 0x72, 0x79, 0x4d, 0x65, 0x74, 0x72, 0x69,
+ 0x63, 0x52, 0x0a, 0x61, 0x6e, 0x64, 0x72, 0x6f, 0x69, 0x64, 0x4d, 0x65,
+ 0x6d, 0x12, 0x5c, 0x0a, 0x11, 0x61, 0x6e, 0x64, 0x72, 0x6f, 0x69, 0x64,
+ 0x5f, 0x6d, 0x65, 0x6d, 0x5f, 0x75, 0x6e, 0x61, 0x67, 0x67, 0x18, 0x0b,
+ 0x20, 0x01, 0x28, 0x0b, 0x32, 0x30, 0x2e, 0x70, 0x65, 0x72, 0x66, 0x65,
+ 0x74, 0x74, 0x6f, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2e, 0x41,
+ 0x6e, 0x64, 0x72, 0x6f, 0x69, 0x64, 0x4d, 0x65, 0x6d, 0x6f, 0x72, 0x79,
+ 0x55, 0x6e, 0x61, 0x67, 0x67, 0x72, 0x65, 0x67, 0x61, 0x74, 0x65, 0x64,
+ 0x4d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x52, 0x0f, 0x61, 0x6e, 0x64, 0x72,
+ 0x6f, 0x69, 0x64, 0x4d, 0x65, 0x6d, 0x55, 0x6e, 0x61, 0x67, 0x67, 0x12,
+ 0x55, 0x0a, 0x14, 0x61, 0x6e, 0x64, 0x72, 0x6f, 0x69, 0x64, 0x5f, 0x70,
+ 0x61, 0x63, 0x6b, 0x61, 0x67, 0x65, 0x5f, 0x6c, 0x69, 0x73, 0x74, 0x18,
+ 0x0c, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x23, 0x2e, 0x70, 0x65, 0x72, 0x66,
+ 0x65, 0x74, 0x74, 0x6f, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2e,
+ 0x41, 0x6e, 0x64, 0x72, 0x6f, 0x69, 0x64, 0x50, 0x61, 0x63, 0x6b, 0x61,
+ 0x67, 0x65, 0x4c, 0x69, 0x73, 0x74, 0x52, 0x12, 0x61, 0x6e, 0x64, 0x72,
+ 0x6f, 0x69, 0x64, 0x50, 0x61, 0x63, 0x6b, 0x61, 0x67, 0x65, 0x4c, 0x69,
+ 0x73, 0x74, 0x12, 0x42, 0x0a, 0x0b, 0x61, 0x6e, 0x64, 0x72, 0x6f, 0x69,
+ 0x64, 0x5f, 0x69, 0x6f, 0x6e, 0x18, 0x09, 0x20, 0x01, 0x28, 0x0b, 0x32,
+ 0x21, 0x2e, 0x70, 0x65, 0x72, 0x66, 0x65, 0x74, 0x74, 0x6f, 0x2e, 0x70,
+ 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2e, 0x41, 0x6e, 0x64, 0x72, 0x6f, 0x69,
+ 0x64, 0x49, 0x6f, 0x6e, 0x4d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x52, 0x0a,
+ 0x61, 0x6e, 0x64, 0x72, 0x6f, 0x69, 0x64, 0x49, 0x6f, 0x6e, 0x12, 0x42,
+ 0x0a, 0x0b, 0x61, 0x6e, 0x64, 0x72, 0x6f, 0x69, 0x64, 0x5f, 0x6c, 0x6d,
+ 0x6b, 0x18, 0x08, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x21, 0x2e, 0x70, 0x65,
+ 0x72, 0x66, 0x65, 0x74, 0x74, 0x6f, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f,
+ 0x73, 0x2e, 0x41, 0x6e, 0x64, 0x72, 0x6f, 0x69, 0x64, 0x4c, 0x6d, 0x6b,
+ 0x4d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x52, 0x0a, 0x61, 0x6e, 0x64, 0x72,
+ 0x6f, 0x69, 0x64, 0x4c, 0x6d, 0x6b, 0x12, 0x4d, 0x0a, 0x10, 0x61, 0x6e,
+ 0x64, 0x72, 0x6f, 0x69, 0x64, 0x5f, 0x70, 0x6f, 0x77, 0x72, 0x61, 0x69,
+ 0x6c, 0x73, 0x18, 0x07, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x22, 0x2e, 0x70,
+ 0x65, 0x72, 0x66, 0x65, 0x74, 0x74, 0x6f, 0x2e, 0x70, 0x72, 0x6f, 0x74,
+ 0x6f, 0x73, 0x2e, 0x41, 0x6e, 0x64, 0x72, 0x6f, 0x69, 0x64, 0x50, 0x6f,
+ 0x77, 0x65, 0x72, 0x52, 0x61, 0x69, 0x6c, 0x73, 0x52, 0x0f, 0x61, 0x6e,
+ 0x64, 0x72, 0x6f, 0x69, 0x64, 0x50, 0x6f, 0x77, 0x72, 0x61, 0x69, 0x6c,
+ 0x73, 0x12, 0x4e, 0x0a, 0x0f, 0x61, 0x6e, 0x64, 0x72, 0x6f, 0x69, 0x64,
+ 0x5f, 0x73, 0x74, 0x61, 0x72, 0x74, 0x75, 0x70, 0x18, 0x02, 0x20, 0x01,
+ 0x28, 0x0b, 0x32, 0x25, 0x2e, 0x70, 0x65, 0x72, 0x66, 0x65, 0x74, 0x74,
+ 0x6f, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2e, 0x41, 0x6e, 0x64,
+ 0x72, 0x6f, 0x69, 0x64, 0x53, 0x74, 0x61, 0x72, 0x74, 0x75, 0x70, 0x4d,
+ 0x65, 0x74, 0x72, 0x69, 0x63, 0x52, 0x0e, 0x61, 0x6e, 0x64, 0x72, 0x6f,
+ 0x69, 0x64, 0x53, 0x74, 0x61, 0x72, 0x74, 0x75, 0x70, 0x12, 0x5b, 0x0a,
+ 0x16, 0x68, 0x65, 0x61, 0x70, 0x5f, 0x70, 0x72, 0x6f, 0x66, 0x69, 0x6c,
+ 0x65, 0x5f, 0x63, 0x61, 0x6c, 0x6c, 0x73, 0x69, 0x74, 0x65, 0x73, 0x18,
+ 0x10, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x25, 0x2e, 0x70, 0x65, 0x72, 0x66,
+ 0x65, 0x74, 0x74, 0x6f, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2e,
+ 0x48, 0x65, 0x61, 0x70, 0x50, 0x72, 0x6f, 0x66, 0x69, 0x6c, 0x65, 0x43,
+ 0x61, 0x6c, 0x6c, 0x73, 0x69, 0x74, 0x65, 0x73, 0x52, 0x14, 0x68, 0x65,
+ 0x61, 0x70, 0x50, 0x72, 0x6f, 0x66, 0x69, 0x6c, 0x65, 0x43, 0x61, 0x6c,
+ 0x6c, 0x73, 0x69, 0x74, 0x65, 0x73, 0x12, 0x45, 0x0a, 0x0e, 0x74, 0x72,
+ 0x61, 0x63, 0x65, 0x5f, 0x6d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61,
+ 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1e, 0x2e, 0x70, 0x65, 0x72,
+ 0x66, 0x65, 0x74, 0x74, 0x6f, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73,
+ 0x2e, 0x54, 0x72, 0x61, 0x63, 0x65, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61,
+ 0x74, 0x61, 0x52, 0x0d, 0x74, 0x72, 0x61, 0x63, 0x65, 0x4d, 0x65, 0x74,
+ 0x61, 0x64, 0x61, 0x74, 0x61, 0x12, 0x54, 0x0a, 0x13, 0x75, 0x6e, 0x73,
+ 0x79, 0x6d, 0x62, 0x6f, 0x6c, 0x69, 0x7a, 0x65, 0x64, 0x5f, 0x66, 0x72,
+ 0x61, 0x6d, 0x65, 0x73, 0x18, 0x0f, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x23,
+ 0x2e, 0x70, 0x65, 0x72, 0x66, 0x65, 0x74, 0x74, 0x6f, 0x2e, 0x70, 0x72,
+ 0x6f, 0x74, 0x6f, 0x73, 0x2e, 0x55, 0x6e, 0x73, 0x79, 0x6d, 0x62, 0x6f,
+ 0x6c, 0x69, 0x7a, 0x65, 0x64, 0x46, 0x72, 0x61, 0x6d, 0x65, 0x73, 0x52,
+ 0x12, 0x75, 0x6e, 0x73, 0x79, 0x6d, 0x62, 0x6f, 0x6c, 0x69, 0x7a, 0x65,
+ 0x64, 0x46, 0x72, 0x61, 0x6d, 0x65, 0x73, 0x12, 0x46, 0x0a, 0x0f, 0x6a,
+ 0x61, 0x76, 0x61, 0x5f, 0x68, 0x65, 0x61, 0x70, 0x5f, 0x73, 0x74, 0x61,
+ 0x74, 0x73, 0x18, 0x11, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1e, 0x2e, 0x70,
+ 0x65, 0x72, 0x66, 0x65, 0x74, 0x74, 0x6f, 0x2e, 0x70, 0x72, 0x6f, 0x74,
+ 0x6f, 0x73, 0x2e, 0x4a, 0x61, 0x76, 0x61, 0x48, 0x65, 0x61, 0x70, 0x53,
+ 0x74, 0x61, 0x74, 0x73, 0x52, 0x0d, 0x6a, 0x61, 0x76, 0x61, 0x48, 0x65,
+ 0x61, 0x70, 0x53, 0x74, 0x61, 0x74, 0x73, 0x12, 0x55, 0x0a, 0x12, 0x61,
+ 0x6e, 0x64, 0x72, 0x6f, 0x69, 0x64, 0x5f, 0x6c, 0x6d, 0x6b, 0x5f, 0x72,
+ 0x65, 0x61, 0x73, 0x6f, 0x6e, 0x18, 0x12, 0x20, 0x01, 0x28, 0x0b, 0x32,
+ 0x27, 0x2e, 0x70, 0x65, 0x72, 0x66, 0x65, 0x74, 0x74, 0x6f, 0x2e, 0x70,
+ 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2e, 0x41, 0x6e, 0x64, 0x72, 0x6f, 0x69,
+ 0x64, 0x4c, 0x6d, 0x6b, 0x52, 0x65, 0x61, 0x73, 0x6f, 0x6e, 0x4d, 0x65,
+ 0x74, 0x72, 0x69, 0x63, 0x52, 0x10, 0x61, 0x6e, 0x64, 0x72, 0x6f, 0x69,
+ 0x64, 0x4c, 0x6d, 0x6b, 0x52, 0x65, 0x61, 0x73, 0x6f, 0x6e, 0x12, 0x58,
+ 0x0a, 0x15, 0x75, 0x6e, 0x6d, 0x61, 0x70, 0x70, 0x65, 0x64, 0x5f, 0x6a,
+ 0x61, 0x76, 0x61, 0x5f, 0x73, 0x79, 0x6d, 0x62, 0x6f, 0x6c, 0x73, 0x18,
+ 0x13, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x24, 0x2e, 0x70, 0x65, 0x72, 0x66,
+ 0x65, 0x74, 0x74, 0x6f, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2e,
+ 0x55, 0x6e, 0x6d, 0x61, 0x70, 0x70, 0x65, 0x64, 0x4a, 0x61, 0x76, 0x61,
+ 0x53, 0x79, 0x6d, 0x62, 0x6f, 0x6c, 0x73, 0x52, 0x13, 0x75, 0x6e, 0x6d,
+ 0x61, 0x70, 0x70, 0x65, 0x64, 0x4a, 0x61, 0x76, 0x61, 0x53, 0x79, 0x6d,
+ 0x62, 0x6f, 0x6c, 0x73, 0x12, 0x52, 0x0a, 0x13, 0x61, 0x6e, 0x64, 0x72,
+ 0x6f, 0x69, 0x64, 0x5f, 0x68, 0x77, 0x75, 0x69, 0x5f, 0x6d, 0x65, 0x74,
+ 0x72, 0x69, 0x63, 0x18, 0x14, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x22, 0x2e,
+ 0x70, 0x65, 0x72, 0x66, 0x65, 0x74, 0x74, 0x6f, 0x2e, 0x70, 0x72, 0x6f,
+ 0x74, 0x6f, 0x73, 0x2e, 0x41, 0x6e, 0x64, 0x72, 0x6f, 0x69, 0x64, 0x48,
+ 0x77, 0x75, 0x69, 0x4d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x52, 0x11, 0x61,
+ 0x6e, 0x64, 0x72, 0x6f, 0x69, 0x64, 0x48, 0x77, 0x75, 0x69, 0x4d, 0x65,
+ 0x74, 0x72, 0x69, 0x63, 0x2a, 0x06, 0x08, 0xc2, 0x03, 0x10, 0xf4, 0x03,
+ 0x2a, 0x06, 0x08, 0xf4, 0x03, 0x10, 0xe9, 0x07, 0x4a, 0x04, 0x08, 0x04,
+ 0x10, 0x05, 0x4a, 0x04, 0x08, 0x0a, 0x10, 0x0b, 0x4a, 0x04, 0x08, 0x0d,
+ 0x10, 0x0e, 0x4a, 0x04, 0x08, 0x0e, 0x10, 0x0f}};
} // namespace perfetto
diff --git a/src/trace_processor/metrics/trace_metadata.sql b/src/trace_processor/metrics/trace_metadata.sql
index 9da756a..c7e68e8 100644
--- a/src/trace_processor/metrics/trace_metadata.sql
+++ b/src/trace_processor/metrics/trace_metadata.sql
@@ -34,5 +34,9 @@
'statsd_triggering_subscription_id', (
SELECT int_value FROM metadata
WHERE name = 'statsd_triggering_subscription_id'
+ ),
+ 'trace_size_bytes', (
+ SELECT int_value FROM metadata
+ WHERE name = 'trace_size_bytes'
)
);
diff --git a/src/trace_processor/process_table.cc b/src/trace_processor/process_table.cc
deleted file mode 100644
index a25c0fa..0000000
--- a/src/trace_processor/process_table.cc
+++ /dev/null
@@ -1,177 +0,0 @@
-/*
- * Copyright (C) 2018 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.
- */
-
-#include "src/trace_processor/process_table.h"
-
-#include "perfetto/base/logging.h"
-#include "src/trace_processor/sqlite/query_constraints.h"
-#include "src/trace_processor/sqlite/sqlite_utils.h"
-
-namespace perfetto {
-namespace trace_processor {
-
-namespace {
-
-using namespace sqlite_utils;
-
-} // namespace
-
-ProcessTable::ProcessTable(sqlite3*, const TraceStorage* storage)
- : storage_(storage) {}
-
-void ProcessTable::RegisterTable(sqlite3* db, const TraceStorage* storage) {
- SqliteTable::Register<ProcessTable>(db, storage, "process");
-}
-
-util::Status ProcessTable::Init(int, const char* const*, Schema* schema) {
- *schema = Schema(
- {
- SqliteTable::Column(Column::kUpid, "upid", SqlValue::Type::kLong),
- SqliteTable::Column(Column::kName, "name", SqlValue::Type::kString),
- SqliteTable::Column(Column::kPid, "pid", SqlValue::Type::kLong),
- SqliteTable::Column(Column::kStartTs, "start_ts",
- SqlValue::Type::kLong),
- SqliteTable::Column(Column::kEndTs, "end_ts", SqlValue::Type::kLong),
- SqliteTable::Column(Column::kParentUpid, "parent_upid",
- SqlValue::Type::kLong),
- SqliteTable::Column(Column::kUid, "uid", SqlValue::Type::kLong),
- },
- {Column::kUpid});
- return util::OkStatus();
-}
-
-std::unique_ptr<SqliteTable::Cursor> ProcessTable::CreateCursor() {
- return std::unique_ptr<SqliteTable::Cursor>(new Cursor(this));
-}
-
-int ProcessTable::BestIndex(const QueryConstraints& qc, BestIndexInfo* info) {
- // If the query has a constraint on the |upid| field, return a reduced cost
- // because we can do that filter efficiently.
- const auto& cs = qc.constraints();
- auto fn = [](const QueryConstraints::Constraint& c) {
- return c.column == Column::kUpid && sqlite_utils::IsOpEq(c.op);
- };
- info->estimated_cost = std::find_if(cs.begin(), cs.end(), fn) != cs.end()
- ? 1
- : static_cast<uint32_t>(storage_->process_count());
- return SQLITE_OK;
-}
-
-ProcessTable::Cursor::Cursor(ProcessTable* table)
- : SqliteTable::Cursor(table), storage_(table->storage_) {}
-
-int ProcessTable::Cursor::Filter(const QueryConstraints& qc,
- sqlite3_value** argv,
- FilterHistory) {
- min_ = 0;
- max_ = static_cast<uint32_t>(storage_->process_count());
- desc_ = false;
-
- for (size_t j = 0; j < qc.constraints().size(); j++) {
- const auto& cs = qc.constraints()[j];
- if (cs.column == Column::kUpid) {
- auto constraint_upid = static_cast<UniquePid>(sqlite3_value_int(argv[j]));
- // Set the range of upids that we are interested in, based on the
- // constraints in the query. Everything between min and max (exclusive)
- // will be returned.
- if (IsOpEq(cs.op)) {
- min_ = constraint_upid;
- max_ = constraint_upid + 1;
- } else if (IsOpGe(cs.op) || IsOpGt(cs.op)) {
- min_ = IsOpGt(cs.op) ? constraint_upid + 1 : constraint_upid;
- } else if (IsOpLe(cs.op) || IsOpLt(cs.op)) {
- max_ = IsOpLt(cs.op) ? constraint_upid : constraint_upid + 1;
- }
- }
- }
-
- for (const auto& ob : qc.order_by()) {
- if (ob.iColumn == Column::kUpid) {
- desc_ = ob.desc;
- }
- }
- index_ = 0;
-
- return SQLITE_OK;
-}
-
-int ProcessTable::Cursor::Column(sqlite3_context* context, int N) {
- uint32_t current = desc_ ? max_ - index_ - 1 : min_ + index_;
- const auto& process = storage_->GetProcess(current);
- switch (N) {
- case Column::kUpid: {
- sqlite3_result_int64(context, current);
- break;
- }
- case Column::kName: {
- const auto& name = storage_->GetString(process.name_id);
- sqlite3_result_text(context, name.c_str(), -1, kSqliteStatic);
- break;
- }
- case Column::kPid: {
- sqlite3_result_int64(context, process.pid);
- break;
- }
- case Column::kStartTs: {
- if (process.start_ns != 0) {
- sqlite3_result_int64(context, process.start_ns);
- } else {
- sqlite3_result_null(context);
- }
- break;
- }
- case Column::kEndTs: {
- if (process.end_ns != 0) {
- sqlite3_result_int64(context, process.end_ns);
- } else {
- sqlite3_result_null(context);
- }
- break;
- }
- case Column::kParentUpid: {
- if (process.parent_upid.has_value()) {
- sqlite3_result_int64(context, process.parent_upid.value());
- } else {
- sqlite3_result_null(context);
- }
- break;
- }
- case Column::kUid: {
- if (process.uid.has_value()) {
- sqlite3_result_int64(context, process.uid.value());
- } else {
- sqlite3_result_null(context);
- }
- break;
- }
- default:
- PERFETTO_FATAL("Unknown column %d", N);
- break;
- }
- return SQLITE_OK;
-}
-
-int ProcessTable::Cursor::Next() {
- ++index_;
- return SQLITE_OK;
-}
-
-int ProcessTable::Cursor::Eof() {
- return index_ >= (max_ - min_);
-}
-
-} // namespace trace_processor
-} // namespace perfetto
diff --git a/src/trace_processor/process_table.h b/src/trace_processor/process_table.h
deleted file mode 100644
index 7e661a6..0000000
--- a/src/trace_processor/process_table.h
+++ /dev/null
@@ -1,77 +0,0 @@
-/*
- * Copyright (C) 2018 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.
- */
-
-#ifndef SRC_TRACE_PROCESSOR_PROCESS_TABLE_H_
-#define SRC_TRACE_PROCESSOR_PROCESS_TABLE_H_
-
-#include <limits>
-#include <memory>
-
-#include "src/trace_processor/sqlite/sqlite_table.h"
-#include "src/trace_processor/trace_storage.h"
-
-namespace perfetto {
-namespace trace_processor {
-
-// The implementation of the SQLite table containing each unique process with
-// their details.
-class ProcessTable : public SqliteTable {
- public:
- enum Column {
- kUpid = 0,
- kName = 1,
- kPid = 2,
- kStartTs = 3,
- kEndTs = 4,
- kParentUpid = 5,
- kUid = 6
- };
- class Cursor : public SqliteTable::Cursor {
- public:
- Cursor(ProcessTable*);
-
- // Implementation of Table::Cursor.
- int Filter(const QueryConstraints&,
- sqlite3_value**,
- FilterHistory) override;
- int Next() override;
- int Eof() override;
- int Column(sqlite3_context*, int N) override;
-
- private:
- const TraceStorage* const storage_;
- UniquePid min_ = 0;
- UniquePid max_ = 0;
- uint32_t index_ = 0;
- bool desc_ = false;
- };
-
- static void RegisterTable(sqlite3* db, const TraceStorage* storage);
-
- ProcessTable(sqlite3*, const TraceStorage*);
-
- // Table implementation.
- util::Status Init(int, const char* const*, SqliteTable::Schema*) override;
- std::unique_ptr<SqliteTable::Cursor> CreateCursor() override;
- int BestIndex(const QueryConstraints&, BestIndexInfo*) override;
-
- private:
- const TraceStorage* const storage_;
-};
-} // namespace trace_processor
-} // namespace perfetto
-
-#endif // SRC_TRACE_PROCESSOR_PROCESS_TABLE_H_
diff --git a/src/trace_processor/process_table_unittest.cc b/src/trace_processor/process_table_unittest.cc
deleted file mode 100644
index 84de696..0000000
--- a/src/trace_processor/process_table_unittest.cc
+++ /dev/null
@@ -1,189 +0,0 @@
-/*
- * Copyright (C) 2018 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.
- */
-
-#include "src/trace_processor/process_table.h"
-#include "src/trace_processor/event_tracker.h"
-#include "src/trace_processor/process_tracker.h"
-#include "src/trace_processor/sqlite/scoped_db.h"
-#include "src/trace_processor/trace_processor_context.h"
-
-#include "test/gtest_and_gmock.h"
-
-namespace perfetto {
-namespace trace_processor {
-namespace {
-
-class ProcessTableUnittest : public ::testing::Test {
- public:
- ProcessTableUnittest() {
- sqlite3* db = nullptr;
- PERFETTO_CHECK(sqlite3_initialize() == SQLITE_OK);
- PERFETTO_CHECK(sqlite3_open(":memory:", &db) == SQLITE_OK);
- db_.reset(db);
-
- context_.storage.reset(new TraceStorage());
- context_.process_tracker.reset(new ProcessTracker(&context_));
-
- ProcessTable::RegisterTable(db_.get(), context_.storage.get());
- }
-
- void PrepareValidStatement(const std::string& sql) {
- int size = static_cast<int>(sql.size());
- sqlite3_stmt* stmt;
- ASSERT_EQ(sqlite3_prepare_v2(*db_, sql.c_str(), size, &stmt, nullptr),
- SQLITE_OK);
- stmt_.reset(stmt);
- }
-
- const char* GetColumnAsText(int colId) {
- return reinterpret_cast<const char*>(sqlite3_column_text(*stmt_, colId));
- }
-
- protected:
- TraceProcessorContext context_;
- ScopedDb db_;
- ScopedStmt stmt_;
-};
-
-TEST_F(ProcessTableUnittest, SelectUpidAndName) {
- static const char kCommProc1[] = "process1";
- static const char kCommProc2[] = "process2";
- context_.process_tracker->SetProcessMetadata(1, base::nullopt, kCommProc1);
- context_.process_tracker->SetProcessMetadata(2, base::nullopt, kCommProc2);
-
- PrepareValidStatement("SELECT upid, name FROM process");
-
- ASSERT_EQ(sqlite3_step(*stmt_), SQLITE_ROW);
- ASSERT_EQ(sqlite3_column_int(*stmt_, 0), 0 /* upid */);
-
- ASSERT_EQ(sqlite3_step(*stmt_), SQLITE_ROW);
- ASSERT_EQ(sqlite3_column_int(*stmt_, 0), 1 /* upid */);
- ASSERT_STREQ(GetColumnAsText(1), kCommProc1);
-
- ASSERT_EQ(sqlite3_step(*stmt_), SQLITE_ROW);
- ASSERT_EQ(sqlite3_column_int(*stmt_, 0), 2 /* upid */);
- ASSERT_STREQ(GetColumnAsText(1), kCommProc2);
-
- ASSERT_EQ(sqlite3_step(*stmt_), SQLITE_DONE);
-}
-
-TEST_F(ProcessTableUnittest, SelectUpidAndNameWithFilter) {
- static const char kCommProc1[] = "process1";
- static const char kCommProc2[] = "process2";
- context_.process_tracker->SetProcessMetadata(1, base::nullopt, kCommProc1);
- context_.process_tracker->SetProcessMetadata(2, base::nullopt, kCommProc2);
-
- PrepareValidStatement("SELECT upid, name FROM process where upid = 2");
-
- ASSERT_EQ(sqlite3_step(*stmt_), SQLITE_ROW);
- ASSERT_EQ(sqlite3_column_int(*stmt_, 0), 2 /* upid */);
- ASSERT_STREQ(GetColumnAsText(1), kCommProc2);
-
- ASSERT_EQ(sqlite3_step(*stmt_), SQLITE_DONE);
-}
-
-TEST_F(ProcessTableUnittest, SelectUpidAndNameWithOrder) {
- static const char kCommProc1[] = "process1";
- static const char kCommProc2[] = "process2";
- context_.process_tracker->SetProcessMetadata(1, base::nullopt, kCommProc1);
- context_.process_tracker->SetProcessMetadata(2, base::nullopt, kCommProc2);
-
- PrepareValidStatement("SELECT upid, name FROM process ORDER BY upid desc");
-
- ASSERT_EQ(sqlite3_step(*stmt_), SQLITE_ROW);
- ASSERT_EQ(sqlite3_column_int(*stmt_, 0), 2 /* upid */);
- ASSERT_STREQ(GetColumnAsText(1), kCommProc2);
-
- ASSERT_EQ(sqlite3_step(*stmt_), SQLITE_ROW);
- ASSERT_EQ(sqlite3_column_int(*stmt_, 0), 1 /* upid */);
- ASSERT_STREQ(GetColumnAsText(1), kCommProc1);
-
- ASSERT_EQ(sqlite3_step(*stmt_), SQLITE_ROW);
- ASSERT_EQ(sqlite3_column_int(*stmt_, 0), 0 /* upid */);
-
- ASSERT_EQ(sqlite3_step(*stmt_), SQLITE_DONE);
-}
-
-TEST_F(ProcessTableUnittest, SelectUpidAndNameFilterGt) {
- static const char kCommProc1[] = "process1";
- static const char kCommProc2[] = "process2";
- context_.process_tracker->SetProcessMetadata(1, base::nullopt, kCommProc1);
- context_.process_tracker->SetProcessMetadata(2, base::nullopt, kCommProc2);
-
- PrepareValidStatement("SELECT upid, name FROM process where upid > 1");
-
- ASSERT_EQ(sqlite3_step(*stmt_), SQLITE_ROW);
- ASSERT_EQ(sqlite3_column_int(*stmt_, 0), 2 /* upid */);
- ASSERT_STREQ(GetColumnAsText(1), kCommProc2);
-
- ASSERT_EQ(sqlite3_step(*stmt_), SQLITE_DONE);
-}
-
-TEST_F(ProcessTableUnittest, SelectUpidAndNameFilterName) {
- static const char kCommProc1[] = "process1";
- static const char kCommProc2[] = "process2";
- context_.process_tracker->SetProcessMetadata(1, base::nullopt, kCommProc1);
- context_.process_tracker->SetProcessMetadata(2, base::nullopt, kCommProc2);
-
- PrepareValidStatement(
- "SELECT upid, name FROM process where name = \"process2\"");
-
- ASSERT_EQ(sqlite3_step(*stmt_), SQLITE_ROW);
- ASSERT_EQ(sqlite3_column_int(*stmt_, 0), 2 /* upid */);
- ASSERT_STREQ(GetColumnAsText(1), kCommProc2);
-
- ASSERT_EQ(sqlite3_step(*stmt_), SQLITE_DONE);
-}
-
-TEST_F(ProcessTableUnittest, SelectUpidAndNameFilterDifferentOr) {
- static const char kCommProc1[] = "process1";
- static const char kCommProc2[] = "process2";
- context_.process_tracker->SetProcessMetadata(1, base::nullopt, kCommProc1);
- context_.process_tracker->SetProcessMetadata(2, base::nullopt, kCommProc2);
-
- PrepareValidStatement(
- "SELECT upid, name FROM process where upid = 2 or name = \"process2\"");
-
- ASSERT_EQ(sqlite3_step(*stmt_), SQLITE_ROW);
- ASSERT_EQ(sqlite3_column_int(*stmt_, 0), 2 /* upid */);
- ASSERT_STREQ(GetColumnAsText(1), kCommProc2);
-
- ASSERT_EQ(sqlite3_step(*stmt_), SQLITE_DONE);
-}
-
-TEST_F(ProcessTableUnittest, SelectUpidAndNameFilterSameOr) {
- static const char kCommProc1[] = "process1";
- static const char kCommProc2[] = "process2";
- context_.process_tracker->SetProcessMetadata(1, base::nullopt, kCommProc1);
- context_.process_tracker->SetProcessMetadata(2, base::nullopt, kCommProc2);
-
- PrepareValidStatement(
- "SELECT upid, name FROM process where upid = 1 or upid = 2");
-
- ASSERT_EQ(sqlite3_step(*stmt_), SQLITE_ROW);
- ASSERT_EQ(sqlite3_column_int(*stmt_, 0), 1 /* upid */);
- ASSERT_STREQ(GetColumnAsText(1), kCommProc1);
-
- ASSERT_EQ(sqlite3_step(*stmt_), SQLITE_ROW);
- ASSERT_EQ(sqlite3_column_int(*stmt_, 0), 2 /* upid */);
- ASSERT_STREQ(GetColumnAsText(1), kCommProc2);
-
- ASSERT_EQ(sqlite3_step(*stmt_), SQLITE_DONE);
-}
-
-} // namespace
-} // namespace trace_processor
-} // namespace perfetto
diff --git a/src/trace_processor/process_tracker.cc b/src/trace_processor/process_tracker.cc
index 5a7ef6b..27668ef 100644
--- a/src/trace_processor/process_tracker.cc
+++ b/src/trace_processor/process_tracker.cc
@@ -33,158 +33,205 @@
ProcessTracker::~ProcessTracker() = default;
-UniqueTid ProcessTracker::StartNewThread(int64_t timestamp,
+UniqueTid ProcessTracker::StartNewThread(base::Optional<int64_t> timestamp,
uint32_t tid,
StringId thread_name_id) {
- UniqueTid new_utid = context_->storage->AddEmptyThread(tid);
- TraceStorage::Thread* thread = context_->storage->GetMutableThread(new_utid);
- thread->name_id = thread_name_id;
- thread->start_ns = timestamp;
+ tables::ThreadTable::Row row;
+ row.tid = tid;
+ row.name = thread_name_id;
+ row.start_ts = timestamp;
+
+ auto* thread_table = context_->storage->mutable_thread_table();
+ UniqueTid new_utid = thread_table->Insert(row).value;
tids_[tid].emplace_back(new_utid);
return new_utid;
}
void ProcessTracker::EndThread(int64_t timestamp, uint32_t tid) {
+ auto* thread_table = context_->storage->mutable_thread_table();
+ auto* process_table = context_->storage->mutable_process_table();
+
UniqueTid utid = GetOrCreateThread(tid);
- TraceStorage::Thread* thread = context_->storage->GetMutableThread(utid);
- thread->end_ns = timestamp;
+ thread_table->mutable_end_ts()->Set(utid, timestamp);
// Remove the thread from the list of threads being tracked as any event after
// this one should be ignored.
auto& vector = tids_[tid];
vector.erase(std::remove(vector.begin(), vector.end(), utid));
- if (thread->upid.has_value()) {
- TraceStorage::Process* process =
- context_->storage->GetMutableProcess(thread->upid.value());
-
+ auto opt_upid = thread_table->upid()[utid];
+ if (opt_upid.has_value()) {
// If the process pid and thread tid are equal, then this is the main thread
// of the process.
- if (process->pid == thread->tid) {
- process->end_ns = timestamp;
+ if (process_table->pid()[*opt_upid] == thread_table->tid()[utid]) {
+ process_table->mutable_end_ts()->Set(*opt_upid, timestamp);
}
}
}
base::Optional<UniqueTid> ProcessTracker::GetThreadOrNull(uint32_t tid) {
- auto vector_it = tids_.find(tid);
- if (vector_it == tids_.end() || vector_it->second.empty()) {
+ auto opt_utid = GetThreadOrNull(tid, base::nullopt);
+ if (!opt_utid)
return base::nullopt;
- }
+
+ auto* threads = context_->storage->mutable_thread_table();
+ UniqueTid utid = *opt_utid;
+
+ // Ensure that the tid matches the tid we were looking for.
+ PERFETTO_DCHECK(threads->tid()[utid] == tid);
// If the thread is being tracked by the process tracker, it should not be
// known to have ended.
- UniqueTid utid = vector_it->second.back();
- PERFETTO_DCHECK(context_->storage->GetMutableThread(utid)->end_ns == 0u);
+ PERFETTO_DCHECK(!threads->end_ts()[utid].has_value());
+
return utid;
}
UniqueTid ProcessTracker::GetOrCreateThread(uint32_t tid) {
auto utid = GetThreadOrNull(tid);
- return utid ? utid.value() : StartNewThread(0, tid, 0);
+ return utid ? *utid : StartNewThread(base::nullopt, tid, kNullStringId);
}
UniqueTid ProcessTracker::UpdateThreadName(uint32_t tid,
StringId thread_name_id) {
+ auto* thread_table = context_->storage->mutable_thread_table();
auto utid = GetOrCreateThread(tid);
- if (!thread_name_id.is_null()) {
- auto* thread = context_->storage->GetMutableThread(utid);
- thread->name_id = thread_name_id;
- }
+ if (!thread_name_id.is_null())
+ thread_table->mutable_name()->Set(utid, thread_name_id);
return utid;
}
void ProcessTracker::SetThreadNameIfUnset(UniqueTid utid,
StringId thread_name_id) {
- auto* thread = context_->storage->GetMutableThread(utid);
- if (thread->name_id == kNullStringId)
- thread->name_id = thread_name_id;
+ auto* thread_table = context_->storage->mutable_thread_table();
+ if (thread_table->name()[utid].is_null())
+ thread_table->mutable_name()->Set(utid, thread_name_id);
+}
+
+bool ProcessTracker::IsThreadAlive(UniqueTid utid) {
+ auto* threads = context_->storage->mutable_thread_table();
+ auto* processes = context_->storage->mutable_process_table();
+
+ // If the thread has an end ts, it's certainly dead.
+ if (threads->end_ts()[utid].has_value())
+ return false;
+
+ // If we don't know the parent process, we have to consider this thread alive.
+ auto opt_current_upid = threads->upid()[utid];
+ if (!opt_current_upid)
+ return true;
+
+ // If the process is already dead, the thread can't be alive.
+ UniquePid current_upid = *opt_current_upid;
+ if (processes->end_ts()[current_upid].has_value())
+ return false;
+
+ // If the process has been replaced in |pids_|, this thread is dead.
+ uint32_t current_pid = processes->pid()[current_upid];
+ auto pid_it = pids_.find(current_pid);
+ if (pid_it != pids_.end() && pid_it->second != current_upid)
+ return false;
+
+ return true;
+}
+
+base::Optional<UniqueTid> ProcessTracker::GetThreadOrNull(
+ uint32_t tid,
+ base::Optional<uint32_t> pid) {
+ auto* threads = context_->storage->mutable_thread_table();
+ auto* processes = context_->storage->mutable_process_table();
+
+ auto vector_it = tids_.find(tid);
+ if (vector_it == tids_.end())
+ return base::nullopt;
+
+ // Iterate backwards through the threads so ones later in the trace are more
+ // likely to be picked.
+ const auto& vector = vector_it->second;
+ for (auto it = vector.rbegin(); it != vector.rend(); it++) {
+ UniqueTid current_utid = *it;
+
+ // If we finished this thread, we should have removed it from the vector
+ // entirely.
+ PERFETTO_DCHECK(!threads->end_ts()[current_utid].has_value());
+
+ // If the thread is dead, ignore it.
+ if (!IsThreadAlive(current_utid))
+ continue;
+
+ // If we don't know the parent process, we have to choose this thread.
+ auto opt_current_upid = threads->upid()[current_utid];
+ if (!opt_current_upid)
+ return current_utid;
+
+ // We found a thread that matches both the tid and its parent pid.
+ uint32_t current_pid = processes->pid()[*opt_current_upid];
+ if (!pid || current_pid == *pid)
+ return current_utid;
+ }
+ return base::nullopt;
}
UniqueTid ProcessTracker::UpdateThread(uint32_t tid, uint32_t pid) {
- auto vector_it = tids_.find(tid);
+ auto* thread_table = context_->storage->mutable_thread_table();
// Try looking for a thread that matches both tid and thread group id (pid).
- TraceStorage::Thread* thread = nullptr;
- UniqueTid utid = 0;
- if (vector_it != tids_.end()) {
- const auto& vector = vector_it->second;
-
- // Iterate backwards through the threads so ones later in the trace are more
- // likely to be picked.
- for (auto it = vector.rbegin(); it != vector.rend(); it++) {
- auto* iter_thread = context_->storage->GetMutableThread(*it);
-
- // If we finished this thread, we should have removed it from the vector
- // entirely.
- PERFETTO_DCHECK(iter_thread->end_ns == 0);
-
- if (!iter_thread->upid.has_value()) {
- // We haven't discovered the parent process for the thread. Assign it
- // now and use this thread.
- thread = iter_thread;
- utid = *it;
- break;
- }
-
- const auto& iter_process =
- context_->storage->GetProcess(iter_thread->upid.value());
- if (iter_process.end_ns != 0) {
- // If the process is already dead, don't bother choosing the associated
- // thread.
- continue;
- }
- if (iter_process.pid == pid) {
- // We found a thread that matches both the tid and its parent pid.
- thread = iter_thread;
- utid = *it;
- break;
- }
- } // for(tids).
- }
+ base::Optional<UniqueTid> opt_utid = GetThreadOrNull(tid, pid);
// If no matching thread was found, create a new one.
- if (thread == nullptr) {
- utid = StartNewThread(0, tid, 0);
- thread = context_->storage->GetMutableThread(utid);
- }
+ UniqueTid utid =
+ opt_utid ? *opt_utid : StartNewThread(base::nullopt, tid, kNullStringId);
+ PERFETTO_DCHECK(thread_table->tid()[utid] == tid);
// Find matching process or create new one.
- if (!thread->upid.has_value()) {
- thread->upid = GetOrCreateProcess(pid);
+ if (!thread_table->upid()[utid].has_value()) {
+ thread_table->mutable_upid()->Set(utid, GetOrCreateProcess(pid));
}
- ResolvePendingAssociations(utid, *thread->upid);
+ ResolvePendingAssociations(utid, *thread_table->upid()[utid]);
return utid;
}
-UniquePid ProcessTracker::StartNewProcess(int64_t timestamp,
- uint32_t parent_tid,
+UniquePid ProcessTracker::StartNewProcess(base::Optional<int64_t> timestamp,
+ base::Optional<uint32_t> parent_tid,
uint32_t pid,
StringId main_thread_name) {
pids_.erase(pid);
+ // TODO(eseckler): Consider erasing all old entries in |tids_| that match the
+ // |pid| (those would be for an older process with the same pid). Right now,
+ // we keep them in |tids_| (if they weren't erased by EndThread()), but ignore
+ // them in GetThreadOrNull().
// Create a new UTID for the main thread, so we don't end up reusing an old
// entry in case of TID recycling.
- StartNewThread(timestamp, /*tid=*/pid, 0);
+ StartNewThread(timestamp, /*tid=*/pid, kNullStringId);
// Note that we erased the pid above so this should always return a new
// process.
- std::pair<UniquePid, TraceStorage::Process*> process =
- GetOrCreateProcessPtr(pid);
- PERFETTO_DCHECK(process.second->name_id == 0);
- process.second->start_ns = timestamp;
- process.second->name_id = main_thread_name;
+ UniquePid upid = GetOrCreateProcess(pid);
- UniqueTid parent_utid = GetOrCreateThread(parent_tid);
- auto* parent_thread = context_->storage->GetMutableThread(parent_utid);
- if (parent_thread->upid.has_value()) {
- process.second->parent_upid = parent_thread->upid.value();
- } else {
- pending_parent_assocs_.emplace_back(parent_utid, process.first);
+ auto* process_table = context_->storage->mutable_process_table();
+ auto* thread_table = context_->storage->mutable_thread_table();
+
+ PERFETTO_DCHECK(process_table->name()[upid].is_null());
+ PERFETTO_DCHECK(!process_table->start_ts()[upid].has_value());
+
+ if (timestamp) {
+ process_table->mutable_start_ts()->Set(upid, *timestamp);
}
- return process.first;
+ process_table->mutable_name()->Set(upid, main_thread_name);
+
+ if (parent_tid) {
+ UniqueTid parent_utid = GetOrCreateThread(*parent_tid);
+ auto opt_parent_upid = thread_table->upid()[parent_utid];
+ if (opt_parent_upid.has_value()) {
+ process_table->mutable_parent_upid()->Set(upid, *opt_parent_upid);
+ } else {
+ pending_parent_assocs_.emplace_back(parent_utid, upid);
+ }
+ }
+ return upid;
}
UniquePid ProcessTracker::SetProcessMetadata(uint32_t pid,
@@ -196,49 +243,54 @@
if (ppid.has_value()) {
pupid = GetOrCreateProcess(ppid.value());
}
- UniquePid upid;
- TraceStorage::Process* process;
- std::tie(upid, process) = GetOrCreateProcessPtr(pid);
- process->name_id = proc_name_id;
- process->parent_upid = pupid;
+
+ UniquePid upid = GetOrCreateProcess(pid);
+
+ auto* process_table = context_->storage->mutable_process_table();
+ process_table->mutable_name()->Set(upid, proc_name_id);
+
+ if (pupid)
+ process_table->mutable_parent_upid()->Set(upid, *pupid);
+
return upid;
}
void ProcessTracker::SetProcessUid(UniquePid upid, uint32_t uid) {
- context_->storage->GetMutableProcess(upid)->uid = uid;
+ auto* process_table = context_->storage->mutable_process_table();
+ process_table->mutable_uid()->Set(upid, uid);
}
void ProcessTracker::SetProcessNameIfUnset(UniquePid upid,
StringId process_name_id) {
- TraceStorage::Process* process = context_->storage->GetMutableProcess(upid);
- if (process->name_id == kNullStringId)
- process->name_id = process_name_id;
+ auto* process_table = context_->storage->mutable_process_table();
+ if (process_table->name()[upid].is_null())
+ process_table->mutable_name()->Set(upid, process_name_id);
}
void ProcessTracker::UpdateProcessNameFromThreadName(uint32_t tid,
StringId thread_name) {
+ auto* thread_table = context_->storage->mutable_thread_table();
+ auto* process_table = context_->storage->mutable_process_table();
+
auto utid = GetOrCreateThread(tid);
- TraceStorage::Thread* thread = context_->storage->GetMutableThread(utid);
- if (thread->upid.has_value()) {
- auto* process = context_->storage->GetMutableProcess(thread->upid.value());
- if (process->pid == tid) {
- process->name_id = thread_name;
+ auto opt_upid = thread_table->upid()[utid];
+ if (opt_upid.has_value()) {
+ if (process_table->pid()[*opt_upid] == tid) {
+ process_table->mutable_name()->Set(*opt_upid, thread_name);
}
}
}
UniquePid ProcessTracker::GetOrCreateProcess(uint32_t pid) {
- return GetOrCreateProcessPtr(pid).first;
-}
-
-std::pair<UniquePid, TraceStorage::Process*>
-ProcessTracker::GetOrCreateProcessPtr(uint32_t pid) {
UniquePid upid;
auto it = pids_.find(pid);
if (it != pids_.end()) {
upid = it->second;
} else {
- upid = context_->storage->AddEmptyProcess(pid);
+ tables::ProcessTable::Row row;
+ row.pid = pid;
+ upid = context_->storage->mutable_process_table()->Insert(row).value;
+
pids_.emplace(pid, upid);
// Create an entry for the main thread.
@@ -247,33 +299,35 @@
// call. This call usually comes from the ProcessTree dump which is delayed.
UpdateThread(/*tid=*/pid, pid);
}
- return std::make_pair(upid, context_->storage->GetMutableProcess(upid));
+ return upid;
}
void ProcessTracker::AssociateThreads(UniqueTid utid1, UniqueTid utid2) {
- TraceStorage::Thread* thd1 = context_->storage->GetMutableThread(utid1);
- TraceStorage::Thread* thd2 = context_->storage->GetMutableThread(utid2);
+ auto* tt = context_->storage->mutable_thread_table();
// First of all check if one of the two threads is already bound to a process.
// If that is the case, map the other thread to the same process and resolve
// recursively any associations pending on the other thread.
- if (thd1->upid.has_value() && !thd2->upid.has_value()) {
- thd2->upid = *thd1->upid;
- ResolvePendingAssociations(utid2, *thd1->upid);
+ auto opt_upid1 = tt->upid()[utid1];
+ auto opt_upid2 = tt->upid()[utid2];
+
+ if (opt_upid1.has_value() && !opt_upid2.has_value()) {
+ tt->mutable_upid()->Set(utid2, *opt_upid1);
+ ResolvePendingAssociations(utid2, *opt_upid1);
return;
}
- if (thd2->upid.has_value() && !thd1->upid.has_value()) {
- thd1->upid = *thd2->upid;
- ResolvePendingAssociations(utid1, *thd2->upid);
+ if (opt_upid2.has_value() && !opt_upid1.has_value()) {
+ tt->mutable_upid()->Set(utid1, *opt_upid2);
+ ResolvePendingAssociations(utid1, *opt_upid2);
return;
}
- if (thd1->upid.has_value() && thd1->upid != thd2->upid) {
+ if (opt_upid1.has_value() && opt_upid1 != opt_upid2) {
// Cannot associate two threads that belong to two different processes.
PERFETTO_ELOG("Process tracker failure. Cannot associate threads %u, %u",
- thd1->tid, thd2->tid);
+ tt->tid()[utid1], tt->tid()[utid2]);
context_->storage->IncrementStats(stats::process_tracker_errors);
return;
}
@@ -283,7 +337,10 @@
void ProcessTracker::ResolvePendingAssociations(UniqueTid utid_arg,
UniquePid upid) {
- PERFETTO_DCHECK(context_->storage->GetMutableThread(utid_arg)->upid == upid);
+ auto* tt = context_->storage->mutable_thread_table();
+ auto* pt = context_->storage->mutable_process_table();
+ PERFETTO_DCHECK(tt->upid()[utid_arg] == upid);
+
std::vector<UniqueTid> resolved_utids;
resolved_utids.emplace_back(utid_arg);
@@ -302,10 +359,9 @@
PERFETTO_DCHECK(child_upid != upid);
// Set the parent pid of the other process
- auto* child_proc = context_->storage->GetMutableProcess(child_upid);
- PERFETTO_DCHECK(!child_proc->parent_upid ||
- child_proc->parent_upid == upid);
- child_proc->parent_upid = upid;
+ PERFETTO_DCHECK(!pt->parent_upid()[child_upid] ||
+ pt->parent_upid()[child_upid] == upid);
+ pt->mutable_parent_upid()->Set(child_upid, upid);
// Erase the pair. The |pending_parent_assocs_| vector is not sorted and
// swapping a std::pair<uint32_t, uint32_t> is cheap.
@@ -327,9 +383,9 @@
PERFETTO_DCHECK(other_utid != utid);
// Update the other thread and associated it to the same process.
- auto* other_thd = context_->storage->GetMutableThread(other_utid);
- PERFETTO_DCHECK(!other_thd->upid || other_thd->upid == upid);
- other_thd->upid = upid;
+ PERFETTO_DCHECK(!tt->upid()[other_utid] ||
+ tt->upid()[other_utid] == upid);
+ tt->mutable_upid()->Set(other_utid, upid);
// Erase the pair. The |pending_assocs_| vector is not sorted and swapping
// a std::pair<uint32_t, uint32_t> is cheap.
diff --git a/src/trace_processor/process_tracker.h b/src/trace_processor/process_tracker.h
index 19be682..d9141c4 100644
--- a/src/trace_processor/process_tracker.h
+++ b/src/trace_processor/process_tracker.h
@@ -48,7 +48,7 @@
// Called when a task_newtask is observed. This force the tracker to start
// a new UTID for the thread, which is needed for TID-recycling resolution.
- UniqueTid StartNewThread(int64_t timestamp,
+ UniqueTid StartNewThread(base::Optional<int64_t> timestamp,
uint32_t tid,
StringId thread_name_id);
@@ -67,8 +67,8 @@
// the thread_name_id.
virtual UniqueTid UpdateThreadName(uint32_t tid, StringId thread_name_id);
- // Assigns the given name to the thread identified |utid| if it does not have
- // a name yet.
+ // Assigns the given name to the thread identified |utid| if it does not
+ // have a name yet.
virtual void SetThreadNameIfUnset(UniqueTid utid, StringId thread_name_id);
// Called when a thread is seen the process tree. Retrieves the matching utid
@@ -78,8 +78,8 @@
// Called when a task_newtask without the CLONE_THREAD flag is observed.
// This force the tracker to start both a new UTID and a new UPID.
- UniquePid StartNewProcess(int64_t timestamp,
- uint32_t parent_tid,
+ UniquePid StartNewProcess(base::Optional<int64_t> timestamp,
+ base::Optional<uint32_t> parent_tid,
uint32_t pid,
StringId main_thread_name);
@@ -95,7 +95,7 @@
// Assigns the given name to the process identified by |upid| if it does not
// have a name yet.
- void SetProcessNameIfUnset(UniquePid upid, StringId process_name_id);
+ virtual void SetProcessNameIfUnset(UniquePid upid, StringId process_name_id);
// Called on a task rename event to set the process name if the tid provided
// is the main thread of the process.
@@ -126,14 +126,20 @@
void AssociateThreads(UniqueTid, UniqueTid);
private:
+ // Returns the utid of a thread having |tid| and |pid| as the parent process.
+ // pid == base::nullopt matches all processes.
+ // Returns base::nullopt if such a thread doesn't exist.
+ base::Optional<uint32_t> GetThreadOrNull(uint32_t tid,
+ base::Optional<uint32_t> pid);
+
+ // Returns whether a thread is considered alive by the process tracker.
+ bool IsThreadAlive(UniqueTid utid);
+
// Called whenever we discover that the passed thread belongs to the passed
// process. The |pending_assocs_| vector is scanned to see if there are any
// other threads associated to the passed thread.
void ResolvePendingAssociations(UniqueTid, UniquePid);
- std::pair<UniquePid, TraceStorage::Process*> GetOrCreateProcessPtr(
- uint32_t pid);
-
TraceProcessorContext* const context_;
// Each tid can have multiple UniqueTid entries, a new UniqueTid is assigned
diff --git a/src/trace_processor/process_tracker_unittest.cc b/src/trace_processor/process_tracker_unittest.cc
index 802ba42..e626681 100644
--- a/src/trace_processor/process_tracker_unittest.cc
+++ b/src/trace_processor/process_tracker_unittest.cc
@@ -34,6 +34,7 @@
public:
ProcessTrackerTest() {
context.storage.reset(new TraceStorage());
+ context.global_args_tracker.reset(new GlobalArgsTracker(&context));
context.args_tracker.reset(new ArgsTracker(&context));
context.process_tracker.reset(new ProcessTracker(&context));
context.event_tracker.reset(new EventTracker(&context));
@@ -58,9 +59,10 @@
TEST_F(ProcessTrackerTest, StartNewProcess) {
TraceStorage storage;
- auto upid = context.process_tracker->StartNewProcess(1000, 0, 123, 0);
+ auto upid =
+ context.process_tracker->StartNewProcess(1000, 0u, 123, kNullStringId);
ASSERT_EQ(context.process_tracker->GetOrCreateProcess(123), upid);
- ASSERT_EQ(context.storage->GetProcess(upid).start_ns, 1000);
+ ASSERT_EQ(context.storage->process_table().start_ts()[upid], 1000);
}
TEST_F(ProcessTrackerTest, PushTwoProcessEntries_SamePidAndName) {
@@ -82,8 +84,9 @@
TEST_F(ProcessTrackerTest, AddProcessEntry_CorrectName) {
context.process_tracker->SetProcessMetadata(1, base::nullopt, "test");
- ASSERT_EQ(context.storage->GetString(context.storage->GetProcess(1).name_id),
- "test");
+ auto name =
+ context.storage->GetString(context.storage->process_table().name()[1]);
+ ASSERT_EQ(name, "test");
}
TEST_F(ProcessTrackerTest, UpdateThreadMatch) {
@@ -105,29 +108,42 @@
context.process_tracker->SetProcessMetadata(2, base::nullopt, "test");
context.process_tracker->UpdateThread(4, 2);
- TraceStorage::Thread thread = context.storage->GetThread(/*utid=*/1);
- TraceStorage::Process process = context.storage->GetProcess(/*utid=*/1);
-
- ASSERT_EQ(thread.tid, 4u);
- ASSERT_EQ(thread.upid.value(), 1u);
- ASSERT_EQ(process.pid, 2u);
- ASSERT_EQ(process.start_ns, 0);
+ ASSERT_EQ(context.storage->thread_table().tid()[1], 4u);
+ ASSERT_EQ(context.storage->thread_table().upid()[1].value(), 1u);
+ ASSERT_EQ(context.storage->process_table().pid()[1], 2u);
+ ASSERT_EQ(context.storage->process_table().start_ts()[1], base::nullopt);
}
TEST_F(ProcessTrackerTest, UpdateThreadCreate) {
context.process_tracker->UpdateThread(12, 2);
- TraceStorage::Thread thread = context.storage->GetThread(1);
-
// We expect 3 threads: Invalid thread, main thread for pid, tid 12.
- ASSERT_EQ(context.storage->thread_count(), 3u);
+ ASSERT_EQ(context.storage->thread_table().row_count(), 3u);
auto tid_it = context.process_tracker->UtidsForTidForTesting(12);
ASSERT_NE(tid_it.first, tid_it.second);
- ASSERT_EQ(thread.upid.value(), 1u);
+ ASSERT_EQ(context.storage->thread_table().upid()[1].value(), 1u);
auto pid_it = context.process_tracker->UpidsForPidForTesting(2);
ASSERT_NE(pid_it.first, pid_it.second);
- ASSERT_EQ(context.storage->process_count(), 2u);
+ ASSERT_EQ(context.storage->process_table().row_count(), 2u);
+}
+
+TEST_F(ProcessTrackerTest, PidReuseWithoutStartAndEndThread) {
+ UniquePid p1 = context.process_tracker->StartNewProcess(
+ base::nullopt, base::nullopt, /*pid=*/1, kNullStringId);
+ UniqueTid t1 = context.process_tracker->UpdateThread(/*tid=*/2, /*pid=*/1);
+
+ UniquePid p2 = context.process_tracker->StartNewProcess(
+ base::nullopt, base::nullopt, /*pid=*/1, kNullStringId);
+ UniqueTid t2 = context.process_tracker->UpdateThread(/*tid=*/2, /*pid=*/1);
+
+ ASSERT_NE(p1, p2);
+ ASSERT_NE(t1, t2);
+
+ // We expect 3 processes: idle process, 2x pid 1.
+ ASSERT_EQ(context.storage->process_table().row_count(), 3u);
+ // We expect 5 threads: Invalid thread, 2x (main thread + sub thread).
+ ASSERT_EQ(context.storage->thread_table().row_count(), 5u);
}
} // namespace
diff --git a/src/trace_processor/proto_to_json.cc b/src/trace_processor/proto_to_json.cc
index 5b07889..e6f22e9 100644
--- a/src/trace_processor/proto_to_json.cc
+++ b/src/trace_processor/proto_to_json.cc
@@ -14,9 +14,14 @@
* limitations under the License.
*/
+#include <vector>
+
+#include <google/protobuf/descriptor.h>
+#include <google/protobuf/descriptor.pb.h>
#include <google/protobuf/message.h>
#include "perfetto/base/logging.h"
+#include "perfetto/ext/base/string_utils.h"
#include "src/trace_processor/proto_to_json.h"
namespace perfetto {
@@ -160,14 +165,162 @@
return ret;
}
+// This is a class helps avoid the situation where every function has to take
+// field_options_prototype as an argument, which becomes distracting.
+class OptionsConverter {
+ public:
+ explicit OptionsConverter(
+ const google::protobuf::Message* field_options_prototype)
+ : field_options_prototype_(field_options_prototype) {}
+
+ // Prints all field options for non-empty fields of a message. Example:
+ // --- Message definitions ---
+ // FooMessage {
+ // repeated int64 foo = 1 [op1 = val1, op2 = val2];
+ // optional BarMessage bar = 2 [op3 = val3];
+ // }
+ //
+ // BarMessage {
+ // optional int64 baz = 1 [op4 = val4];
+ // }
+ // --- MessageInstance ---
+ // foo_msg = { // (As JSON)
+ // foo: [23, 24, 25],
+ // bar: {
+ // baz: 42
+ // }
+ // }
+ // --- Output of MessageFieldOptionsToJson(foo_msg) ---
+ // foo: {
+ // __field_options: {
+ // op1: val1,
+ // op2: val2,
+ // },
+ // __repeated: true
+ // }
+ // bar: {
+ // __field_options: {
+ // op3 = val3,
+ // },
+ // baz: {
+ // __field_options: {
+ // op4 = val4
+ // },
+ // }
+ // }
+ // --- Notes ---
+ // This function does not produce the surrounding braces for easier use in
+ // recursive use cases. The caller needs to surround the output with braces.
+ std::string MessageFieldOptionsToJson(
+ const google::protobuf::Message& message,
+ uint32_t indent) {
+ using google::protobuf::FieldDescriptor;
+ std::vector<const FieldDescriptor*> field_descs;
+ message.GetReflection()->ListFields(message, &field_descs);
+ std::vector<std::string> field_outputs;
+ for (auto* field_desc : field_descs) {
+ std::vector<std::string> field_entries;
+ if (HasFieldOptions(field_desc)) {
+ std::string options_entry;
+ options_entry +=
+ std::string(indent + 2, ' ') + R"("__field_options": )";
+ options_entry += FieldOptionsToJson(field_desc, indent + 4);
+ field_entries.push_back(std::move(options_entry));
+ }
+ std::string nested_fields =
+ NestedMessageFieldOptionsToJson(message, field_desc, indent + 2);
+ if (nested_fields != "") {
+ field_entries.push_back(std::move(nested_fields));
+ }
+ // We don't output annotations for a field if that field and all its
+ // descendants have no field options.
+ if (field_entries.size() > 0) {
+ if (field_desc->is_repeated()) {
+ field_entries.push_back(std::string(indent, ' ') +
+ R"("__repeated": true)");
+ }
+ std::string field_output;
+ const std::string& name = field_desc->is_extension()
+ ? field_desc->full_name()
+ : field_desc->name();
+ field_output += std::string(indent, ' ') + "\"" + name + "\": {\n";
+ field_output += base::Join(field_entries, ",\n") + "\n";
+ field_output += std::string(indent, ' ') + "}";
+ field_outputs.push_back(std::move(field_output));
+ }
+ }
+ return base::Join(field_outputs, ",\n");
+ }
+
+ private:
+ static bool HasFieldOptions(
+ const google::protobuf::FieldDescriptor* field_desc) {
+ return field_desc->options().ByteSizeLong() > 0;
+ }
+
+ std::string NestedMessageFieldOptionsToJson(
+ const google::protobuf::Message& message,
+ const google::protobuf::FieldDescriptor* field_desc,
+ uint32_t indent) {
+ using google::protobuf::FieldDescriptor;
+ if (field_desc->cpp_type() != FieldDescriptor::CppType::CPPTYPE_MESSAGE)
+ return "";
+ const auto* reflection = message.GetReflection();
+ const google::protobuf::Message& nested_message =
+ field_desc->is_repeated()
+ ? reflection->GetRepeatedMessage(message, field_desc, 0)
+ : reflection->GetMessage(message, field_desc);
+ return MessageFieldOptionsToJson(nested_message, indent);
+ }
+
+ std::string FieldOptionsToJson(
+ const google::protobuf::FieldDescriptor* field_desc,
+ uint32_t indent) {
+ PERFETTO_DCHECK(HasFieldOptions(field_desc));
+ std::unique_ptr<google::protobuf::Message> options(
+ field_options_prototype_->New());
+ // Field option extensions are compiled at runtime as opposed to being
+ // compiled in and being part of the generated pool, so the field option
+ // must be re-parsed as a dynamic message for the extensions to show up. If
+ // we do not do this, the extension fields remain "unknown fields" to the
+ // reflection API.
+ options->ParseFromString(field_desc->options().SerializeAsString());
+ return MessageToJson(*options, indent);
+ }
+
+ const google::protobuf::Message* field_options_prototype_;
+};
+
} // namespace
std::string MessageToJson(const google::protobuf::Message& message,
uint32_t indent) {
- return "{" + MessageFieldsToJson(message, indent + 2) + "\n" +
+ return "{" + MessageFieldsToJson(message, indent + 2) + '\n' +
std::string(indent, ' ') + "}";
}
+std::string MessageToJsonWithAnnotations(
+ const google::protobuf::Message& message,
+ const google::protobuf::Message* field_options_prototype,
+ uint32_t indent) {
+ std::string ret;
+ OptionsConverter options_converter(field_options_prototype);
+
+ ret = "{" + MessageFieldsToJson(message, indent + 2);
+ std::string annotation_fields =
+ options_converter.MessageFieldOptionsToJson(message, indent + 4);
+ if (annotation_fields != "") {
+ ret += ",\n";
+ ret += std::string(indent + 2, ' ') + "\"__annotations\": {\n";
+ ret += annotation_fields + "\n";
+ ret += std::string(indent + 2, ' ') + "}\n";
+ } else {
+ ret += "\n";
+ }
+ ret += std::string(indent, ' ') + "}\n";
+ return ret;
+}
+
} // namespace proto_to_json
} // namespace trace_processor
} // namespace perfetto
diff --git a/src/trace_processor/proto_to_json.h b/src/trace_processor/proto_to_json.h
index f46f4c1..90cae5c 100644
--- a/src/trace_processor/proto_to_json.h
+++ b/src/trace_processor/proto_to_json.h
@@ -26,6 +26,11 @@
std::string MessageToJson(const google::protobuf::Message& message,
uint32_t indent = 0);
+std::string MessageToJsonWithAnnotations(
+ const google::protobuf::Message& message,
+ const google::protobuf::Message* field_options_prototype,
+ uint32_t indent = 0);
+
} // namespace proto_to_json
} // namespace trace_processor
} // namespace perfetto
diff --git a/src/trace_processor/rpc/BUILD.gn b/src/trace_processor/rpc/BUILD.gn
index 02ef12f..8ca56b1 100644
--- a/src/trace_processor/rpc/BUILD.gn
+++ b/src/trace_processor/rpc/BUILD.gn
@@ -54,9 +54,7 @@
if (enable_perfetto_ui && is_wasm) {
source_set("wasm_bridge") {
- sources = [
- "wasm_bridge.cc",
- ]
+ sources = [ "wasm_bridge.cc" ]
deps = [
":rpc",
"../../../gn:default_deps",
diff --git a/src/trace_processor/sched_slice_table.cc b/src/trace_processor/sched_slice_table.cc
index 67694d9..49d4a0a 100644
--- a/src/trace_processor/sched_slice_table.cc
+++ b/src/trace_processor/sched_slice_table.cc
@@ -83,7 +83,7 @@
// it's actually better to do subqueries on this table. Estimate the cost
// of filtering on utid equality constraint by dividing the number of slices
// by the number of threads.
- return RowCount() / storage_->thread_count();
+ return RowCount() / storage_->thread_table().row_count();
}
// If we get to this point, we do not have any special filter logic so
diff --git a/src/trace_processor/sched_slice_table_unittest.cc b/src/trace_processor/sched_slice_table_unittest.cc
index f9131ae..7e624d0 100644
--- a/src/trace_processor/sched_slice_table_unittest.cc
+++ b/src/trace_processor/sched_slice_table_unittest.cc
@@ -41,6 +41,7 @@
db_.reset(db);
context_.storage.reset(new TraceStorage());
+ context_.global_args_tracker.reset(new GlobalArgsTracker(&context_));
context_.args_tracker.reset(new ArgsTracker(&context_));
context_.process_tracker.reset(new ProcessTracker(&context_));
context_.event_tracker.reset(new EventTracker(&context_));
diff --git a/src/trace_processor/slice_tracker.cc b/src/trace_processor/slice_tracker.cc
index 290c8d5..39f7d96 100644
--- a/src/trace_processor/slice_tracker.cc
+++ b/src/trace_processor/slice_tracker.cc
@@ -42,16 +42,22 @@
StringId category,
StringId name,
SetArgsCallback args_callback) {
- // At this stage all events should be globally timestamp ordered.
- if (timestamp < prev_timestamp_) {
- context_->storage->IncrementStats(stats::slice_out_of_order);
- return base::nullopt;
- }
- prev_timestamp_ = timestamp;
+ tables::SliceTable::Row row(timestamp, kPendingDuration, track_id.value,
+ category, name);
+ return StartSlice(timestamp, track_id, args_callback, [this, &row]() {
+ return context_->storage->mutable_slice_table()->Insert(row);
+ });
+}
- MaybeCloseStack(timestamp, &stacks_[track_id]);
- return StartSlice(timestamp, kPendingDuration, track_id, category, name,
- args_callback);
+void SliceTracker::BeginGpu(tables::GpuSliceTable::Row row,
+ SetArgsCallback args_callback) {
+ // Ensure that the duration is pending for this row.
+ // TODO(lalitm): change this to eventually use null instead of -1.
+ row.dur = kPendingDuration;
+
+ StartSlice(row.ts, TrackId(row.track_id), args_callback, [this, &row]() {
+ return context_->storage->mutable_gpu_slice_table()->Insert(row);
+ });
}
base::Optional<uint32_t> SliceTracker::Scoped(int64_t timestamp,
@@ -60,6 +66,51 @@
StringId name,
int64_t duration,
SetArgsCallback args_callback) {
+ PERFETTO_DCHECK(duration >= 0);
+
+ tables::SliceTable::Row row(timestamp, duration, track_id.value, category,
+ name);
+ return StartSlice(timestamp, track_id, args_callback, [this, &row]() {
+ return context_->storage->mutable_slice_table()->Insert(row);
+ });
+}
+
+void SliceTracker::ScopedGpu(const tables::GpuSliceTable::Row& row,
+ SetArgsCallback args_callback) {
+ PERFETTO_DCHECK(row.dur >= 0);
+
+ StartSlice(row.ts, TrackId(row.track_id), args_callback, [this, &row]() {
+ return context_->storage->mutable_gpu_slice_table()->Insert(row);
+ });
+}
+
+base::Optional<uint32_t> SliceTracker::End(int64_t timestamp,
+ TrackId track_id,
+ StringId category,
+ StringId name,
+ SetArgsCallback args_callback) {
+ auto finder = [this, category, name](const SlicesStack& stack) {
+ return MatchingIncompleteSliceIndex(stack, name, category);
+ };
+ auto slice_id = CompleteSlice(timestamp, track_id, args_callback, finder);
+ if (!slice_id)
+ return base::nullopt;
+ return context_->storage->slice_table().id().IndexOf(*slice_id);
+}
+
+base::Optional<SliceId> SliceTracker::EndGpu(int64_t ts,
+ TrackId t_id,
+ SetArgsCallback args_callback) {
+ return CompleteSlice(ts, t_id, args_callback, [](const SlicesStack& stack) {
+ return static_cast<uint32_t>(stack.size() - 1);
+ });
+}
+
+base::Optional<uint32_t> SliceTracker::StartSlice(
+ int64_t timestamp,
+ TrackId track_id,
+ SetArgsCallback args_callback,
+ std::function<SliceId()> inserter) {
// At this stage all events should be globally timestamp ordered.
if (timestamp < prev_timestamp_) {
context_->storage->IncrementStats(stats::slice_out_of_order);
@@ -67,21 +118,9 @@
}
prev_timestamp_ = timestamp;
- PERFETTO_DCHECK(duration >= 0);
- MaybeCloseStack(timestamp, &stacks_[track_id]);
- return StartSlice(timestamp, duration, track_id, category, name,
- args_callback);
-}
-
-base::Optional<uint32_t> SliceTracker::StartSlice(
- int64_t timestamp,
- int64_t duration,
- TrackId track_id,
- StringId category,
- StringId name,
- SetArgsCallback args_callback) {
auto* stack = &stacks_[track_id];
auto* slices = context_->storage->mutable_slice_table();
+ MaybeCloseStack(timestamp, stack);
const uint8_t depth = static_cast<uint8_t>(stack->size());
if (depth >= std::numeric_limits<uint8_t>::max()) {
@@ -91,27 +130,70 @@
int64_t parent_stack_id =
depth == 0 ? 0 : slices->stack_id()[stack->back().first];
- tables::SliceTable::Row row(timestamp, duration, track_id.value, category,
- name, depth, 0, parent_stack_id);
- auto id = slices->Insert(row);
+ SliceId id = inserter();
uint32_t slice_idx = *slices->id().IndexOf(id);
stack->emplace_back(std::make_pair(slice_idx, ArgsTracker(context_)));
+ // Post fill all the relevant columns. All the other columns should have
+ // been filled by the inserter.
+ slices->mutable_depth()->Set(slice_idx, depth);
+ slices->mutable_parent_stack_id()->Set(slice_idx, parent_stack_id);
+ slices->mutable_stack_id()->Set(slice_idx, GetStackHash(*stack));
+
if (args_callback) {
ArgsTracker* tracker = &stack->back().second;
- ArgsTracker::BoundInserter inserter(tracker, TableId::kNestableSlices,
- slice_idx);
- args_callback(&inserter);
+ auto bound_inserter = tracker->AddArgsTo(id);
+ args_callback(&bound_inserter);
}
- slices->mutable_stack_id()->Set(slice_idx, GetStackHash(*stack));
return slice_idx;
}
+base::Optional<SliceId> SliceTracker::CompleteSlice(
+ int64_t timestamp,
+ TrackId track_id,
+ SetArgsCallback args_callback,
+ std::function<base::Optional<uint32_t>(const SlicesStack&)> finder) {
+ // At this stage all events should be globally timestamp ordered.
+ if (timestamp < prev_timestamp_) {
+ context_->storage->IncrementStats(stats::slice_out_of_order);
+ return base::nullopt;
+ }
+ prev_timestamp_ = timestamp;
+
+ auto& stack = stacks_[track_id];
+ MaybeCloseStack(timestamp, &stack);
+ if (stack.empty())
+ return base::nullopt;
+
+ auto* slices = context_->storage->mutable_slice_table();
+ base::Optional<uint32_t> stack_idx = finder(stack);
+
+ // If we are trying to close slices that are not open on the stack (e.g.,
+ // slices that began before tracing started), bail out.
+ if (!stack_idx)
+ return base::nullopt;
+
+ uint32_t slice_idx = stack[stack_idx.value()].first;
+ PERFETTO_DCHECK(slices->dur()[slice_idx] == kPendingDuration);
+ slices->mutable_dur()->Set(slice_idx, timestamp - slices->ts()[slice_idx]);
+
+ if (args_callback) {
+ ArgsTracker* tracker = &stack.back().second;
+ auto bound_inserter = tracker->AddArgsTo(slices->id()[slice_idx]);
+ args_callback(&bound_inserter);
+ }
+
+ // If this slice is the top slice on the stack, pop it off.
+ if (*stack_idx == stack.size() - 1)
+ stack.pop_back();
+ return slices->id()[slice_idx];
+}
+
// Returns the first incomplete slice in the stack with matching name and
// category. We assume null category/name matches everything. Returns
// nullopt if no matching slice is found.
-base::Optional<size_t> SliceTracker::MatchingIncompleteSliceIndex(
- SlicesStack& stack,
+base::Optional<uint32_t> SliceTracker::MatchingIncompleteSliceIndex(
+ const SlicesStack& stack,
StringId name,
StringId category) {
auto* slices = context_->storage->mutable_slice_table();
@@ -126,68 +208,11 @@
const StringId& other_name = slices->name()[slice_idx];
if (!name.is_null() && !other_name.is_null() && name != other_name)
continue;
- return static_cast<size_t>(i);
+ return static_cast<uint32_t>(i);
}
return base::nullopt;
}
-base::Optional<uint32_t> SliceTracker::End(int64_t timestamp,
- TrackId track_id,
- StringId category,
- StringId name,
- SetArgsCallback args_callback) {
- // At this stage all events should be globally timestamp ordered.
- if (timestamp < prev_timestamp_) {
- context_->storage->IncrementStats(stats::slice_out_of_order);
- return base::nullopt;
- }
- prev_timestamp_ = timestamp;
-
- MaybeCloseStack(timestamp, &stacks_[track_id]);
-
- auto& stack = stacks_[track_id];
- if (stack.empty())
- return base::nullopt;
-
- auto* slices = context_->storage->mutable_slice_table();
- base::Optional<size_t> stack_idx =
- MatchingIncompleteSliceIndex(stack, name, category);
-
- // If we are trying to close slices that are not open on the stack (e.g.,
- // slices that began before tracing started), bail out.
- if (!stack_idx)
- return base::nullopt;
-
- if (*stack_idx != stack.size() - 1) {
- // This usually happens because we have two slices that are partially
- // overlapping.
- // [ slice 1 ]
- // [ slice 2 ]
- // This is invalid in chrome and should be fixed. Duration events should
- // either be nested or disjoint, never partially intersecting.
- PERFETTO_DLOG(
- "Incorrect ordering of End slice event around timestamp "
- "%" PRId64,
- timestamp);
- context_->storage->IncrementStats(stats::misplaced_end_event);
- }
-
- uint32_t slice_idx = stack[stack_idx.value()].first;
-
- PERFETTO_DCHECK(slices->dur()[slice_idx] == kPendingDuration);
- slices->mutable_dur()->Set(slice_idx, timestamp - slices->ts()[slice_idx]);
-
- if (args_callback) {
- ArgsTracker* tracker = &stack.back().second;
- ArgsTracker::BoundInserter inserter(tracker, TableId::kNestableSlices,
- slice_idx);
- args_callback(&inserter);
- }
-
- return CompleteSlice(track_id);
- // TODO(primiano): auto-close B slices left open at the end.
-}
-
void SliceTracker::FlushPendingSlices() {
// Clear the remaining stack entries. This ensures that any pending args are
// written to the storage. We don't close any slices with kPendingDuration so
@@ -199,40 +224,53 @@
stacks_.clear();
}
-base::Optional<uint32_t> SliceTracker::CompleteSlice(TrackId track_id) {
- auto& stack = stacks_[track_id];
- uint32_t slice_idx = stack.back().first;
- stack.pop_back();
- return slice_idx;
-}
-
void SliceTracker::MaybeCloseStack(int64_t ts, SlicesStack* stack) {
- const auto& slices = context_->storage->slice_table();
- bool pending_dur_descendent = false;
+ auto* slices = context_->storage->mutable_slice_table();
+ bool incomplete_descendent = false;
for (int i = static_cast<int>(stack->size()) - 1; i >= 0; i--) {
uint32_t slice_idx = (*stack)[static_cast<size_t>(i)].first;
- int64_t start_ts = slices.ts()[slice_idx];
- int64_t dur = slices.dur()[slice_idx];
+ int64_t start_ts = slices->ts()[slice_idx];
+ int64_t dur = slices->dur()[slice_idx];
int64_t end_ts = start_ts + dur;
if (dur == kPendingDuration) {
- pending_dur_descendent = true;
+ incomplete_descendent = true;
+ continue;
}
- if (pending_dur_descendent) {
+ if (incomplete_descendent) {
PERFETTO_DCHECK(ts >= start_ts);
- // Some trace producers emit END events in the wrong order (even after
- // sorting by timestamp), e.g. BEGIN A, BEGIN B, END A, END B. We discard
- // the mismatching END A in End(). Because of this, we can end up in a
- // situation where we attempt to close the stack on top of A at a
- // timestamp beyond A's parent. To avoid crashing in such a case, we just
- // emit a warning instead.
- if (dur != kPendingDuration && ts > end_ts) {
- PERFETTO_DLOG(
- "Incorrect ordering of begin/end slice events around timestamp "
- "%" PRId64,
- ts);
+
+ // Only process slices if the ts is past the end of the slice.
+ if (ts <= end_ts)
+ continue;
+
+ // This usually happens because we have two slices that are partially
+ // overlapping.
+ // [ slice 1 ]
+ // [ slice 2 ]
+ // This is invalid in chrome and should be fixed. Duration events should
+ // either be nested or disjoint, never partially intersecting.
+ PERFETTO_DLOG(
+ "Incorrect ordering of begin/end slice events around timestamp "
+ "%" PRId64,
+ ts);
+ context_->storage->IncrementStats(stats::misplaced_end_event);
+
+ // Every slice below this one should have a pending duration. Update
+ // of them to have the end ts of the current slice and pop them
+ // all off.
+ for (int j = static_cast<int>(stack->size()) - 1; j > i; --j) {
+ uint32_t child_idx = (*stack)[static_cast<size_t>(j)].first;
+ PERFETTO_DCHECK(slices->dur()[child_idx] == kPendingDuration);
+ slices->mutable_dur()->Set(child_idx, end_ts - slices->ts()[child_idx]);
+ stack->pop_back();
}
+
+ // Also pop the current row itself and reset the incomplete flag.
+ stack->pop_back();
+ incomplete_descendent = false;
+
continue;
}
@@ -253,7 +291,14 @@
hash.Update(slices.category()[slice_idx]);
hash.Update(slices.name()[slice_idx]);
}
- return static_cast<int64_t>(hash.digest());
+
+ // For clients which don't have an integer type (i.e. Javascript), returning
+ // hashes which have the top 11 bits set leads to numbers which are
+ // unrepresenatble. This means that clients cannot filter using this number as
+ // it will be meaningless when passed back to us. For this reason, make sure
+ // that the hash is always less than 2^53 - 1.
+ constexpr uint64_t kSafeBitmask = (1ull << 53) - 1;
+ return static_cast<int64_t>(hash.digest() & kSafeBitmask);
}
} // namespace trace_processor
diff --git a/src/trace_processor/slice_tracker.h b/src/trace_processor/slice_tracker.h
index a2ffd86..36fe5ef 100644
--- a/src/trace_processor/slice_tracker.h
+++ b/src/trace_processor/slice_tracker.h
@@ -43,6 +43,9 @@
StringId name,
SetArgsCallback args_callback = SetArgsCallback());
+ void BeginGpu(tables::GpuSliceTable::Row row,
+ SetArgsCallback args_callback = SetArgsCallback());
+
// virtual for testing
virtual base::Optional<uint32_t> Scoped(
int64_t timestamp,
@@ -52,6 +55,9 @@
int64_t duration,
SetArgsCallback args_callback = SetArgsCallback());
+ void ScopedGpu(const tables::GpuSliceTable::Row& row,
+ SetArgsCallback args_callback = SetArgsCallback());
+
// virtual for testing
virtual base::Optional<uint32_t> End(
int64_t timestamp,
@@ -60,6 +66,13 @@
StringId opt_name = {},
SetArgsCallback args_callback = SetArgsCallback());
+ // TODO(lalitm): eventually this method should become End and End should
+ // be renamed EndChrome.
+ base::Optional<SliceId> EndGpu(
+ int64_t ts,
+ TrackId track_id,
+ SetArgsCallback args_callback = SetArgsCallback());
+
void FlushPendingSlices();
private:
@@ -67,17 +80,22 @@
using StackMap = std::unordered_map<TrackId, SlicesStack>;
base::Optional<uint32_t> StartSlice(int64_t timestamp,
- int64_t duration,
TrackId track_id,
- StringId category,
- StringId name,
- SetArgsCallback args_callback);
- base::Optional<uint32_t> CompleteSlice(TrackId track_id);
+ SetArgsCallback args_callback,
+ std::function<SliceId()> inserter);
+
+ base::Optional<SliceId> CompleteSlice(
+ int64_t timestamp,
+ TrackId track_id,
+ SetArgsCallback args_callback,
+ std::function<base::Optional<uint32_t>(const SlicesStack&)> finder);
void MaybeCloseStack(int64_t end_ts, SlicesStack*);
- base::Optional<size_t> MatchingIncompleteSliceIndex(SlicesStack& stack,
- StringId name,
- StringId category);
+
+ base::Optional<uint32_t> MatchingIncompleteSliceIndex(
+ const SlicesStack& stack,
+ StringId name,
+ StringId category);
int64_t GetStackHash(const SlicesStack&);
// Timestamp of the previous event. Used to discard events arriving out
diff --git a/src/trace_processor/slice_tracker_unittest.cc b/src/trace_processor/slice_tracker_unittest.cc
index a38709e..6b27258 100644
--- a/src/trace_processor/slice_tracker_unittest.cc
+++ b/src/trace_processor/slice_tracker_unittest.cc
@@ -56,16 +56,18 @@
SliceTracker tracker(&context);
constexpr TrackId track{22u};
- tracker.Begin(2 /*ts*/, track, 0 /*cat*/, 1 /*name*/);
- tracker.End(10 /*ts*/, track, 0 /*cat*/, 1 /*name*/);
+ tracker.Begin(2 /*ts*/, track, kNullStringId /*cat*/,
+ StringId::Raw(1) /*name*/);
+ tracker.End(10 /*ts*/, track, kNullStringId /*cat*/,
+ StringId::Raw(1) /*name*/);
const auto& slices = context.storage->slice_table();
EXPECT_EQ(slices.row_count(), 1u);
EXPECT_EQ(slices.ts()[0], 2);
EXPECT_EQ(slices.dur()[0], 8);
EXPECT_EQ(slices.track_id()[0], track.value);
- EXPECT_EQ(slices.category()[0], 0u);
- EXPECT_EQ(slices.name()[0], 1u);
+ EXPECT_EQ(slices.category()[0].raw_id(), 0u);
+ EXPECT_EQ(slices.name()[0].raw_id(), 1u);
EXPECT_EQ(slices.depth()[0], 0u);
EXPECT_EQ(slices.arg_set_id()[0], kInvalidArgSetId);
}
@@ -73,17 +75,22 @@
TEST(SliceTrackerTest, OneSliceWithArgs) {
TraceProcessorContext context;
context.storage.reset(new TraceStorage());
+ context.global_args_tracker.reset(new GlobalArgsTracker(&context));
SliceTracker tracker(&context);
constexpr TrackId track{22u};
- tracker.Begin(2 /*ts*/, track, 0 /*cat*/, 1 /*name*/,
+ tracker.Begin(2 /*ts*/, track, kNullStringId /*cat*/,
+ StringId::Raw(1) /*name*/,
[](ArgsTracker::BoundInserter* inserter) {
- inserter->AddArg(/*flat_key=*/1, /*key=*/2,
+ inserter->AddArg(/*flat_key=*/StringId::Raw(1),
+ /*key=*/StringId::Raw(2),
/*value=*/Variadic::Integer(10));
});
- tracker.End(10 /*ts*/, track, 0 /*cat*/, 1 /*name*/,
+ tracker.End(10 /*ts*/, track, kNullStringId /*cat*/,
+ StringId::Raw(1) /*name*/,
[](ArgsTracker::BoundInserter* inserter) {
- inserter->AddArg(/*flat_key=*/3, /*key=*/4,
+ inserter->AddArg(/*flat_key=*/StringId::Raw(3),
+ /*key=*/StringId::Raw(4),
/*value=*/Variadic::Integer(20));
});
@@ -92,20 +99,20 @@
EXPECT_EQ(slices.ts()[0], 2);
EXPECT_EQ(slices.dur()[0], 8);
EXPECT_EQ(slices.track_id()[0], track.value);
- EXPECT_EQ(slices.category()[0], 0u);
- EXPECT_EQ(slices.name()[0], 1u);
+ EXPECT_EQ(slices.category()[0].raw_id(), 0u);
+ EXPECT_EQ(slices.name()[0].raw_id(), 1u);
EXPECT_EQ(slices.depth()[0], 0u);
auto set_id = slices.arg_set_id()[0];
- auto args = context.storage->args();
- EXPECT_EQ(args.set_ids()[0], set_id);
- EXPECT_EQ(args.flat_keys()[0], 1u);
- EXPECT_EQ(args.keys()[0], 2u);
- EXPECT_EQ(args.arg_values()[0], Variadic::Integer(10));
- EXPECT_EQ(args.set_ids()[1], set_id);
- EXPECT_EQ(args.flat_keys()[1], 3u);
- EXPECT_EQ(args.keys()[1], 4u);
- EXPECT_EQ(args.arg_values()[1], Variadic::Integer(20));
+ const auto& args = context.storage->arg_table();
+ EXPECT_EQ(args.arg_set_id()[0], set_id);
+ EXPECT_EQ(args.flat_key()[0].raw_id(), 1u);
+ EXPECT_EQ(args.key()[0].raw_id(), 2u);
+ EXPECT_EQ(args.int_value()[0], 10);
+ EXPECT_EQ(args.arg_set_id()[1], set_id);
+ EXPECT_EQ(args.flat_key()[1].raw_id(), 3u);
+ EXPECT_EQ(args.key()[1].raw_id(), 4u);
+ EXPECT_EQ(args.int_value()[1], 20);
}
TEST(SliceTrackerTest, TwoSliceDetailed) {
@@ -114,8 +121,10 @@
SliceTracker tracker(&context);
constexpr TrackId track{22u};
- tracker.Begin(2 /*ts*/, track, 0 /*cat*/, 1 /*name*/);
- tracker.Begin(3 /*ts*/, track, 0 /*cat*/, 2 /*name*/);
+ tracker.Begin(2 /*ts*/, track, kNullStringId /*cat*/,
+ StringId::Raw(1) /*name*/);
+ tracker.Begin(3 /*ts*/, track, kNullStringId /*cat*/,
+ StringId::Raw(2) /*name*/);
tracker.End(5 /*ts*/, track);
tracker.End(10 /*ts*/, track);
@@ -127,15 +136,15 @@
EXPECT_EQ(slices.ts()[idx], 2);
EXPECT_EQ(slices.dur()[idx], 8);
EXPECT_EQ(slices.track_id()[idx], track.value);
- EXPECT_EQ(slices.category()[idx], 0u);
- EXPECT_EQ(slices.name()[idx], 1u);
+ EXPECT_EQ(slices.category()[idx].raw_id(), 0u);
+ EXPECT_EQ(slices.name()[idx].raw_id(), 1u);
EXPECT_EQ(slices.depth()[idx++], 0u);
EXPECT_EQ(slices.ts()[idx], 3);
EXPECT_EQ(slices.dur()[idx], 2);
EXPECT_EQ(slices.track_id()[idx], track.value);
- EXPECT_EQ(slices.category()[idx], 0u);
- EXPECT_EQ(slices.name()[idx], 2u);
+ EXPECT_EQ(slices.category()[idx].raw_id(), 0u);
+ EXPECT_EQ(slices.name()[idx].raw_id(), 2u);
EXPECT_EQ(slices.depth()[idx], 1u);
EXPECT_EQ(slices.parent_stack_id()[0], 0);
@@ -149,9 +158,9 @@
SliceTracker tracker(&context);
constexpr TrackId track{22u};
- tracker.Begin(0 /*ts*/, track, 0, 0);
- tracker.Begin(1 /*ts*/, track, 0, 0);
- tracker.Scoped(2 /*ts*/, track, 0, 0, 6);
+ tracker.Begin(0 /*ts*/, track, kNullStringId, kNullStringId);
+ tracker.Begin(1 /*ts*/, track, kNullStringId, kNullStringId);
+ tracker.Scoped(2 /*ts*/, track, kNullStringId, kNullStringId, 6);
tracker.End(9 /*ts*/, track);
tracker.End(10 /*ts*/, track);
@@ -166,10 +175,14 @@
SliceTracker tracker(&context);
constexpr TrackId track{22u};
- tracker.Begin(2 /*ts*/, track, 5 /*cat*/, 1 /*name*/);
- tracker.End(3 /*ts*/, track, 1 /*cat*/, 1 /*name*/);
- tracker.End(4 /*ts*/, track, 0 /*cat*/, 2 /*name*/);
- tracker.End(5 /*ts*/, track, 5 /*cat*/, 1 /*name*/);
+ tracker.Begin(2 /*ts*/, track, StringId::Raw(5) /*cat*/,
+ StringId::Raw(1) /*name*/);
+ tracker.End(3 /*ts*/, track, StringId::Raw(1) /*cat*/,
+ StringId::Raw(1) /*name*/);
+ tracker.End(4 /*ts*/, track, kNullStringId /*cat*/,
+ StringId::Raw(2) /*name*/);
+ tracker.End(5 /*ts*/, track, StringId::Raw(5) /*cat*/,
+ StringId::Raw(1) /*name*/);
auto slices = ToSliceInfo(context.storage->slice_table());
EXPECT_THAT(slices, ElementsAre(SliceInfo{2, 3}));
@@ -184,10 +197,14 @@
// from being closed, leading to an inconsistency when we try to insert the
// final slice and it doesn't intersect with the still pending first slice.
constexpr TrackId track{22u};
- tracker.Scoped(2 /*ts*/, track, 0 /*cat*/, 1 /*name*/, 10 /* dur */);
- tracker.Scoped(2 /*ts*/, track, 0 /*cat*/, 1 /*name*/, 0 /* dur */);
- tracker.Scoped(12 /*ts*/, track, 0 /*cat*/, 1 /*name*/, 1 /* dur */);
- tracker.Scoped(13 /*ts*/, track, 0 /*cat*/, 1 /*name*/, 1 /* dur */);
+ tracker.Scoped(2 /*ts*/, track, kNullStringId /*cat*/,
+ StringId::Raw(1) /*name*/, 10 /* dur */);
+ tracker.Scoped(2 /*ts*/, track, kNullStringId /*cat*/,
+ StringId::Raw(1) /*name*/, 0 /* dur */);
+ tracker.Scoped(12 /*ts*/, track, kNullStringId /*cat*/,
+ StringId::Raw(1) /*name*/, 1 /* dur */);
+ tracker.Scoped(13 /*ts*/, track, kNullStringId /*cat*/,
+ StringId::Raw(1) /*name*/, 1 /* dur */);
auto slices = ToSliceInfo(context.storage->slice_table());
EXPECT_THAT(slices, ElementsAre(SliceInfo{2, 10}, SliceInfo{2, 0},
@@ -201,9 +218,9 @@
constexpr TrackId track_a{22u};
constexpr TrackId track_b{23u};
- tracker.Begin(0 /*ts*/, track_a, 0, 0);
- tracker.Scoped(2 /*ts*/, track_b, 0, 0, 6);
- tracker.Scoped(3 /*ts*/, track_b, 0, 0, 4);
+ tracker.Begin(0 /*ts*/, track_a, kNullStringId, kNullStringId);
+ tracker.Scoped(2 /*ts*/, track_b, kNullStringId, kNullStringId, 6);
+ tracker.Scoped(3 /*ts*/, track_b, kNullStringId, kNullStringId, 4);
tracker.End(10 /*ts*/, track_a);
tracker.FlushPendingSlices();
@@ -225,34 +242,47 @@
SliceTracker tracker(&context);
constexpr TrackId track{22u};
- tracker.Scoped(50 /*ts*/, track, 11 /*cat*/, 21 /*name*/, 100 /*dur*/);
- tracker.Begin(100 /*ts*/, track, 12 /*cat*/, 22 /*name*/);
- tracker.Scoped(450 /*ts*/, track, 12 /*cat*/, 22 /*name*/, 100 /*dur*/);
- tracker.End(500 /*ts*/, track, 12 /*cat*/, 22 /*name*/);
+ tracker.Scoped(50 /*ts*/, track, StringId::Raw(11) /*cat*/,
+ StringId::Raw(21) /*name*/, 100 /*dur*/);
+ tracker.Begin(100 /*ts*/, track, StringId::Raw(12) /*cat*/,
+ StringId::Raw(22) /*name*/);
// This slice should now have depth 0.
- tracker.Begin(800 /*ts*/, track, 13 /*cat*/, 23 /*name*/);
+ tracker.Scoped(450 /*ts*/, track, StringId::Raw(12) /*cat*/,
+ StringId::Raw(22) /*name*/, 100 /*dur*/);
+
+ // This slice should be ignored.
+ tracker.End(500 /*ts*/, track, StringId::Raw(12) /*cat*/,
+ StringId::Raw(22) /*name*/);
+
+ tracker.Begin(800 /*ts*/, track, StringId::Raw(13) /*cat*/,
+ StringId::Raw(23) /*name*/);
// Null cat and name matches everything.
- tracker.End(1000 /*ts*/, track, 0 /*cat*/, 0 /*name*/);
+ tracker.End(1000 /*ts*/, track, kNullStringId /*cat*/,
+ kNullStringId /*name*/);
// Slice will not close if category is different.
- tracker.Begin(1100 /*ts*/, track, 11 /*cat*/, 21 /*name*/);
- tracker.End(1200 /*ts*/, track, 12 /*cat*/, 21 /*name*/);
+ tracker.Begin(1100 /*ts*/, track, StringId::Raw(11) /*cat*/,
+ StringId::Raw(21) /*name*/);
+ tracker.End(1200 /*ts*/, track, StringId::Raw(12) /*cat*/,
+ StringId::Raw(21) /*name*/);
// Slice will not close if name is different.
- tracker.Begin(1300 /*ts*/, track, 11 /*cat*/, 21 /*name*/);
- tracker.End(1400 /*ts*/, track, 11 /*cat*/, 22 /*name*/);
+ tracker.Begin(1300 /*ts*/, track, StringId::Raw(11) /*cat*/,
+ StringId::Raw(21) /*name*/);
+ tracker.End(1400 /*ts*/, track, StringId::Raw(11) /*cat*/,
+ StringId::Raw(22) /*name*/);
tracker.FlushPendingSlices();
auto slices = ToSliceInfo(context.storage->slice_table());
- EXPECT_THAT(slices, ElementsAre(SliceInfo{50, 100}, SliceInfo{100, 400},
+ EXPECT_THAT(slices, ElementsAre(SliceInfo{50, 100}, SliceInfo{100, 50},
SliceInfo{450, 100}, SliceInfo{800, 200},
SliceInfo{1100, -1}, SliceInfo{1300, 0 - 1}));
EXPECT_EQ(context.storage->slice_table().depth()[0], 0u);
EXPECT_EQ(context.storage->slice_table().depth()[1], 1u);
- EXPECT_EQ(context.storage->slice_table().depth()[2], 2u);
+ EXPECT_EQ(context.storage->slice_table().depth()[2], 0u);
EXPECT_EQ(context.storage->slice_table().depth()[3], 0u);
}
diff --git a/src/trace_processor/sqlite/BUILD.gn b/src/trace_processor/sqlite/BUILD.gn
index 07b39c0..418e517 100644
--- a/src/trace_processor/sqlite/BUILD.gn
+++ b/src/trace_processor/sqlite/BUILD.gn
@@ -14,40 +14,44 @@
import("../../../gn/test.gni")
-source_set("sqlite") {
- sources = [
- "db_sqlite_table.cc",
- "db_sqlite_table.h",
- "query_constraints.cc",
- "query_constraints.h",
- "scoped_db.h",
- "sqlite3_str_split.cc",
- "sqlite3_str_split.h",
- "sqlite_table.cc",
- "sqlite_table.h",
- "sqlite_utils.h",
- ]
- deps = [
- "../../../gn:default_deps",
- "../../../gn:sqlite",
- "../../../include/perfetto/trace_processor",
- "../../base",
- "../db:lib",
- ]
-}
+if (enable_perfetto_trace_processor_sqlite) {
+ source_set("sqlite") {
+ sources = [
+ "db_sqlite_table.cc",
+ "db_sqlite_table.h",
+ "query_constraints.cc",
+ "query_constraints.h",
+ "scoped_db.h",
+ "sqlite3_str_split.cc",
+ "sqlite3_str_split.h",
+ "sqlite_table.cc",
+ "sqlite_table.h",
+ "sqlite_utils.h",
+ ]
+ deps = [
+ "../../../gn:default_deps",
+ "../../../gn:sqlite",
+ "../../../include/perfetto/trace_processor",
+ "../../../protos/perfetto/trace/ftrace:zero",
+ "../../base",
+ "../db:lib",
+ "../types",
+ ]
+ }
-perfetto_unittest_source_set("unittests") {
- testonly = true
- sources = [
- "db_sqlite_table_unittest.cc",
- "query_constraints_unittest.cc",
- "sqlite3_str_split_unittest.cc",
- ]
- deps = [
- ":sqlite",
- "../../../gn:default_deps",
- "../../../gn:gtest_and_gmock",
- "../../../gn:sqlite",
- "../../base",
- ]
+ perfetto_unittest_source_set("unittests") {
+ testonly = true
+ sources = [
+ "db_sqlite_table_unittest.cc",
+ "query_constraints_unittest.cc",
+ "sqlite3_str_split_unittest.cc",
+ ]
+ deps = [
+ ":sqlite",
+ "../../../gn:default_deps",
+ "../../../gn:gtest_and_gmock",
+ "../../../gn:sqlite",
+ "../../base",
+ ]
+ }
}
diff --git a/src/trace_processor/sqlite/db_sqlite_table.cc b/src/trace_processor/sqlite/db_sqlite_table.cc
index 65ed66e..83789ea 100644
--- a/src/trace_processor/sqlite/db_sqlite_table.cc
+++ b/src/trace_processor/sqlite/db_sqlite_table.cc
@@ -45,6 +45,8 @@
return FilterOp::kIsNotNull;
case SQLITE_INDEX_CONSTRAINT_LIKE:
return FilterOp::kLike;
+ case SQLITE_INDEX_CONSTRAINT_GLOB:
+ return FilterOp::kGlob;
default:
PERFETTO_FATAL("Currently unsupported constraint");
}
@@ -91,26 +93,31 @@
}
util::Status DbSqliteTable::Init(int, const char* const*, Schema* schema) {
+ *schema = ComputeSchema(*table_, name().c_str());
+ return util::OkStatus();
+}
+
+SqliteTable::Schema DbSqliteTable::ComputeSchema(const Table& table,
+ const char* table_name) {
std::vector<SqliteTable::Column> schema_cols;
- for (uint32_t i = 0; i < table_->GetColumnCount(); ++i) {
- const auto& col = table_->GetColumn(i);
+ for (uint32_t i = 0; i < table.GetColumnCount(); ++i) {
+ const auto& col = table.GetColumn(i);
schema_cols.emplace_back(i, col.name(), col.type());
}
+
// TODO(lalitm): this is hardcoded to be the id column but change this to be
// more generic in the future.
- const auto* col = table_->GetColumnByName("id");
+ const auto* col = table.GetColumnByName("id");
if (!col) {
PERFETTO_FATAL(
"id column not found in %s. Currently all db Tables need to contain an "
"id column; this constraint will be relaxed in the future.",
- name().c_str());
+ table_name);
}
std::vector<size_t> primary_keys;
primary_keys.emplace_back(col->index_in_table());
-
- *schema = Schema(std::move(schema_cols), std::move(primary_keys));
- return util::OkStatus();
+ return Schema(std::move(schema_cols), std::move(primary_keys));
}
int DbSqliteTable::BestIndex(const QueryConstraints& qc, BestIndexInfo* info) {
@@ -215,9 +222,12 @@
} else if (sqlite_utils::IsOpEq(c.op)) {
// If there is only a single equality constraint, we have special logic
// to sort by that column and then binary search if we see the constraint
- // set often. Model this by dividing but the log of the number of rows as
+ // set often. Model this by dividing by the log of the number of rows as
// a good approximation. Otherwise, we'll need to do a full table scan.
- filter_cost += cs.size() == 1
+ // Alternatively, if the column is sorted, we can use the same binary
+ // search logic so we have the same low cost (even better because we don't
+ // have to sort at all).
+ filter_cost += cs.size() == 1 || col.IsSorted()
? (2 * current_row_count) / log2(current_row_count)
: current_row_count;
@@ -250,11 +260,50 @@
}
std::unique_ptr<SqliteTable::Cursor> DbSqliteTable::CreateCursor() {
- return std::unique_ptr<Cursor>(new Cursor(this));
+ return std::unique_ptr<Cursor>(new Cursor(this, table_));
}
-DbSqliteTable::Cursor::Cursor(DbSqliteTable* table)
- : SqliteTable::Cursor(table), initial_db_table_(table->table_) {}
+DbSqliteTable::Cursor::Cursor(SqliteTable* sqlite_table, const Table* table)
+ : SqliteTable::Cursor(sqlite_table), initial_db_table_(table) {}
+
+void DbSqliteTable::Cursor::TryCacheCreateSortedTable(
+ const QueryConstraints& qc,
+ FilterHistory history) {
+ if (history == FilterHistory::kDifferent) {
+ // Every time we get a new constraint set, reset the state of any caching
+ // structures.
+ sorted_cache_table_ = base::nullopt;
+ repeated_cache_count_ = 0;
+ return;
+ }
+
+ PERFETTO_DCHECK(history == FilterHistory::kSame);
+
+ // Only try and create the cached table on exactly the third time we see this
+ // constraint set.
+ constexpr uint32_t kRepeatedThreshold = 3;
+ if (repeated_cache_count_++ != kRepeatedThreshold)
+ return;
+
+ // If we have more than one constraint, we can't cache the table using
+ // this method.
+ if (qc.constraints().size() != 1)
+ return;
+
+ // If the constraing is not an equality constraint, there's little
+ // benefit to caching
+ const auto& c = qc.constraints().front();
+ if (!sqlite_utils::IsOpEq(c.op))
+ return;
+
+ // If the column is already sorted, we don't need to cache at all.
+ uint32_t col = static_cast<uint32_t>(c.column);
+ if (initial_db_table_->GetColumn(col).IsSorted())
+ return;
+
+ // Create the cached table, sorting on the column which has the constraint.
+ sorted_cache_table_ = initial_db_table_->Sort({Order{col, false}});
+}
int DbSqliteTable::Cursor::Filter(const QueryConstraints& qc,
sqlite3_value** argv,
@@ -263,23 +312,9 @@
// before the table's destructor.
iterator_ = base::nullopt;
- if (history == FilterHistory::kSame && qc.constraints().size() == 1 &&
- sqlite_utils::IsOpEq(qc.constraints().front().op)) {
- // If we've seen the same constraint set with a single equality constraint
- // more than |kRepeatedThreshold| times, we assume we will see it more
- // in the future and thus cache a table sorted on the column. That way,
- // future equality constraints can binary search for the value instead of
- // doing a full table scan.
- constexpr uint32_t kRepeatedThreshold = 3;
- if (!sorted_cache_table_ && repeated_cache_count_++ > kRepeatedThreshold) {
- const auto& c = qc.constraints().front();
- uint32_t col = static_cast<uint32_t>(c.column);
- sorted_cache_table_ = initial_db_table_->Sort({Order{col, false}});
- }
- } else {
- sorted_cache_table_ = base::nullopt;
- repeated_cache_count_ = 0;
- }
+ // Tries to create a sorted cached table which can be used to speed up
+ // filters below.
+ TryCacheCreateSortedTable(qc, history);
// We reuse this vector to reduce memory allocations on nested subqueries.
constraints_.resize(qc.constraints().size());
diff --git a/src/trace_processor/sqlite/db_sqlite_table.h b/src/trace_processor/sqlite/db_sqlite_table.h
index 1e39653..2a606ec 100644
--- a/src/trace_processor/sqlite/db_sqlite_table.h
+++ b/src/trace_processor/sqlite/db_sqlite_table.h
@@ -26,9 +26,9 @@
// Implements the SQLite table interface for db tables.
class DbSqliteTable : public SqliteTable {
public:
- class Cursor final : public SqliteTable::Cursor {
+ class Cursor : public SqliteTable::Cursor {
public:
- explicit Cursor(DbSqliteTable* table);
+ Cursor(SqliteTable*, const Table* table);
Cursor(Cursor&&) noexcept = default;
Cursor& operator=(Cursor&&) = default;
@@ -41,12 +41,22 @@
int Eof() override;
int Column(sqlite3_context*, int N) override;
+ protected:
+ // Sets the table this class uses as the reference for all filter
+ // operations. Should be immediately followed by a call to Filter with
+ // |FilterHistory::kDifferent|.
+ void set_table(const Table* table) { initial_db_table_ = table; }
+
private:
enum class Mode {
kSingleRow,
kTable,
};
+ // Tries to create a sorted table to cache in |sorted_cache_table_| if the
+ // constraint set matches the requirements.
+ void TryCacheCreateSortedTable(const QueryConstraints&, FilterHistory);
+
const Table* SourceTable() const {
// Try and use the sorted cache table (if it exists) to speed up the
// sorting. Otherwise, just use the original table.
@@ -101,6 +111,9 @@
int ModifyConstraints(QueryConstraints*) override;
int BestIndex(const QueryConstraints&, BestIndexInfo*) override;
+ static SqliteTable::Schema ComputeSchema(const Table& table,
+ const char* table_name);
+
// static for testing.
static QueryCost EstimateCost(const Table& table, const QueryConstraints& qc);
diff --git a/src/trace_processor/sqlite/db_sqlite_table_unittest.cc b/src/trace_processor/sqlite/db_sqlite_table_unittest.cc
index 4f39839..2fbc3e4 100644
--- a/src/trace_processor/sqlite/db_sqlite_table_unittest.cc
+++ b/src/trace_processor/sqlite/db_sqlite_table_unittest.cc
@@ -33,12 +33,18 @@
Column("a", &a_, Column::Flag::kNoFlag, this, 1u, 0u));
columns_.emplace_back(
Column("sorted", &sorted_, Column::Flag::kSorted, this, 2u, 0u));
+ columns_.emplace_back(
+ Column("other", &other_, Column::Flag::kNoFlag, this, 3u, 0u));
+ columns_.emplace_back(
+ Column("other2", &other_, Column::Flag::kNoFlag, this, 4u, 0u));
}
private:
StringPool pool_;
SparseVector<uint32_t> a_;
SparseVector<uint32_t> sorted_;
+ SparseVector<uint32_t> other_;
+ SparseVector<uint32_t> other2_;
};
TEST(DbSqliteTable, IdEqCheaperThanOtherEq) {
@@ -95,6 +101,27 @@
ASSERT_GT(single_cost.rows, multi_cost.rows);
}
+TEST(DbSqliteTable, MultiSortedEqCheaperThanMultiUnsortedEq) {
+ TestTable table(1234);
+
+ QueryConstraints sorted_eq;
+ sorted_eq.AddConstraint(2u, SQLITE_INDEX_CONSTRAINT_EQ, 0u);
+ sorted_eq.AddConstraint(3u, SQLITE_INDEX_CONSTRAINT_EQ, 0u);
+
+ auto sorted_cost = DbSqliteTable::EstimateCost(table, sorted_eq);
+
+ QueryConstraints unsorted_eq;
+ unsorted_eq.AddConstraint(3u, SQLITE_INDEX_CONSTRAINT_EQ, 0u);
+ unsorted_eq.AddConstraint(4u, SQLITE_INDEX_CONSTRAINT_EQ, 0u);
+
+ auto unsorted_cost = DbSqliteTable::EstimateCost(table, unsorted_eq);
+
+ // The number of rows should be the same but the cost of the sorted
+ // query should be less.
+ ASSERT_LT(sorted_cost.cost, unsorted_cost.cost);
+ ASSERT_EQ(sorted_cost.rows, unsorted_cost.rows);
+}
+
TEST(DbSqliteTable, EmptyTableCosting) {
TestTable table(0u);
diff --git a/src/trace_processor/sqlite/sqlite_table.h b/src/trace_processor/sqlite/sqlite_table.h
index a5f95e1..2cb7a0f 100644
--- a/src/trace_processor/sqlite/sqlite_table.h
+++ b/src/trace_processor/sqlite/sqlite_table.h
@@ -55,7 +55,9 @@
size_t index() const { return index_; }
const std::string& name() const { return name_; }
SqlValue::Type type() const { return type_; }
+
bool hidden() const { return hidden_; }
+ void set_hidden(bool hidden) { hidden_ = hidden; }
private:
size_t index_ = 0;
@@ -137,6 +139,8 @@
std::string ToCreateTableStmt() const;
const std::vector<Column>& columns() const { return columns_; }
+ std::vector<Column>* mutable_columns() { return &columns_; }
+
const std::vector<size_t> primary_keys() { return primary_keys_; }
private:
diff --git a/src/trace_processor/sqlite_experimental_flamegraph_table.cc b/src/trace_processor/sqlite_experimental_flamegraph_table.cc
new file mode 100644
index 0000000..12a9bb6
--- /dev/null
+++ b/src/trace_processor/sqlite_experimental_flamegraph_table.cc
@@ -0,0 +1,178 @@
+
+/*
+ * Copyright (C) 2020 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.
+ */
+
+#include "src/trace_processor/sqlite_experimental_flamegraph_table.h"
+
+#include "src/trace_processor/heap_profile_tracker.h"
+#include "src/trace_processor/importers/proto/heap_graph_tracker.h"
+#include "src/trace_processor/trace_processor_context.h"
+
+namespace perfetto {
+namespace trace_processor {
+
+namespace {
+
+SqliteExperimentalFlamegraphTable::InputValues GetInputValues(
+ const QueryConstraints& qc,
+ sqlite3_value** argv) {
+ using T = tables::ExperimentalFlamegraphNodesTable;
+
+ const auto& cs = qc.constraints();
+
+ auto ts_fn = [](const QueryConstraints::Constraint& c) {
+ return c.column == static_cast<int>(T::ColumnIndex::ts) &&
+ c.op == SQLITE_INDEX_CONSTRAINT_EQ;
+ };
+ auto upid_fn = [](const QueryConstraints::Constraint& c) {
+ return c.column == static_cast<int>(T::ColumnIndex::upid) &&
+ c.op == SQLITE_INDEX_CONSTRAINT_EQ;
+ };
+ auto profile_type_fn = [](const QueryConstraints::Constraint& c) {
+ return c.column == static_cast<int>(T::ColumnIndex::profile_type) &&
+ c.op == SQLITE_INDEX_CONSTRAINT_EQ;
+ };
+
+ auto ts_idx = static_cast<uint32_t>(
+ std::distance(cs.begin(), std::find_if(cs.begin(), cs.end(), ts_fn)));
+ auto upid_idx = static_cast<uint32_t>(
+ std::distance(cs.begin(), std::find_if(cs.begin(), cs.end(), upid_fn)));
+ auto profile_type_idx = static_cast<uint32_t>(std::distance(
+ cs.begin(), std::find_if(cs.begin(), cs.end(), profile_type_fn)));
+
+ // We should always have valid indices 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(ts_idx < cs.size());
+ PERFETTO_CHECK(upid_idx < cs.size());
+ PERFETTO_CHECK(profile_type_idx < cs.size());
+
+ int64_t ts = sqlite3_value_int64(argv[ts_idx]);
+ UniquePid upid = static_cast<UniquePid>(sqlite3_value_int64(argv[upid_idx]));
+ std::string profile_type =
+ reinterpret_cast<const char*>(sqlite3_value_text(argv[profile_type_idx]));
+
+ return SqliteExperimentalFlamegraphTable::InputValues{ts, upid, profile_type};
+}
+
+} // namespace
+
+SqliteExperimentalFlamegraphTable::SqliteExperimentalFlamegraphTable(
+ sqlite3*,
+ TraceProcessorContext* context)
+ : context_(context) {}
+
+SqliteExperimentalFlamegraphTable::~SqliteExperimentalFlamegraphTable() =
+ default;
+
+void SqliteExperimentalFlamegraphTable::RegisterTable(
+ sqlite3* db,
+ TraceProcessorContext* context) {
+ SqliteTable::Register<SqliteExperimentalFlamegraphTable>(
+ db, context, "experimental_flamegraph");
+}
+
+util::Status SqliteExperimentalFlamegraphTable::Init(
+ int,
+ const char* const*,
+ SqliteTable::Schema* schema) {
+ // Create an empty table for the sake of getting the schema.
+ tables::ExperimentalFlamegraphNodesTable table(nullptr, nullptr);
+ *schema = DbSqliteTable::ComputeSchema(table, name().c_str());
+
+ using T = tables::ExperimentalFlamegraphNodesTable;
+
+ // TODO(lalitm): make it so that this happens on the macro table itself.
+ auto& cols = *schema->mutable_columns();
+ cols[static_cast<uint32_t>(T::ColumnIndex::ts)].set_hidden(true);
+ cols[static_cast<uint32_t>(T::ColumnIndex::upid)].set_hidden(true);
+ cols[static_cast<uint32_t>(T::ColumnIndex::profile_type)].set_hidden(true);
+
+ return util::OkStatus();
+}
+
+int SqliteExperimentalFlamegraphTable::BestIndex(const QueryConstraints& qc,
+ BestIndexInfo*) {
+ using T = tables::ExperimentalFlamegraphNodesTable;
+
+ const auto& cs = qc.constraints();
+
+ auto ts_fn = [](const QueryConstraints::Constraint& c) {
+ return c.column == static_cast<int>(T::ColumnIndex::ts) &&
+ c.op == SQLITE_INDEX_CONSTRAINT_EQ;
+ };
+ bool has_ts_cs = std::find_if(cs.begin(), cs.end(), ts_fn) != cs.end();
+
+ auto upid_fn = [](const QueryConstraints::Constraint& c) {
+ return c.column == static_cast<int>(T::ColumnIndex::upid) &&
+ c.op == SQLITE_INDEX_CONSTRAINT_EQ;
+ };
+ bool has_upid_cs = std::find_if(cs.begin(), cs.end(), upid_fn) != cs.end();
+
+ auto profile_type_fn = [](const QueryConstraints::Constraint& c) {
+ return c.column == static_cast<int>(T::ColumnIndex::profile_type) &&
+ c.op == SQLITE_INDEX_CONSTRAINT_EQ;
+ };
+ bool has_profile_type_cs =
+ std::find_if(cs.begin(), cs.end(), profile_type_fn) != cs.end();
+
+ return has_ts_cs && has_upid_cs && has_profile_type_cs ? SQLITE_OK
+ : SQLITE_CONSTRAINT;
+}
+
+std::unique_ptr<SqliteTable::Cursor>
+SqliteExperimentalFlamegraphTable::CreateCursor() {
+ return std::unique_ptr<Cursor>(new Cursor(this, context_));
+}
+
+SqliteExperimentalFlamegraphTable::Cursor::Cursor(
+ SqliteTable* sqlite_table,
+ TraceProcessorContext* context)
+ : DbSqliteTable::Cursor(sqlite_table, nullptr), context_(context) {}
+
+int SqliteExperimentalFlamegraphTable::Cursor::Filter(
+ const QueryConstraints& qc,
+ sqlite3_value** argv,
+ FilterHistory) {
+ // Extract the old table to free after we call the parent Filter function.
+ // We need to do this to make sure that we don't get a use-after-free for
+ // any pointers the parent is holding onto in this table.
+ auto old_table = std::move(table_);
+
+ // Get the input column values and compute the flamegraph using them.
+ values_ = GetInputValues(qc, argv);
+
+ if (values_.profile_type == "graph") {
+ auto* tracker = HeapGraphTracker::GetOrCreate(context_);
+ table_ = tracker->BuildFlamegraph(values_.ts, values_.upid);
+ }
+ if (values_.profile_type == "native") {
+ table_ = BuildNativeFlamegraph(context_->storage.get(),
+ values_.upid, values_.ts);
+ }
+
+ // table_ can be nullptr precisely where the constraints passed to us don't
+ // make sense. Therefore, we can just return this to SQLite.
+ if (!table_)
+ return SQLITE_CONSTRAINT;
+
+ // Set the table in the parent to the correct value and then filter.
+ DbSqliteTable::Cursor::set_table(table_.get());
+ return DbSqliteTable::Cursor::Filter(qc, argv, FilterHistory::kDifferent);
+}
+
+} // namespace trace_processor
+} // namespace perfetto
diff --git a/src/trace_processor/sqlite_experimental_flamegraph_table.h b/src/trace_processor/sqlite_experimental_flamegraph_table.h
new file mode 100644
index 0000000..e531814
--- /dev/null
+++ b/src/trace_processor/sqlite_experimental_flamegraph_table.h
@@ -0,0 +1,73 @@
+/*
+ * Copyright (C) 2020 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.
+ */
+
+#ifndef SRC_TRACE_PROCESSOR_SQLITE_EXPERIMENTAL_FLAMEGRAPH_TABLE_H_
+#define SRC_TRACE_PROCESSOR_SQLITE_EXPERIMENTAL_FLAMEGRAPH_TABLE_H_
+
+#include "src/trace_processor/sqlite/db_sqlite_table.h"
+
+#include "src/trace_processor/trace_storage.h"
+
+namespace perfetto {
+namespace trace_processor {
+
+class TraceProcessorContext;
+
+class SqliteExperimentalFlamegraphTable : public SqliteTable {
+ public:
+ struct InputValues {
+ int64_t ts;
+ UniquePid upid;
+ std::string profile_type;
+ };
+
+ class Cursor : public DbSqliteTable::Cursor {
+ public:
+ Cursor(SqliteTable*, TraceProcessorContext*);
+
+ int Filter(const QueryConstraints& qc,
+ sqlite3_value** argv,
+ FilterHistory) override;
+
+ private:
+ TraceProcessorContext* context_ = nullptr;
+
+ std::unique_ptr<Table> table_;
+ InputValues values_ = {};
+ };
+
+ SqliteExperimentalFlamegraphTable(sqlite3*, TraceProcessorContext*);
+ ~SqliteExperimentalFlamegraphTable() override;
+
+ static void RegisterTable(sqlite3* db, TraceProcessorContext* storage);
+
+ // SqliteTable implementation.
+ util::Status Init(int,
+ const char* const*,
+ SqliteTable::Schema*) override final;
+ std::unique_ptr<SqliteTable::Cursor> CreateCursor() override;
+ int BestIndex(const QueryConstraints&, BestIndexInfo*) override;
+
+ private:
+ friend class Cursor;
+
+ TraceProcessorContext* context_;
+};
+
+} // namespace trace_processor
+} // namespace perfetto
+
+#endif // SRC_TRACE_PROCESSOR_SQLITE_EXPERIMENTAL_FLAMEGRAPH_TABLE_H_
diff --git a/src/trace_processor/raw_table.cc b/src/trace_processor/sqlite_raw_table.cc
similarity index 78%
rename from src/trace_processor/raw_table.cc
rename to src/trace_processor/sqlite_raw_table.cc
index ac8127f..af66914 100644
--- a/src/trace_processor/raw_table.cc
+++ b/src/trace_processor/sqlite_raw_table.cc
@@ -14,15 +14,15 @@
* limitations under the License.
*/
-#include "src/trace_processor/raw_table.h"
+#include "src/trace_processor/sqlite_raw_table.h"
#include <inttypes.h>
#include "perfetto/base/compiler.h"
#include "perfetto/ext/base/string_utils.h"
-#include "src/trace_processor/gfp_flags.h"
#include "src/trace_processor/sqlite/sqlite_utils.h"
-#include "src/trace_processor/variadic.h"
+#include "src/trace_processor/types/gfp_flags.h"
+#include "src/trace_processor/types/variadic.h"
#include "protos/perfetto/trace/ftrace/binder.pbzero.h"
#include "protos/perfetto/trace/ftrace/clk.pbzero.h"
@@ -50,10 +50,10 @@
}
} // namespace
-RawTable::RawTable(sqlite3* db, const TraceStorage* storage)
- : storage_(storage) {
+SqliteRawTable::SqliteRawTable(sqlite3* db, const TraceStorage* storage)
+ : DbSqliteTable(db, &storage->raw_table()), storage_(storage) {
auto fn = [](sqlite3_context* ctx, int argc, sqlite3_value** argv) {
- auto* thiz = static_cast<RawTable*>(sqlite3_user_data(ctx));
+ auto* thiz = static_cast<SqliteRawTable*>(sqlite3_user_data(ctx));
thiz->ToSystrace(ctx, argc, argv);
};
sqlite3_create_function(db, "to_ftrace", 1,
@@ -61,41 +61,13 @@
nullptr);
}
-void RawTable::RegisterTable(sqlite3* db, const TraceStorage* storage) {
- SqliteTable::Register<RawTable>(db, storage, "raw");
+SqliteRawTable::~SqliteRawTable() = default;
+
+void SqliteRawTable::RegisterTable(sqlite3* db, const TraceStorage* storage) {
+ SqliteTable::Register<SqliteRawTable>(db, storage, "raw");
}
-StorageSchema RawTable::CreateStorageSchema() {
- const auto& raw = storage_->raw_events();
- return StorageSchema::Builder()
- .AddGenericNumericColumn("id", RowAccessor())
- .AddOrderedNumericColumn("ts", &raw.timestamps())
- .AddStringColumn("name", &raw.name_ids(), &storage_->string_pool())
- .AddNumericColumn("cpu", &raw.cpus())
- .AddNumericColumn("utid", &raw.utids())
- .AddNumericColumn("arg_set_id", &raw.arg_set_ids())
- .Build({"name", "ts"});
-}
-
-uint32_t RawTable::RowCount() {
- return static_cast<uint32_t>(storage_->raw_events().raw_event_count());
-}
-
-int RawTable::BestIndex(const QueryConstraints& qc, BestIndexInfo* info) {
- info->estimated_cost = RowCount();
- info->sqlite_omit_order_by = true;
-
- // Only the string columns are handled by SQLite
- size_t name_index = schema().ColumnIndexFromName("name");
- for (size_t i = 0; i < qc.constraints().size(); i++) {
- info->sqlite_omit_constraint[i] =
- qc.constraints()[i].column != static_cast<int>(name_index);
- }
-
- return SQLITE_OK;
-}
-
-bool RawTable::ParseGfpFlags(Variadic value, base::StringWriter* writer) {
+bool SqliteRawTable::ParseGfpFlags(Variadic value, base::StringWriter* writer) {
const auto& metadata_table = storage_->metadata_table();
auto opt_name_idx = metadata_table.name().IndexOf(
@@ -118,15 +90,21 @@
return true;
}
-void RawTable::FormatSystraceArgs(NullTermStringView event_name,
- ArgSetId arg_set_id,
- base::StringWriter* writer) {
- const auto& set_ids = storage_->args().set_ids();
- auto lb = std::lower_bound(set_ids.begin(), set_ids.end(), arg_set_id);
- auto ub = std::find(lb, set_ids.end(), arg_set_id + 1);
+void SqliteRawTable::FormatSystraceArgs(NullTermStringView event_name,
+ ArgSetId arg_set_id,
+ base::StringWriter* writer) {
+ const auto& set_ids = storage_->arg_table().arg_set_id();
- auto start_row = static_cast<uint32_t>(std::distance(set_ids.begin(), lb));
- auto end_row = static_cast<uint32_t>(std::distance(set_ids.begin(), ub));
+ // TODO(lalitm): this code is quite hacky for performance reasons. We assume
+ // that the row map is a contiguous range (which is always the case
+ // because arg_set_ids are contiguous by definition). We also assume that
+ // the proto field order is also the order of insertion (which happens to
+ // be true but proabably shouldn't be relied on).
+ RowMap rm = storage_->arg_table().FilterToRowMap({set_ids.eq(arg_set_id)});
+ if (rm.empty())
+ return;
+
+ uint32_t start_row = rm.Get(0);
using ValueWriter = std::function<void(const Variadic&)>;
auto write_value = [this, writer](const Variadic& value) {
switch (value.type) {
@@ -159,24 +137,22 @@
};
auto write_value_at_index = [this, start_row](uint32_t arg_idx,
ValueWriter value_fn) {
- value_fn(storage_->args().arg_values()[start_row + arg_idx]);
+ value_fn(storage_->GetArgValue(start_row + arg_idx));
};
auto write_arg = [this, writer, start_row](uint32_t arg_idx,
ValueWriter value_fn) {
uint32_t arg_row = start_row + arg_idx;
- const auto& args = storage_->args();
- const auto& key = storage_->GetString(args.keys()[arg_row]);
+ const auto& args = storage_->arg_table();
+ const auto& key = storage_->GetString(args.key()[arg_row]);
+ auto value = storage_->GetArgValue(arg_row);
writer->AppendChar(' ');
writer->AppendString(key.c_str(), key.size());
writer->AppendChar('=');
- if (key == "gfp_flags" &&
- ParseGfpFlags(args.arg_values()[arg_row], writer)) {
+ if (key == "gfp_flags" && ParseGfpFlags(value, writer))
return;
- }
-
- value_fn(args.arg_values()[arg_row]);
+ value_fn(value);
};
if (event_name == "sched_switch") {
@@ -234,17 +210,17 @@
write_value_at_index(BT::kToThreadFieldNumber - 1, write_value);
write_arg(BT::kReplyFieldNumber - 1, write_value);
writer->AppendString(" flags=0x");
- write_value_at_index(
- BT::kFlagsFieldNumber - 1, [writer](const Variadic& value) {
- PERFETTO_DCHECK(value.type == Variadic::Type::kUint);
- writer->AppendHexInt(value.uint_value);
- });
+ write_value_at_index(BT::kFlagsFieldNumber - 1,
+ [writer](const Variadic& value) {
+ PERFETTO_DCHECK(value.type == Variadic::Type::kUint);
+ writer->AppendHexInt(value.uint_value);
+ });
writer->AppendString(" code=0x");
- write_value_at_index(
- BT::kCodeFieldNumber - 1, [writer](const Variadic& value) {
- PERFETTO_DCHECK(value.type == Variadic::Type::kUint);
- writer->AppendHexInt(value.uint_value);
- });
+ write_value_at_index(BT::kCodeFieldNumber - 1,
+ [writer](const Variadic& value) {
+ PERFETTO_DCHECK(value.type == Variadic::Type::kUint);
+ writer->AppendHexInt(value.uint_value);
+ });
return;
} else if (event_name == "binder_transaction_alloc_buf") {
using BTAB = protos::pbzero::BinderTransactionAllocBufFtraceEvent;
@@ -291,9 +267,8 @@
} else if (event_name == "print") {
// 'ip' may be the first field or it may be dropped. We only care
// about the 'buf' field which will always appear last.
- uint32_t arg_row = end_row - 1;
- const auto& args = storage_->args();
- const auto& value = args.arg_values()[arg_row];
+ uint32_t arg_row = rm.Get(rm.size() - 1);
+ const auto& value = storage_->GetArgValue(arg_row);
const auto& str = storage_->GetString(value.string_value);
// If the last character is a newline in a print, just drop it.
auto chars_to_print = !str.empty() && str.c_str()[str.size() - 1] == '\n'
@@ -365,38 +340,37 @@
return;
}
- uint32_t arg = 0;
- for (auto it = lb; it != ub; it++) {
- write_arg(arg++, write_value);
+ for (auto it = rm.IterateRows(); it; it.Next()) {
+ write_arg(it.index(), write_value);
}
}
-void RawTable::ToSystrace(sqlite3_context* ctx,
- int argc,
- sqlite3_value** argv) {
+void SqliteRawTable::ToSystrace(sqlite3_context* ctx,
+ int argc,
+ sqlite3_value** argv) {
if (argc != 1 || sqlite3_value_type(argv[0]) != SQLITE_INTEGER) {
sqlite3_result_error(ctx, "Usage: to_ftrace(id)", -1);
return;
}
uint32_t row = static_cast<uint32_t>(sqlite3_value_int64(argv[0]));
- const auto& raw_evts = storage_->raw_events();
+ const auto& raw_evts = storage_->raw_table();
- UniqueTid utid = raw_evts.utids()[row];
- const auto& thread = storage_->GetThread(utid);
+ UniqueTid utid = raw_evts.utid()[row];
uint32_t tgid = 0;
- if (thread.upid.has_value()) {
- tgid = storage_->GetProcess(thread.upid.value()).pid;
+ auto opt_upid = storage_->thread_table().upid()[utid];
+ if (opt_upid.has_value()) {
+ tgid = storage_->process_table().pid()[*opt_upid];
}
- const auto& name = storage_->GetString(thread.name_id);
+ const auto& name = storage_->GetString(storage_->thread_table().name()[utid]);
char line[4096];
base::StringWriter writer(line, sizeof(line));
- ftrace_utils::FormatSystracePrefix(raw_evts.timestamps()[row],
- raw_evts.cpus()[row], thread.tid, tgid,
+ ftrace_utils::FormatSystracePrefix(raw_evts.ts()[row], raw_evts.cpu()[row],
+ storage_->thread_table().tid()[utid], tgid,
base::StringView(name), &writer);
- const auto& event_name = storage_->GetString(raw_evts.name_ids()[row]);
+ const auto& event_name = storage_->GetString(raw_evts.name()[row]);
writer.AppendChar(' ');
if (event_name == "print") {
writer.AppendString("tracing_mark_write");
@@ -405,7 +379,7 @@
}
writer.AppendChar(':');
- FormatSystraceArgs(event_name, raw_evts.arg_set_ids()[row], &writer);
+ FormatSystraceArgs(event_name, raw_evts.arg_set_id()[row], &writer);
sqlite3_result_text(ctx, writer.CreateStringCopy(), -1, free);
}
diff --git a/src/trace_processor/raw_table.h b/src/trace_processor/sqlite_raw_table.h
similarity index 74%
rename from src/trace_processor/raw_table.h
rename to src/trace_processor/sqlite_raw_table.h
index e4506b4..99ebff2 100644
--- a/src/trace_processor/raw_table.h
+++ b/src/trace_processor/sqlite_raw_table.h
@@ -14,27 +14,25 @@
* limitations under the License.
*/
-#ifndef SRC_TRACE_PROCESSOR_RAW_TABLE_H_
-#define SRC_TRACE_PROCESSOR_RAW_TABLE_H_
+#ifndef SRC_TRACE_PROCESSOR_SQLITE_RAW_TABLE_H_
+#define SRC_TRACE_PROCESSOR_SQLITE_RAW_TABLE_H_
#include "perfetto/base/logging.h"
-#include "src/trace_processor/storage_table.h"
+#include "perfetto/ext/base/string_writer.h"
+#include "src/trace_processor/sqlite/db_sqlite_table.h"
#include "src/trace_processor/trace_storage.h"
+#include "src/trace_processor/types/variadic.h"
namespace perfetto {
namespace trace_processor {
-class RawTable : public StorageTable {
+class SqliteRawTable : public DbSqliteTable {
public:
+ SqliteRawTable(sqlite3*, const TraceStorage*);
+ virtual ~SqliteRawTable();
+
static void RegisterTable(sqlite3* db, const TraceStorage* storage);
- RawTable(sqlite3*, const TraceStorage*);
-
- // Table implementation.
- StorageSchema CreateStorageSchema() override;
- uint32_t RowCount() override;
- int BestIndex(const QueryConstraints&, BestIndexInfo*) override;
-
private:
void FormatSystraceArgs(NullTermStringView event_name,
ArgSetId arg_set_id,
@@ -48,4 +46,4 @@
} // namespace trace_processor
} // namespace perfetto
-#endif // SRC_TRACE_PROCESSOR_RAW_TABLE_H_
+#endif // SRC_TRACE_PROCESSOR_SQLITE_RAW_TABLE_H_
diff --git a/src/trace_processor/stack_profile_tracker.cc b/src/trace_processor/stack_profile_tracker.cc
index e130710..10138f3 100644
--- a/src/trace_processor/stack_profile_tracker.cc
+++ b/src/trace_processor/stack_profile_tracker.cc
@@ -43,14 +43,14 @@
string_map_.emplace(id, str.ToStdString());
}
-base::Optional<int64_t> StackProfileTracker::AddMapping(
+base::Optional<MappingId> StackProfileTracker::AddMapping(
SourceMappingId id,
const SourceMapping& mapping,
const InternLookup* intern_lookup) {
std::string path;
for (SourceStringId str_id : mapping.name_ids) {
- auto opt_str =
- FindString(str_id, intern_lookup, InternedStringType::kMappingPath);
+ auto opt_str = FindOrInsertString(str_id, intern_lookup,
+ InternedStringType::kMappingPath);
if (!opt_str)
break;
path += "/" + *opt_str;
@@ -60,7 +60,7 @@
InternedStringType::kBuildId);
if (!opt_build_id) {
context_->storage->IncrementStats(stats::stackprofile_invalid_string_id);
- PERFETTO_DFATAL("Invalid string.");
+ PERFETTO_DLOG("Invalid string.");
return base::nullopt;
}
const StringId raw_build_id = opt_build_id.value();
@@ -68,9 +68,18 @@
context_->storage->GetString(raw_build_id);
StringId build_id = GetEmptyStringId();
if (raw_build_id_str.size() > 0) {
- std::string hex_build_id =
- base::ToHex(raw_build_id_str.c_str(), raw_build_id_str.size());
- build_id = context_->storage->InternString(base::StringView(hex_build_id));
+ // If the build_id is 33 characters long, we assume it's a Breakpad debug
+ // identifier which is already in Hex and doesn't need conversion.
+ // TODO(b/148109467): Remove workaround once all active Chrome versions
+ // write raw bytes instead of a string as build_id.
+ if (raw_build_id_str.size() == 33) {
+ build_id = raw_build_id;
+ } else {
+ std::string hex_build_id =
+ base::ToHex(raw_build_id_str.c_str(), raw_build_id_str.size());
+ build_id =
+ context_->storage->InternString(base::StringView(hex_build_id));
+ }
}
tables::StackProfileMappingTable::Row row{
@@ -84,42 +93,40 @@
tables::StackProfileMappingTable* mappings =
context_->storage->mutable_stack_profile_mapping_table();
- int64_t cur_row = -1;
+ base::Optional<MappingId> cur_id;
auto it = mapping_idx_.find(row);
if (it != mapping_idx_.end()) {
- cur_row = it->second;
+ cur_id = it->second;
} else {
- std::vector<int64_t> db_mappings =
+ std::vector<MappingId> db_mappings =
context_->storage->FindMappingRow(row.name, row.build_id);
- for (const int64_t preexisting_mapping : db_mappings) {
- PERFETTO_DCHECK(preexisting_mapping >= 0);
- uint32_t preexisting_row_id = static_cast<uint32_t>(preexisting_mapping);
- tables::StackProfileMappingTable::Row preexisting_row{
- mappings->build_id()[preexisting_row_id],
- mappings->exact_offset()[preexisting_row_id],
- mappings->start_offset()[preexisting_row_id],
- mappings->start()[preexisting_row_id],
- mappings->end()[preexisting_row_id],
- mappings->load_bias()[preexisting_row_id],
- mappings->name()[preexisting_row_id]};
+ for (const MappingId preexisting_mapping : db_mappings) {
+ uint32_t preexisting_row = *mappings->id().IndexOf(preexisting_mapping);
+ tables::StackProfileMappingTable::Row preexisting_data{
+ mappings->build_id()[preexisting_row],
+ mappings->exact_offset()[preexisting_row],
+ mappings->start_offset()[preexisting_row],
+ mappings->start()[preexisting_row],
+ mappings->end()[preexisting_row],
+ mappings->load_bias()[preexisting_row],
+ mappings->name()[preexisting_row]};
- if (row == preexisting_row) {
- cur_row = preexisting_mapping;
+ if (row == preexisting_data) {
+ cur_id = preexisting_mapping;
}
}
- if (cur_row == -1) {
+ if (!cur_id) {
MappingId mapping_id = mappings->Insert(row);
- uint32_t mapping_row = *mappings->id().IndexOf(mapping_id);
- context_->storage->InsertMappingRow(row.name, row.build_id, mapping_row);
- cur_row = mapping_row;
+ context_->storage->InsertMappingId(row.name, row.build_id, mapping_id);
+ cur_id = mapping_id;
}
- mapping_idx_.emplace(row, cur_row);
+ mapping_idx_.emplace(row, *cur_id);
}
- mappings_.emplace(id, cur_row);
- return cur_row;
+ mapping_ids_.emplace(id, *cur_id);
+ return cur_id;
}
-base::Optional<int64_t> StackProfileTracker::AddFrame(
+base::Optional<FrameId> StackProfileTracker::AddFrame(
SourceFrameId id,
const SourceFrame& frame,
const InternLookup* intern_lookup) {
@@ -127,106 +134,101 @@
InternedStringType::kFunctionName);
if (!opt_str_id) {
context_->storage->IncrementStats(stats::stackprofile_invalid_string_id);
- PERFETTO_DFATAL("Invalid string.");
+ PERFETTO_DLOG("Invalid string.");
return base::nullopt;
}
const StringId& str_id = opt_str_id.value();
- auto maybe_mapping = FindMapping(frame.mapping_id, intern_lookup);
+ auto maybe_mapping = FindOrInsertMapping(frame.mapping_id, intern_lookup);
if (!maybe_mapping) {
context_->storage->IncrementStats(stats::stackprofile_invalid_mapping_id);
PERFETTO_ELOG("Invalid mapping for frame %" PRIu64, id);
return base::nullopt;
}
- int64_t mapping_row = *maybe_mapping;
+ MappingId mapping_id = *maybe_mapping;
- tables::StackProfileFrameTable::Row row{str_id, mapping_row,
+ tables::StackProfileFrameTable::Row row{str_id, mapping_id.value,
static_cast<int64_t>(frame.rel_pc)};
auto* frames = context_->storage->mutable_stack_profile_frame_table();
- int64_t cur_row = -1;
+ base::Optional<FrameId> cur_id;
auto it = frame_idx_.find(row);
if (it != frame_idx_.end()) {
- cur_row = it->second;
+ cur_id = it->second;
} else {
- std::vector<int64_t> db_frames = context_->storage->FindFrameRow(
- static_cast<size_t>(mapping_row), frame.rel_pc);
- for (const int64_t preexisting_frame : db_frames) {
- PERFETTO_DCHECK(preexisting_frame >= 0);
- uint32_t preexisting_row_id = static_cast<uint32_t>(preexisting_frame);
+ std::vector<FrameId> db_frames =
+ context_->storage->FindFrameIds(mapping_id, frame.rel_pc);
+ for (const FrameId preexisting_frame : db_frames) {
+ uint32_t preexisting_row_id = preexisting_frame.value;
tables::StackProfileFrameTable::Row preexisting_row{
frames->name()[preexisting_row_id],
frames->mapping()[preexisting_row_id],
frames->rel_pc()[preexisting_row_id]};
if (row == preexisting_row) {
- cur_row = preexisting_frame;
+ cur_id = preexisting_frame;
}
}
- if (cur_row == -1) {
- auto new_id = frames->Insert(row);
- cur_row = *frames->id().IndexOf(new_id);
- context_->storage->InsertFrameRow(static_cast<size_t>(row.mapping),
- static_cast<uint64_t>(row.rel_pc),
- static_cast<uint32_t>(cur_row));
+ if (!cur_id) {
+ cur_id = frames->Insert(row);
+ context_->storage->InsertFrameRow(
+ mapping_id, static_cast<uint64_t>(row.rel_pc), *cur_id);
}
- frame_idx_.emplace(row, cur_row);
+ frame_idx_.emplace(row, *cur_id);
}
- frames_.emplace(id, cur_row);
- return cur_row;
+ frame_ids_.emplace(id, *cur_id);
+ return cur_id;
}
-base::Optional<int64_t> StackProfileTracker::AddCallstack(
+base::Optional<CallsiteId> StackProfileTracker::AddCallstack(
SourceCallstackId id,
const SourceCallstack& frame_ids,
const InternLookup* intern_lookup) {
- // TODO(fmayer): This should be NULL.
- int64_t parent_id = -1;
- for (size_t depth = 0; depth < frame_ids.size(); ++depth) {
- std::vector<SourceFrameId> frame_subset = frame_ids;
- frame_subset.resize(depth + 1);
- auto self_it = callstacks_from_frames_.find(frame_subset);
- if (self_it != callstacks_from_frames_.end()) {
- parent_id = self_it->second;
- continue;
- }
+ if (frame_ids.size() == 0)
+ return base::nullopt;
- SourceFrameId frame_id = frame_ids[depth];
- auto maybe_frame_row = FindFrame(frame_id, intern_lookup);
- if (!maybe_frame_row) {
+ // TODO(fmayer): This should be NULL.
+ base::Optional<CallsiteId> parent_id;
+ for (size_t depth = 0; depth < frame_ids.size(); ++depth) {
+ auto maybe_frame_id = FindOrInsertFrame(frame_ids[depth], intern_lookup);
+ if (!maybe_frame_id) {
context_->storage->IncrementStats(stats::stackprofile_invalid_frame_id);
PERFETTO_ELOG("Unknown frame in callstack; ignoring.");
return base::nullopt;
}
- int64_t frame_row = *maybe_frame_row;
+ FrameId frame_id = *maybe_frame_id;
+ // TODO(fmayer): Store roots as having null parent_id instead of -1.
+ int64_t db_parent_id = -1;
+ if (parent_id)
+ db_parent_id = parent_id->value;
tables::StackProfileCallsiteTable::Row row{static_cast<int64_t>(depth),
- parent_id, frame_row};
+ db_parent_id, frame_id.value};
- int64_t self_id;
+ CallsiteId self_id;
auto callsite_it = callsite_idx_.find(row);
if (callsite_it != callsite_idx_.end()) {
self_id = callsite_it->second;
} else {
auto* callsite =
context_->storage->mutable_stack_profile_callsite_table();
- auto callsite_id = callsite->Insert(row);
- self_id = callsite_id.value;
+ self_id = callsite->Insert(row);
callsite_idx_.emplace(row, self_id);
}
parent_id = self_id;
}
- callstacks_.emplace(id, parent_id);
+ PERFETTO_DCHECK(parent_id); // The loop ran at least once.
+ callstack_ids_.emplace(id, *parent_id);
return parent_id;
}
-int64_t StackProfileTracker::GetDatabaseFrameIdForTesting(
+FrameId StackProfileTracker::GetDatabaseFrameIdForTesting(
SourceFrameId frame_id) {
- auto it = frames_.find(frame_id);
- if (it == frames_.end()) {
- PERFETTO_DFATAL("Invalid frame.");
- return -1;
+ auto it = frame_ids_.find(frame_id);
+ if (it == frame_ids_.end()) {
+ PERFETTO_DLOG("Invalid frame.");
+ return {};
}
return it->second;
}
@@ -238,14 +240,14 @@
if (id == 0)
return GetEmptyStringId();
- auto opt_str = FindString(id, intern_lookup, type);
+ auto opt_str = FindOrInsertString(id, intern_lookup, type);
if (!opt_str)
return GetEmptyStringId();
return context_->storage->InternString(base::StringView(*opt_str));
}
-base::Optional<std::string> StackProfileTracker::FindString(
+base::Optional<std::string> StackProfileTracker::FindOrInsertString(
SourceStringId id,
const InternLookup* intern_lookup,
StackProfileTracker::InternedStringType type) {
@@ -259,7 +261,7 @@
if (!str) {
context_->storage->IncrementStats(
stats::stackprofile_invalid_string_id);
- PERFETTO_DFATAL("Invalid string.");
+ PERFETTO_DLOG("Invalid string.");
return base::nullopt;
}
return str->ToStdString();
@@ -270,12 +272,12 @@
return it->second;
}
-base::Optional<int64_t> StackProfileTracker::FindMapping(
+base::Optional<MappingId> StackProfileTracker::FindOrInsertMapping(
SourceMappingId mapping_id,
const InternLookup* intern_lookup) {
- base::Optional<int64_t> res;
- auto it = mappings_.find(mapping_id);
- if (it == mappings_.end()) {
+ base::Optional<MappingId> res;
+ auto it = mapping_ids_.find(mapping_id);
+ if (it == mapping_ids_.end()) {
if (intern_lookup) {
auto interned_mapping = intern_lookup->GetMapping(mapping_id);
if (interned_mapping) {
@@ -285,19 +287,19 @@
}
context_->storage->IncrementStats(stats::stackprofile_invalid_mapping_id);
PERFETTO_ELOG("Unknown mapping %" PRIu64 " : %zu", mapping_id,
- mappings_.size());
+ mapping_ids_.size());
return res;
}
res = it->second;
return res;
}
-base::Optional<int64_t> StackProfileTracker::FindFrame(
+base::Optional<FrameId> StackProfileTracker::FindOrInsertFrame(
SourceFrameId frame_id,
const InternLookup* intern_lookup) {
- base::Optional<int64_t> res;
- auto it = frames_.find(frame_id);
- if (it == frames_.end()) {
+ base::Optional<FrameId> res;
+ auto it = frame_ids_.find(frame_id);
+ if (it == frame_ids_.end()) {
if (intern_lookup) {
auto interned_frame = intern_lookup->GetFrame(frame_id);
if (interned_frame) {
@@ -306,28 +308,28 @@
}
}
context_->storage->IncrementStats(stats::stackprofile_invalid_frame_id);
- PERFETTO_DFATAL("Unknown frame %" PRIu64 " : %zu", frame_id,
- frames_.size());
+ PERFETTO_DLOG("Unknown frame %" PRIu64 " : %zu", frame_id,
+ frame_ids_.size());
return res;
}
res = it->second;
return res;
}
-base::Optional<int64_t> StackProfileTracker::FindCallstack(
+base::Optional<CallsiteId> StackProfileTracker::FindOrInsertCallstack(
SourceCallstackId callstack_id,
const InternLookup* intern_lookup) {
- base::Optional<int64_t> res;
- auto it = callstacks_.find(callstack_id);
- if (it == callstacks_.end()) {
+ base::Optional<CallsiteId> res;
+ auto it = callstack_ids_.find(callstack_id);
+ if (it == callstack_ids_.end()) {
auto interned_callstack = intern_lookup->GetCallstack(callstack_id);
if (interned_callstack) {
res = AddCallstack(callstack_id, *interned_callstack, intern_lookup);
return res;
}
context_->storage->IncrementStats(stats::stackprofile_invalid_callstack_id);
- PERFETTO_DFATAL("Unknown callstack %" PRIu64 " : %zu", callstack_id,
- callstacks_.size());
+ PERFETTO_DLOG("Unknown callstack %" PRIu64 " : %zu", callstack_id,
+ callstack_ids_.size());
return res;
}
res = it->second;
@@ -336,10 +338,9 @@
void StackProfileTracker::ClearIndices() {
string_map_.clear();
- mappings_.clear();
- callstacks_from_frames_.clear();
- callstacks_.clear();
- frames_.clear();
+ mapping_ids_.clear();
+ callstack_ids_.clear();
+ frame_ids_.clear();
}
} // namespace trace_processor
diff --git a/src/trace_processor/stack_profile_tracker.h b/src/trace_processor/stack_profile_tracker.h
index 8c592f5..00357ce 100644
--- a/src/trace_processor/stack_profile_tracker.h
+++ b/src/trace_processor/stack_profile_tracker.h
@@ -18,6 +18,7 @@
#define SRC_TRACE_PROCESSOR_STACK_PROFILE_TRACKER_H_
#include <deque>
+#include <unordered_map>
#include "perfetto/ext/base/optional.h"
@@ -38,6 +39,41 @@
};
template <>
+struct hash<std::pair<uint32_t, perfetto::trace_processor::CallsiteId>> {
+ using argument_type =
+ std::pair<uint32_t, perfetto::trace_processor::CallsiteId>;
+ using result_type = size_t;
+
+ result_type operator()(const argument_type& p) const {
+ return std::hash<uint32_t>{}(p.first) ^
+ std::hash<uint32_t>{}(p.second.value);
+ }
+};
+
+template <>
+struct hash<std::pair<uint32_t, perfetto::trace_processor::MappingId>> {
+ using argument_type =
+ std::pair<uint32_t, perfetto::trace_processor::MappingId>;
+ using result_type = size_t;
+
+ result_type operator()(const argument_type& p) const {
+ return std::hash<uint32_t>{}(p.first) ^
+ std::hash<uint32_t>{}(p.second.value);
+ }
+};
+
+template <>
+struct hash<std::pair<uint32_t, perfetto::trace_processor::FrameId>> {
+ using argument_type = std::pair<uint32_t, perfetto::trace_processor::FrameId>;
+ using result_type = size_t;
+
+ result_type operator()(const argument_type& p) const {
+ return std::hash<uint32_t>{}(p.first) ^
+ std::hash<uint32_t>{}(p.second.value);
+ }
+};
+
+template <>
struct hash<std::vector<uint64_t>> {
using argument_type = std::vector<uint64_t>;
using result_type = size_t;
@@ -118,19 +154,19 @@
~StackProfileTracker();
void AddString(SourceStringId, base::StringView);
- base::Optional<int64_t> AddMapping(
+ base::Optional<MappingId> AddMapping(
SourceMappingId,
const SourceMapping&,
const InternLookup* intern_lookup = nullptr);
- base::Optional<int64_t> AddFrame(SourceFrameId,
+ base::Optional<FrameId> AddFrame(SourceFrameId,
const SourceFrame&,
const InternLookup* intern_lookup = nullptr);
- base::Optional<int64_t> AddCallstack(
+ base::Optional<CallsiteId> AddCallstack(
SourceCallstackId,
const SourceCallstack&,
const InternLookup* intern_lookup = nullptr);
- int64_t GetDatabaseFrameIdForTesting(SourceFrameId);
+ FrameId GetDatabaseFrameIdForTesting(SourceFrameId);
// Gets the row number of string / mapping / frame / callstack previously
// added through AddString / AddMapping/ AddFrame / AddCallstack.
@@ -146,15 +182,19 @@
SourceStringId,
const InternLookup* intern_lookup,
InternedStringType type);
- base::Optional<std::string> FindString(SourceStringId,
- const InternLookup* intern_lookup,
- InternedStringType type);
- base::Optional<int64_t> FindMapping(SourceMappingId,
- const InternLookup* intern_lookup);
- base::Optional<int64_t> FindFrame(SourceFrameId,
- const InternLookup* intern_lookup);
- base::Optional<int64_t> FindCallstack(SourceCallstackId,
- const InternLookup* intern_lookup);
+ base::Optional<std::string> FindOrInsertString(
+ SourceStringId,
+ const InternLookup* intern_lookup,
+ InternedStringType type);
+ base::Optional<MappingId> FindOrInsertMapping(
+ SourceMappingId,
+ const InternLookup* intern_lookup);
+ base::Optional<FrameId> FindOrInsertFrame(SourceFrameId,
+ const InternLookup* intern_lookup);
+
+ base::Optional<CallsiteId> FindOrInsertCallstack(
+ SourceCallstackId,
+ const InternLookup* intern_lookup);
// Clear indices when they're no longer needed.
void ClearIndices();
@@ -163,17 +203,21 @@
StringId GetEmptyStringId();
std::unordered_map<SourceStringId, std::string> string_map_;
- std::unordered_map<SourceMappingId, int64_t> mappings_;
- std::unordered_map<SourceFrameId, int64_t> frames_;
- std::unordered_map<SourceCallstack, int64_t> callstacks_from_frames_;
- std::unordered_map<SourceCallstackId, int64_t> callstacks_;
+
+ // Mapping from ID of mapping / frame / callstack in original trace and the
+ // index in the respective table it was inserted into.
+ std::unordered_map<SourceMappingId, MappingId> mapping_ids_;
+ std::unordered_map<SourceFrameId, FrameId> frame_ids_;
+ std::unordered_map<SourceCallstackId, CallsiteId> callstack_ids_;
// TODO(oysteine): Share these indices between the StackProfileTrackers,
// since they're not sequence-specific.
- std::unordered_map<tables::StackProfileMappingTable::Row, int64_t>
+ //
+ // Mapping from content of database row to the index of the raw.
+ std::unordered_map<tables::StackProfileMappingTable::Row, MappingId>
mapping_idx_;
- std::unordered_map<tables::StackProfileFrameTable::Row, int64_t> frame_idx_;
- std::unordered_map<tables::StackProfileCallsiteTable::Row, int64_t>
+ std::unordered_map<tables::StackProfileFrameTable::Row, FrameId> frame_idx_;
+ std::unordered_map<tables::StackProfileCallsiteTable::Row, CallsiteId>
callsite_idx_;
TraceProcessorContext* const context_;
diff --git a/src/trace_processor/stats.h b/src/trace_processor/stats.h
index 19b35b3..e9d614a 100644
--- a/src/trace_processor/stats.h
+++ b/src/trace_processor/stats.h
@@ -108,6 +108,7 @@
F(vmstat_unknown_keys, kSingle, kError, kAnalysis), \
F(vulkan_allocations_invalid_string_id, kSingle, kError, kTrace), \
F(clock_sync_failure, kSingle, kError, kAnalysis), \
+ F(clock_sync_cache_miss, kSingle, kInfo, kAnalysis), \
F(process_tracker_errors, kSingle, kError, kAnalysis), \
F(json_tokenizer_failure, kSingle, kError, kTrace), \
F(heap_graph_invalid_string_id, kIndexed, kError, kTrace), \
@@ -116,6 +117,8 @@
F(heap_graph_missing_packet, kIndexed, kDataLoss, kTrace), \
F(heapprofd_buffer_corrupted, kIndexed, kError, kTrace), \
F(heapprofd_buffer_overran, kIndexed, kDataLoss, kTrace), \
+ F(heapprofd_client_disconnected, kIndexed, kInfo, kTrace), \
+ F(heapprofd_malformed_packet, kIndexed, kError, kTrace), \
F(heapprofd_missing_packet, kSingle, kError, kTrace), \
F(heapprofd_rejected_concurrent, kIndexed, kError, kTrace), \
F(metatrace_overruns, kSingle, kError, kTrace), \
@@ -150,6 +153,9 @@
kAnalysis
};
+// Ignore GCC warning about a missing argument for a variadic macro parameter.
+#pragma GCC system_header
+
// Declares an enum of literals (one for each stat). The enum values of each
// literal corresponds to the string index in the arrays below.
#define PERFETTO_TP_STATS_ENUM(name, ...) name
diff --git a/src/trace_processor/syscall_tracker.cc b/src/trace_processor/syscall_tracker.cc
index 609284d..5991497 100644
--- a/src/trace_processor/syscall_tracker.cc
+++ b/src/trace_processor/syscall_tracker.cc
@@ -83,7 +83,7 @@
}
for (size_t i = 0; i < kMaxSyscalls; i++) {
- StringId id = 0;
+ StringId id = kNullStringId;
if (i < num_syscalls && syscall_table[i] && *syscall_table[i]) {
const char* name = syscall_table[i];
id = context_->storage->InternString(name);
diff --git a/src/trace_processor/syscall_tracker.h b/src/trace_processor/syscall_tracker.h
index 1dba57d..88d67b4 100644
--- a/src/trace_processor/syscall_tracker.h
+++ b/src/trace_processor/syscall_tracker.h
@@ -58,7 +58,8 @@
StringId name = SyscallNumberToStringId(syscall_num);
if (!name.is_null()) {
TrackId track_id = context_->track_tracker->InternThreadTrack(utid);
- context_->slice_tracker->Begin(ts, track_id, 0 /* cat */, name);
+ context_->slice_tracker->Begin(ts, track_id, kNullStringId /* cat */,
+ name);
}
}
@@ -66,7 +67,7 @@
StringId name = SyscallNumberToStringId(syscall_num);
if (!name.is_null()) {
TrackId track_id = context_->track_tracker->InternThreadTrack(utid);
- context_->slice_tracker->End(ts, track_id, 0 /* cat */, name);
+ context_->slice_tracker->End(ts, track_id, kNullStringId /* cat */, name);
}
}
@@ -77,14 +78,14 @@
inline StringId SyscallNumberToStringId(uint32_t syscall_num) {
if (syscall_num > kMaxSyscalls)
- return 0;
+ return kNullStringId;
// We see two write sys calls around each userspace slice that is going via
// trace_marker, this violates the assumption that userspace slices are
// perfectly nested. For the moment ignore all write sys calls.
// TODO(hjd): Remove this limitation.
StringId id = arch_syscall_to_string_id_[syscall_num];
if (id == sys_write_string_id_)
- return 0;
+ return kNullStringId;
return id;
}
diff --git a/src/trace_processor/syscall_tracker_unittest.cc b/src/trace_processor/syscall_tracker_unittest.cc
index f7a2eef..61124d1 100644
--- a/src/trace_processor/syscall_tracker_unittest.cc
+++ b/src/trace_processor/syscall_tracker_unittest.cc
@@ -64,8 +64,8 @@
TEST_F(SyscallTrackerTest, ReportUnknownSyscalls) {
constexpr TrackId track{0u};
- StringId begin_name = 0;
- StringId end_name = 0;
+ StringId begin_name = kNullStringId;
+ StringId end_name = kNullStringId;
EXPECT_CALL(*slice_tracker, Begin(100, track, kNullStringId, _, _))
.WillOnce(DoAll(SaveArg<3>(&begin_name), Return(base::nullopt)));
EXPECT_CALL(*slice_tracker, End(110, track, kNullStringId, _, _))
@@ -90,8 +90,8 @@
TEST_F(SyscallTrackerTest, Aarch64) {
constexpr TrackId track{0u};
- StringId begin_name = 0;
- StringId end_name = 0;
+ StringId begin_name = kNullStringId;
+ StringId end_name = kNullStringId;
EXPECT_CALL(*slice_tracker, Begin(100, track, kNullStringId, _, _))
.WillOnce(DoAll(SaveArg<3>(&begin_name), Return(base::nullopt)));
EXPECT_CALL(*slice_tracker, End(110, track, kNullStringId, _, _))
@@ -107,8 +107,8 @@
TEST_F(SyscallTrackerTest, x8664) {
constexpr TrackId track{0u};
- StringId begin_name = 0;
- StringId end_name = 0;
+ StringId begin_name = kNullStringId;
+ StringId end_name = kNullStringId;
EXPECT_CALL(*slice_tracker, Begin(100, track, kNullStringId, _, _))
.WillOnce(DoAll(SaveArg<3>(&begin_name), Return(base::nullopt)));
EXPECT_CALL(*slice_tracker, End(110, track, kNullStringId, _, _))
diff --git a/src/trace_processor/tables/BUILD.gn b/src/trace_processor/tables/BUILD.gn
index 268e419..83628fa 100644
--- a/src/trace_processor/tables/BUILD.gn
+++ b/src/trace_processor/tables/BUILD.gn
@@ -33,9 +33,7 @@
source_set("unittests") {
testonly = true
- sources = [
- "macros_unittest.cc",
- ]
+ sources = [ "macros_unittest.cc" ]
deps = [
":tables",
"../../../gn:default_deps",
@@ -51,8 +49,6 @@
"../../../gn:benchmark",
"../../../gn:default_deps",
]
- sources = [
- "macros_benchmark.cc",
- ]
+ sources = [ "macros_benchmark.cc" ]
}
}
diff --git a/src/trace_processor/tables/macros_benchmark.cc b/src/trace_processor/tables/macros_benchmark.cc
index 2e7bfbb..c4ed6e3 100644
--- a/src/trace_processor/tables/macros_benchmark.cc
+++ b/src/trace_processor/tables/macros_benchmark.cc
@@ -27,6 +27,7 @@
PERFETTO_TP_ROOT_TABLE(PARENT, C) \
C(uint32_t, root_sorted, Column::Flag::kSorted) \
C(uint32_t, root_non_null) \
+ C(uint32_t, root_non_null_2) \
C(base::Optional<uint32_t>, root_nullable)
PERFETTO_TP_TABLE(PERFETTO_TP_ROOT_TEST_TABLE);
@@ -200,6 +201,28 @@
}
BENCHMARK(BM_TableFilterRootNonNullEqMatchMany)->Apply(TableFilterArgs);
+static void BM_TableFilterRootMultipleNonNull(benchmark::State& state) {
+ StringPool pool;
+ RootTestTable root(&pool, nullptr);
+
+ uint32_t size = static_cast<uint32_t>(state.range(0));
+ uint32_t partitions = size / 512;
+
+ std::minstd_rand0 rnd_engine;
+ for (uint32_t i = 0; i < size; ++i) {
+ RootTestTable::Row row;
+ row.root_non_null = rnd_engine() % partitions;
+ row.root_non_null_2 = rnd_engine() % partitions;
+ root.Insert(row);
+ }
+
+ for (auto _ : state) {
+ benchmark::DoNotOptimize(root.Filter(
+ {root.root_non_null().lt(4), root.root_non_null_2().lt(10)}));
+ }
+}
+BENCHMARK(BM_TableFilterRootMultipleNonNull)->Apply(TableFilterArgs);
+
static void BM_TableFilterRootNullableEqMatchMany(benchmark::State& state) {
StringPool pool;
RootTestTable root(&pool, nullptr);
@@ -336,6 +359,31 @@
}
BENCHMARK(BM_TableFilterParentSortedEq)->Apply(TableFilterArgs);
+static void BM_TableFilterParentSortedAndOther(benchmark::State& state) {
+ StringPool pool;
+ RootTestTable root(&pool, nullptr);
+
+ uint32_t size = static_cast<uint32_t>(state.range(0));
+
+ for (uint32_t i = 0; i < size; ++i) {
+ // Group the rows into rows of 10. This emulates the behaviour of e.g.
+ // args.
+ RootTestTable::Row row;
+ row.root_sorted = (i / 10) * 10;
+ row.root_non_null = i;
+ root.Insert(row);
+ }
+
+ // We choose to search for the last group as if there is O(n^2), it will
+ // be more easily visible.
+ uint32_t last_group = ((size - 1) / 10) * 10;
+ for (auto _ : state) {
+ benchmark::DoNotOptimize(root.Filter({root.root_sorted().eq(last_group),
+ root.root_non_null().eq(size - 1)}));
+ }
+}
+BENCHMARK(BM_TableFilterParentSortedAndOther)->Apply(TableFilterArgs);
+
static void BM_TableFilterChildSortedEq(benchmark::State& state) {
StringPool pool;
RootTestTable root(&pool, nullptr);
diff --git a/src/trace_processor/tables/macros_internal.h b/src/trace_processor/tables/macros_internal.h
index 37c09f1..1533f91 100644
--- a/src/trace_processor/tables/macros_internal.h
+++ b/src/trace_processor/tables/macros_internal.h
@@ -122,6 +122,9 @@
} // namespace macros_internal
+// Ignore GCC warning about a missing argument for a variadic macro parameter.
+#pragma GCC system_header
+
// Basic helper macros.
#define PERFETTO_TP_NOOP(...)
@@ -191,7 +194,7 @@
// Defines the member variable in the Table.
#define PERFETTO_TP_TABLE_MEMBER(type, name, ...) \
- SparseVector<TypedColumn<type>::StoredType> name##_;
+ SparseVector<TypedColumn<type>::serialized_type> name##_;
// Constructs the column in the Table constructor when flags are specified.
#define PERFETTO_TP_TABLE_CONSTRUCTOR_COLUMN_FLAGS(type, name, flags) \
@@ -261,6 +264,7 @@
explicit constexpr DefinedId(uint32_t v) : value(v) {} \
\
bool operator==(const DefinedId& o) const { return o.value == value; } \
+ bool operator<(const DefinedId& o) const { return value < o.value; } \
\
uint32_t value; \
}; \
@@ -293,7 +297,7 @@
} \
\
bool operator==(const class_name::Row& other) const { \
- return PERFETTO_TP_TABLE_COLUMNS(DEF, PERFETTO_TP_ROW_EQUALS) true; \
+ return PERFETTO_TP_ALL_COLUMNS(DEF, PERFETTO_TP_ROW_EQUALS) true; \
} \
\
/* \
@@ -305,6 +309,12 @@
PERFETTO_TP_TABLE_COLUMNS(DEF, PERFETTO_TP_ROW_DEFINITION) \
}; \
\
+ enum class ColumnIndex : uint32_t { \
+ id, \
+ type, /* Expands to col1, col2, ... */ \
+ PERFETTO_TP_ALL_COLUMNS(DEF, PERFETTO_TP_NAME_COMMA) kNumCols \
+ }; \
+ \
class_name(StringPool* pool, parent_class_name* parent) \
: macros_internal::MacroTable(table_name, pool, parent), \
parent_(parent) { \
@@ -360,12 +370,6 @@
PERFETTO_TP_ALL_COLUMNS(DEF, PERFETTO_TP_TABLE_COL_ACCESSOR) \
\
private: \
- enum class ColumnIndex : uint32_t { \
- id, \
- type, /* Expands to col1, col2, ... */ \
- PERFETTO_TP_ALL_COLUMNS(DEF, PERFETTO_TP_NAME_COMMA) kNumCols \
- }; \
- \
parent_class_name* parent_; \
\
/* \
diff --git a/src/trace_processor/tables/metadata_tables.h b/src/trace_processor/tables/metadata_tables.h
index 9a2095d..dfcb98b 100644
--- a/src/trace_processor/tables/metadata_tables.h
+++ b/src/trace_processor/tables/metadata_tables.h
@@ -23,6 +23,30 @@
namespace trace_processor {
namespace tables {
+#define PERFETTO_TP_RAW_TABLE_DEF(NAME, PARENT, C) \
+ NAME(RawTable, "raw") \
+ PERFETTO_TP_ROOT_TABLE(PARENT, C) \
+ C(int64_t, ts, Column::Flag::kSorted) \
+ C(StringPool::Id, name) \
+ C(uint32_t, cpu) \
+ C(uint32_t, utid) \
+ C(uint32_t, arg_set_id)
+
+PERFETTO_TP_TABLE(PERFETTO_TP_RAW_TABLE_DEF);
+
+#define PERFETTO_TP_ARG_TABLE_DEF(NAME, PARENT, C) \
+ NAME(ArgTable, "args") \
+ PERFETTO_TP_ROOT_TABLE(PARENT, C) \
+ C(uint32_t, arg_set_id, Column::Flag::kSorted) \
+ C(StringPool::Id, flat_key) \
+ C(StringPool::Id, key) \
+ C(base::Optional<int64_t>, int_value) \
+ C(base::Optional<StringPool::Id>, string_value) \
+ C(base::Optional<double>, real_value) \
+ C(StringPool::Id, value_type)
+
+PERFETTO_TP_TABLE(PERFETTO_TP_ARG_TABLE_DEF);
+
#define PERFETTO_TP_METADATA_TABLE_DEF(NAME, PARENT, C) \
NAME(MetadataTable, "metadata") \
PERFETTO_TP_ROOT_TABLE(PARENT, C) \
@@ -33,6 +57,29 @@
PERFETTO_TP_TABLE(PERFETTO_TP_METADATA_TABLE_DEF);
+#define PERFETTO_TP_THREAD_TABLE_DEF(NAME, PARENT, C) \
+ NAME(ThreadTable, "internal_thread") \
+ PERFETTO_TP_ROOT_TABLE(PARENT, C) \
+ C(uint32_t, tid) \
+ C(StringPool::Id, name) \
+ C(base::Optional<int64_t>, start_ts) \
+ C(base::Optional<int64_t>, end_ts) \
+ C(base::Optional<uint32_t>, upid)
+
+PERFETTO_TP_TABLE(PERFETTO_TP_THREAD_TABLE_DEF);
+
+#define PERFETTO_TP_PROCESS_TABLE_DEF(NAME, PARENT, C) \
+ NAME(ProcessTable, "internal_process") \
+ PERFETTO_TP_ROOT_TABLE(PARENT, C) \
+ C(uint32_t, pid) \
+ C(StringPool::Id, name) \
+ C(base::Optional<int64_t>, start_ts) \
+ C(base::Optional<int64_t>, end_ts) \
+ C(base::Optional<uint32_t>, parent_upid) \
+ C(base::Optional<uint32_t>, uid)
+
+PERFETTO_TP_TABLE(PERFETTO_TP_PROCESS_TABLE_DEF);
+
} // namespace tables
} // namespace trace_processor
} // namespace perfetto
diff --git a/src/trace_processor/tables/profiler_tables.h b/src/trace_processor/tables/profiler_tables.h
index c735997..04dae8d 100644
--- a/src/trace_processor/tables/profiler_tables.h
+++ b/src/trace_processor/tables/profiler_tables.h
@@ -85,6 +85,29 @@
PERFETTO_TP_TABLE(PERFETTO_TP_HEAP_PROFILE_ALLOCATION_DEF);
+// This will eventually go away, when we also pre-compute the cumulative
+// sizes for native heap profiles.
+#define PERFETTO_TP_EXPERIMENTAL_FLAMEGRAPH_NODES(NAME, PARENT, C) \
+ NAME(ExperimentalFlamegraphNodesTable, "experimental_flamegraph_nodes") \
+ PERFETTO_TP_ROOT_TABLE(PARENT, C) \
+ C(int64_t, ts, Column::Flag::kSorted) \
+ C(uint32_t, upid) \
+ C(StringPool::Id, profile_type) \
+ C(uint32_t, depth) \
+ C(StringPool::Id, name) \
+ C(StringPool::Id, map_name) \
+ C(int64_t, count) \
+ C(int64_t, cumulative_count) \
+ C(int64_t, size) \
+ C(int64_t, cumulative_size) \
+ C(int64_t, alloc_count) \
+ C(int64_t, cumulative_alloc_count) \
+ C(int64_t, alloc_size) \
+ C(int64_t, cumulative_alloc_size) \
+ C(base::Optional<uint32_t>, parent_id)
+
+PERFETTO_TP_TABLE(PERFETTO_TP_EXPERIMENTAL_FLAMEGRAPH_NODES);
+
#define PERFETTO_TP_HEAP_GRAPH_OBJECT_DEF(NAME, PARENT, C) \
NAME(HeapGraphObjectTable, "heap_graph_object") \
PERFETTO_TP_ROOT_TABLE(PARENT, C) \
@@ -105,7 +128,7 @@
#define PERFETTO_TP_HEAP_GRAPH_REFERENCE_DEF(NAME, PARENT, C) \
NAME(HeapGraphReferenceTable, "heap_graph_reference") \
PERFETTO_TP_ROOT_TABLE(PARENT, C) \
- C(int64_t, reference_set_id) \
+ C(int64_t, reference_set_id, Column::Flag::kSorted) \
C(int64_t, owner_id) \
C(int64_t, owned_id) \
C(StringPool::Id, field_name) \
diff --git a/src/trace_processor/tables/slice_tables.h b/src/trace_processor/tables/slice_tables.h
index 3c34ff6..7d041bb 100644
--- a/src/trace_processor/tables/slice_tables.h
+++ b/src/trace_processor/tables/slice_tables.h
@@ -50,11 +50,15 @@
PERFETTO_TP_TABLE(PERFETTO_TP_INSTANT_TABLE_DEF);
#define PERFETTO_TP_GPU_SLICES_DEF(NAME, PARENT, C) \
- NAME(GpuSliceTable, "internal_gpu_slice") \
- PERFETTO_TP_ROOT_TABLE(PARENT, C) \
- C(uint32_t, slice_id, Column::kSorted) \
+ NAME(GpuSliceTable, "gpu_slice") \
+ PARENT(PERFETTO_TP_SLICE_TABLE_DEF, C) \
C(base::Optional<int64_t>, context_id) \
C(base::Optional<int64_t>, render_target) \
+ C(StringPool::Id, render_target_name) \
+ C(base::Optional<int64_t>, render_pass) \
+ C(StringPool::Id, render_pass_name) \
+ C(base::Optional<int64_t>, command_buffer) \
+ C(StringPool::Id, command_buffer_name) \
C(base::Optional<uint32_t>, frame_id) \
C(base::Optional<uint32_t>, submission_id) \
C(base::Optional<uint32_t>, hw_queue_id)
diff --git a/src/trace_processor/thread_table.cc b/src/trace_processor/thread_table.cc
deleted file mode 100644
index 1ead7c5..0000000
--- a/src/trace_processor/thread_table.cc
+++ /dev/null
@@ -1,171 +0,0 @@
-/*
- * Copyright (C) 2018 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.
- */
-
-#include "src/trace_processor/thread_table.h"
-
-#include "perfetto/base/logging.h"
-#include "src/trace_processor/sqlite/query_constraints.h"
-#include "src/trace_processor/sqlite/sqlite_utils.h"
-
-namespace perfetto {
-namespace trace_processor {
-
-namespace {
-
-using namespace sqlite_utils;
-
-} // namespace
-
-ThreadTable::ThreadTable(sqlite3*, const TraceStorage* storage)
- : storage_(storage) {}
-
-void ThreadTable::RegisterTable(sqlite3* db, const TraceStorage* storage) {
- SqliteTable::Register<ThreadTable>(db, storage, "thread");
-}
-
-util::Status ThreadTable::Init(int, const char* const*, Schema* schema) {
- *schema = Schema(
- {
- SqliteTable::Column(Column::kUtid, "utid", SqlValue::Type::kLong),
- SqliteTable::Column(Column::kUpid, "upid", SqlValue::Type::kLong),
- SqliteTable::Column(Column::kName, "name", SqlValue::Type::kString),
- SqliteTable::Column(Column::kTid, "tid", SqlValue::Type::kLong),
- SqliteTable::Column(Column::kStartTs, "start_ts",
- SqlValue::Type::kLong),
- SqliteTable::Column(Column::kEndTs, "end_ts", SqlValue::Type::kLong),
- },
- {Column::kUtid});
- return util::OkStatus();
-}
-
-std::unique_ptr<SqliteTable::Cursor> ThreadTable::CreateCursor() {
- return std::unique_ptr<SqliteTable::Cursor>(new Cursor(this));
-}
-
-int ThreadTable::BestIndex(const QueryConstraints& qc, BestIndexInfo* info) {
- info->estimated_cost = static_cast<uint32_t>(storage_->thread_count());
-
- // If the query has a constraint on the |utid| field, return a reduced cost
- // because we can do that filter efficiently.
- const auto& constraints = qc.constraints();
- for (const auto& cs : qc.constraints()) {
- if (cs.column == Column::kUtid) {
- info->estimated_cost = IsOpEq(constraints.front().op) ? 1 : 10;
- }
- }
- return SQLITE_OK;
-}
-
-ThreadTable::Cursor::Cursor(ThreadTable* table)
- : SqliteTable::Cursor(table), storage_(table->storage_), table_(table) {}
-
-int ThreadTable::Cursor::Filter(const QueryConstraints& qc,
- sqlite3_value** argv,
- FilterHistory) {
- *this = Cursor(table_);
-
- min_ = 0;
- max_ = static_cast<uint32_t>(storage_->thread_count());
- desc_ = false;
-
- for (size_t j = 0; j < qc.constraints().size(); j++) {
- const auto& cs = qc.constraints()[j];
- if (cs.column == Column::kUtid) {
- UniqueTid constraint_utid =
- static_cast<UniqueTid>(sqlite3_value_int(argv[j]));
- // Filter the range of utids that we are interested in, based on the
- // constraints in the query. Everything between min and max (exclusive)
- // will be returned.
- if (IsOpEq(cs.op)) {
- min_ = constraint_utid;
- max_ = constraint_utid + 1;
- } else if (IsOpGe(cs.op) || IsOpGt(cs.op)) {
- min_ = IsOpGt(cs.op) ? constraint_utid + 1 : constraint_utid;
- } else if (IsOpLe(cs.op) || IsOpLt(cs.op)) {
- max_ = IsOpLt(cs.op) ? constraint_utid : constraint_utid + 1;
- }
- }
- }
-
- for (const auto& ob : qc.order_by()) {
- if (ob.iColumn == Column::kUtid) {
- desc_ = ob.desc;
- }
- }
- index_ = 0;
-
- return SQLITE_OK;
-}
-
-int ThreadTable::Cursor::Column(sqlite3_context* context, int N) {
- uint32_t current = desc_ ? max_ - index_ - 1 : min_ + index_;
- const auto& thread = storage_->GetThread(current);
- switch (N) {
- case Column::kUtid: {
- sqlite3_result_int64(context, current);
- break;
- }
- case Column::kUpid: {
- if (thread.upid.has_value()) {
- sqlite3_result_int64(context, thread.upid.value());
- } else {
- sqlite3_result_null(context);
- }
- break;
- }
- case Column::kName: {
- const auto& name = storage_->GetString(thread.name_id);
- sqlite3_result_text(context, name.c_str(), -1, kSqliteStatic);
- break;
- }
- case Column::kTid: {
- sqlite3_result_int64(context, thread.tid);
- break;
- }
- case Column::kStartTs: {
- if (thread.start_ns != 0) {
- sqlite3_result_int64(context, thread.start_ns);
- } else {
- sqlite3_result_null(context);
- }
- break;
- }
- case Column::kEndTs: {
- if (thread.end_ns != 0) {
- sqlite3_result_int64(context, thread.end_ns);
- } else {
- sqlite3_result_null(context);
- }
- break;
- }
- default: {
- PERFETTO_FATAL("Unknown column %d", N);
- break;
- }
- }
- return SQLITE_OK;
-}
-
-int ThreadTable::Cursor::Next() {
- ++index_;
- return SQLITE_OK;
-}
-
-int ThreadTable::Cursor::Eof() {
- return index_ >= (max_ - min_);
-}
-} // namespace trace_processor
-} // namespace perfetto
diff --git a/src/trace_processor/thread_table.h b/src/trace_processor/thread_table.h
deleted file mode 100644
index 152399f..0000000
--- a/src/trace_processor/thread_table.h
+++ /dev/null
@@ -1,84 +0,0 @@
-/*
- * Copyright (C) 2018 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.
- */
-
-#ifndef SRC_TRACE_PROCESSOR_THREAD_TABLE_H_
-#define SRC_TRACE_PROCESSOR_THREAD_TABLE_H_
-
-#include <limits>
-#include <memory>
-
-#include "src/trace_processor/sqlite/sqlite_table.h"
-#include "src/trace_processor/trace_storage.h"
-
-namespace perfetto {
-namespace trace_processor {
-
-// The implementation of the SQLite table containing each unique process with
-// the metadata for those processes.
-class ThreadTable : public SqliteTable {
- public:
- enum Column {
- kUtid = 0,
- kUpid = 1,
- kName = 2,
- kTid = 3,
- kStartTs = 4,
- kEndTs = 5,
- };
- class Cursor : public SqliteTable::Cursor {
- public:
- Cursor(ThreadTable* table);
-
- // Implementation of Table::Cursor.
- int Filter(const QueryConstraints&,
- sqlite3_value**,
- FilterHistory) override;
- int Next() override;
- int Eof() override;
- int Column(sqlite3_context*, int N) override;
-
- private:
- Cursor(Cursor&) = delete;
- Cursor& operator=(const Cursor&) = delete;
-
- Cursor(Cursor&&) noexcept = default;
- Cursor& operator=(Cursor&&) = default;
-
- UniqueTid min_ = 0;
- UniqueTid max_ = 0;
- uint32_t index_ = 0;
- bool desc_ = false;
-
- const TraceStorage* storage_ = nullptr;
- ThreadTable* table_ = nullptr;
- };
-
- static void RegisterTable(sqlite3* db, const TraceStorage* storage);
-
- ThreadTable(sqlite3*, const TraceStorage*);
-
- // Table implementation.
- util::Status Init(int, const char* const*, SqliteTable::Schema*) override;
- std::unique_ptr<SqliteTable::Cursor> CreateCursor() override;
- int BestIndex(const QueryConstraints&, BestIndexInfo*) override;
-
- private:
- const TraceStorage* const storage_;
-};
-} // namespace trace_processor
-} // namespace perfetto
-
-#endif // SRC_TRACE_PROCESSOR_THREAD_TABLE_H_
diff --git a/src/trace_processor/thread_table_unittest.cc b/src/trace_processor/thread_table_unittest.cc
index 03c6647..fda86e1 100644
--- a/src/trace_processor/thread_table_unittest.cc
+++ b/src/trace_processor/thread_table_unittest.cc
@@ -38,6 +38,7 @@
db_.reset(db);
context_.storage.reset(new TraceStorage());
+ context_.global_args_tracker.reset(new GlobalArgsTracker(&context_));
context_.args_tracker.reset(new ArgsTracker(&context_));
context_.process_tracker.reset(new ProcessTracker(&context_));
context_.event_tracker.reset(new EventTracker(&context_));
diff --git a/src/trace_processor/trace_processor_context.cc b/src/trace_processor/trace_processor_context.cc
index 52ec6de..bb5b6a0 100644
--- a/src/trace_processor/trace_processor_context.cc
+++ b/src/trace_processor/trace_processor_context.cc
@@ -20,6 +20,7 @@
#include "src/trace_processor/chunked_trace_reader.h"
#include "src/trace_processor/clock_tracker.h"
#include "src/trace_processor/event_tracker.h"
+#include "src/trace_processor/global_args_tracker.h"
#include "src/trace_processor/heap_profile_tracker.h"
#include "src/trace_processor/importers/ftrace/ftrace_module.h"
#include "src/trace_processor/importers/json/json_trace_parser.h"
diff --git a/src/trace_processor/trace_processor_context.h b/src/trace_processor/trace_processor_context.h
index 10e6eb4..63e0886 100644
--- a/src/trace_processor/trace_processor_context.h
+++ b/src/trace_processor/trace_processor_context.h
@@ -33,6 +33,7 @@
class ClockTracker;
class EventTracker;
class FtraceModule;
+class GlobalArgsTracker;
class HeapGraphTracker;
class HeapProfileTracker;
class MetadataTracker;
@@ -52,7 +53,6 @@
std::unique_ptr<TraceStorage> storage;
std::unique_ptr<TrackTracker> track_tracker;
- std::unique_ptr<ArgsTracker> args_tracker;
std::unique_ptr<SliceTracker> slice_tracker;
std::unique_ptr<ProcessTracker> process_tracker;
std::unique_ptr<EventTracker> event_tracker;
@@ -63,14 +63,20 @@
std::unique_ptr<HeapProfileTracker> heap_profile_tracker;
std::unique_ptr<MetadataTracker> metadata_tracker;
+ // Keep the global tracker before the args tracker as we access the global
+ // tracker in the destructor of the args tracker.
+ std::unique_ptr<GlobalArgsTracker> global_args_tracker;
+ std::unique_ptr<ArgsTracker> args_tracker;
+
// These fields are stored as pointers to Destructible objects rather than
// their actual type (a subclass of Destructible), as the concrete subclass
// type is only available in the storage_full target. To access these fields,
// use the GetOrCreate() method on their subclass type,
// e.g. SyscallTracker::GetOrCreate(context).
- std::unique_ptr<Destructible> syscall_tracker; // SyscallTracker
- std::unique_ptr<Destructible> sched_tracker; // SchedEventTracker
- std::unique_ptr<Destructible> systrace_parser; // SystraceParser
+ std::unique_ptr<Destructible> syscall_tracker; // SyscallTracker
+ std::unique_ptr<Destructible> sched_tracker; // SchedEventTracker
+ std::unique_ptr<Destructible> systrace_parser; // SystraceParser
+ std::unique_ptr<Destructible> heap_graph_tracker; // HeapGraphTracker
// This will be nullptr in the minimal build (storage_minimal target), and
// a pointer to the instance of SystraceTraceParser class in the full build
diff --git a/src/trace_processor/trace_processor_impl.cc b/src/trace_processor/trace_processor_impl.cc
index c843df7..9f14054 100644
--- a/src/trace_processor/trace_processor_impl.cc
+++ b/src/trace_processor/trace_processor_impl.cc
@@ -23,10 +23,8 @@
#include "perfetto/base/time.h"
#include "perfetto/ext/base/string_splitter.h"
#include "perfetto/ext/base/string_utils.h"
-#include "src/trace_processor/args_table.h"
#include "src/trace_processor/importers/ftrace/sched_event_tracker.h"
-#include "src/trace_processor/process_table.h"
-#include "src/trace_processor/raw_table.h"
+#include "src/trace_processor/metadata_tracker.h"
#include "src/trace_processor/register_additional_modules.h"
#include "src/trace_processor/sched_slice_table.h"
#include "src/trace_processor/span_join_operator_table.h"
@@ -34,8 +32,10 @@
#include "src/trace_processor/sqlite/db_sqlite_table.h"
#include "src/trace_processor/sqlite/sqlite3_str_split.h"
#include "src/trace_processor/sqlite/sqlite_table.h"
+#include "src/trace_processor/sqlite_experimental_flamegraph_table.h"
+#include "src/trace_processor/sqlite_raw_table.h"
#include "src/trace_processor/stats_table.h"
-#include "src/trace_processor/thread_table.h"
+#include "src/trace_processor/types/variadic.h"
#include "src/trace_processor/window_operator_table.h"
#include "src/trace_processor/metrics/metrics.descriptor.h"
@@ -179,18 +179,6 @@
}
sqlite3_exec(db,
- "CREATE VIEW gpu_slice AS "
- "SELECT "
- "* "
- "FROM internal_gpu_slice join internal_slice "
- "ON internal_gpu_slice.slice_id = internal_slice.id;",
- 0, 0, &error);
- if (error) {
- PERFETTO_ELOG("Error initializing: %s", error);
- sqlite3_free(error);
- }
-
- sqlite3_exec(db,
"CREATE VIEW instants AS "
"SELECT "
"*, "
@@ -212,6 +200,30 @@
PERFETTO_ELOG("Error initializing: %s", error);
sqlite3_free(error);
}
+
+ sqlite3_exec(db,
+ "CREATE VIEW thread AS "
+ "SELECT "
+ "id as utid, "
+ "* "
+ "FROM internal_thread;",
+ 0, 0, &error);
+ if (error) {
+ PERFETTO_ELOG("Error initializing: %s", error);
+ sqlite3_free(error);
+ }
+
+ sqlite3_exec(db,
+ "CREATE VIEW process AS "
+ "SELECT "
+ "id as upid, "
+ "* "
+ "FROM internal_process;",
+ 0, 0, &error);
+ if (error) {
+ PERFETTO_ELOG("Error initializing: %s", error);
+ sqlite3_free(error);
+ }
}
#if PERFETTO_BUILDFLAG(PERFETTO_TP_JSON)
@@ -348,13 +360,22 @@
PERFETTO_ELOG("Error initializing RepeatedField");
}
}
+
+void EnsureSqliteInitialized() {
+ // sqlite3_initialize isn't actually thread-safe despite being documented
+ // as such; we need to make sure multiple TraceProcessorImpl instances don't
+ // call it concurrently and only gets called once per process, instead.
+ static bool init_once = [] { return sqlite3_initialize() == SQLITE_OK; }();
+ PERFETTO_CHECK(init_once);
+}
+
} // namespace
TraceProcessorImpl::TraceProcessorImpl(const Config& cfg)
: TraceProcessorStorageImpl(cfg) {
RegisterAdditionalModules(&context_);
sqlite3* db = nullptr;
- PERFETTO_CHECK(sqlite3_initialize() == SQLITE_OK);
+ EnsureSqliteInitialized();
PERFETTO_CHECK(sqlite3_open(":memory:", &db) == SQLITE_OK);
InitializeSqlite(db);
CreateBuiltinTables(db);
@@ -369,18 +390,27 @@
SetupMetrics(this, *db_, &sql_metrics_);
- ArgsTable::RegisterTable(*db_, context_.storage.get());
- ProcessTable::RegisterTable(*db_, context_.storage.get());
- SchedSliceTable::RegisterTable(*db_, context_.storage.get());
- SqlStatsTable::RegisterTable(*db_, context_.storage.get());
- ThreadTable::RegisterTable(*db_, context_.storage.get());
- SpanJoinOperatorTable::RegisterTable(*db_, context_.storage.get());
- WindowOperatorTable::RegisterTable(*db_, context_.storage.get());
- StatsTable::RegisterTable(*db_, context_.storage.get());
- RawTable::RegisterTable(*db_, context_.storage.get());
+ const TraceStorage* storage = context_.storage.get();
+
+ SchedSliceTable::RegisterTable(*db_, storage);
+ SqlStatsTable::RegisterTable(*db_, storage);
+ StatsTable::RegisterTable(*db_, storage);
+
+ // Operator tables.
+ SpanJoinOperatorTable::RegisterTable(*db_, storage);
+ WindowOperatorTable::RegisterTable(*db_, storage);
+
+ // New style tables but with some custom logic.
+ SqliteExperimentalFlamegraphTable::RegisterTable(*db_, &context_);
+ SqliteRawTable::RegisterTable(*db_, context_.storage.get());
// New style db-backed tables.
- const TraceStorage* storage = context_.storage.get();
+ DbSqliteTable::RegisterTable(*db_, &storage->arg_table(),
+ storage->arg_table().table_name());
+ DbSqliteTable::RegisterTable(*db_, &storage->thread_table(),
+ storage->thread_table().table_name());
+ DbSqliteTable::RegisterTable(*db_, &storage->process_table(),
+ storage->process_table().table_name());
DbSqliteTable::RegisterTable(*db_, &storage->slice_table(),
storage->slice_table().table_name());
@@ -483,6 +513,9 @@
TraceProcessorStorageImpl::NotifyEndOfFile();
SchedEventTracker::GetOrCreate(&context_)->FlushPendingEvents();
+ context_.metadata_tracker->SetMetadata(
+ metadata::trace_size_bytes,
+ Variadic::Integer(static_cast<int64_t>(bytes_parsed_)));
BuildBoundsTable(*db_, context_.storage->GetTraceTimestampBoundsNs());
// Create a snapshot of all tables and views created so far. This is so later
@@ -516,7 +549,12 @@
auto it = ExecuteQuery(query);
while (it.Next()) {
}
- PERFETTO_CHECK(it.Status().ok());
+ // Index deletion can legitimately fail. If one creates an index "i" on a
+ // table "t" but issues the deletion in the order (t, i), the DROP index i
+ // will fail with "no such index" because deleting the table "t"
+ // automatically deletes all associated indexes.
+ if (!it.Status().ok() && tn.first != "index")
+ PERFETTO_FATAL("%s -> %s", query.c_str(), it.Status().c_message());
}
return deletion_list.size();
}
diff --git a/src/trace_processor/trace_processor_shell.cc b/src/trace_processor/trace_processor_shell.cc
index 5cc06cb..594e13e 100644
--- a/src/trace_processor/trace_processor_shell.cc
+++ b/src/trace_processor/trace_processor_shell.cc
@@ -36,6 +36,7 @@
#include "perfetto/ext/base/string_splitter.h"
#include "perfetto/trace_processor/read_trace.h"
#include "perfetto/trace_processor/trace_processor.h"
+#include "src/trace_processor/metrics/custom_options.descriptor.h"
#include "src/trace_processor/metrics/metrics.descriptor.h"
#include "src/trace_processor/proto_to_json.h"
@@ -290,15 +291,20 @@
}
};
+// This function returns an indentifier for a metric suitable for use
+// as an SQL table name (i.e. containing no forward or backward slashes).
+std::string BaseName(std::string metric_path) {
+ std::replace(metric_path.begin(), metric_path.end(), '\\', '/');
+ auto slash_idx = metric_path.rfind('/');
+ return slash_idx == std::string::npos ? metric_path
+ : metric_path.substr(slash_idx + 1);
+}
+
util::Status RegisterMetric(const std::string& register_metric) {
std::string sql;
base::ReadFile(register_metric, &sql);
- std::string path = "shell/";
- auto slash_idx = register_metric.rfind('/');
- path += slash_idx == std::string::npos
- ? register_metric
- : register_metric.substr(slash_idx + 1);
+ std::string path = "shell/" + BaseName(register_metric);
return g_tp->RegisterMetric(path, sql);
}
@@ -317,16 +323,12 @@
ErrorPrinter printer;
google::protobuf::io::Tokenizer tokenizer(&stream, &printer);
- auto* proto = desc_set.add_file();
+ auto* file_desc = desc_set.add_file();
google::protobuf::compiler::Parser parser;
- parser.Parse(&tokenizer, proto);
+ parser.Parse(&tokenizer, file_desc);
- auto basename_idx = extend_metrics_proto.rfind('/');
- auto basename = basename_idx == std::string::npos
- ? extend_metrics_proto
- : extend_metrics_proto.substr(basename_idx + 1);
- proto->set_name(basename);
- pool->BuildFile(*proto);
+ file_desc->set_name(BaseName(extend_metrics_proto));
+ pool->BuildFile(*file_desc);
std::vector<uint8_t> metric_proto;
metric_proto.resize(static_cast<size_t>(desc_set.ByteSize()));
@@ -375,7 +377,13 @@
break;
}
case OutputFormat::kJson: {
- auto out = proto_to_json::MessageToJson(*metrics) + "\n";
+ // We need to instantiate field options from dynamic message factory
+ // because otherwise it cannot parse our custom extensions.
+ const google::protobuf::Message* field_options_prototype =
+ factory.GetPrototype(
+ pool.FindMessageTypeByName("google.protobuf.FieldOptions"));
+ auto out = proto_to_json::MessageToJsonWithAnnotations(
+ *metrics, field_options_prototype, 0);
fwrite(out.c_str(), sizeof(char), out.size(), stdout);
break;
}
@@ -654,30 +662,51 @@
#if PERFETTO_BUILDFLAG(PERFETTO_OS_WIN)
void PrintUsage(char** argv) {
- PERFETTO_ELOG(
- "Interactive trace processor shell.\n"
- "Usage: %s [-q query_file] trace_file.pb",
- argv[0]);
+ PERFETTO_ELOG(R"(
+Interactive trace processor shell.
+Usage: %s [OPTIONS] trace_file.pb
+
+Options:
+ -q, --query-file FILE Read and execute an SQL query from a file.
+ If used with --run-metrics, the query is
+ executed after the selected metrics and
+ the metrics output is suppressed.
+ --run-metrics x,y,z Runs a comma separated list of metrics and
+ prints the result as a TraceMetrics proto
+ to stdout. The specified can either be
+ in-built metrics or SQL/proto files of
+ extension metrics.
+ --metrics-output [binary|text|json] Allows the output of --run-metrics to be
+ specified in either proto binary, proto
+ text format or JSON format (default: proto
+ text).)",
+ argv[0]);
}
CommandLineOptions ParseCommandLineOptions(int argc, char** argv) {
CommandLineOptions command_line_options;
- if (argc == 2) {
- command_line_options.trace_file_path = argv[1];
- command_line_options.launch_shell = true;
- } else if (argc == 4) {
- if (strcmp(argv[1], "-q") != 0) {
- PrintUsage(argv);
- exit(1);
- }
- command_line_options.query_file_path = argv[2];
- command_line_options.trace_file_path = argv[3];
- } else {
+ if (argc < 2 || argc % 2 == 1) {
PrintUsage(argv);
exit(1);
}
+ for (int i = 1; i < argc - 1; i += 2) {
+ if (strcmp(argv[i], "-q") == 0 || strcmp(argv[i], "--query-file") == 0) {
+ command_line_options.query_file_path = argv[i + 1];
+ } else if (strcmp(argv[i], "--run-metrics") == 0) {
+ command_line_options.metric_names = argv[i + 1];
+ } else if (strcmp(argv[i], "--metrics-output") == 0) {
+ command_line_options.metric_output = argv[i + 1];
+ } else {
+ PrintUsage(argv);
+ exit(1);
+ }
+ }
+ command_line_options.trace_file_path = argv[argc - 1];
+ command_line_options.launch_shell =
+ command_line_options.metric_names.empty() &&
+ command_line_options.query_file_path.empty();
return command_line_options;
}
@@ -895,6 +924,16 @@
#endif // PERFETTO_BUILDFLAG(PERFETTO_OS_WIN)
+void ExtendPoolWithBinaryDescriptor(google::protobuf::DescriptorPool& pool,
+ const void* data,
+ int size) {
+ google::protobuf::FileDescriptorSet desc_set;
+ desc_set.ParseFromArray(data, size);
+ for (const auto& desc : desc_set.file()) {
+ pool.BuildFile(desc);
+ }
+}
+
int TraceProcessorMain(int argc, char** argv) {
CommandLineOptions options = ParseCommandLineOptions(argc, argv);
@@ -970,13 +1009,14 @@
auto t_run_start = base::GetWallTimeNs();
// Descriptor pool used for printing output as textproto.
- google::protobuf::DescriptorPool pool;
- google::protobuf::FileDescriptorSet root_desc_set;
- root_desc_set.ParseFromArray(kMetricsDescriptor.data(),
- kMetricsDescriptor.size());
- for (const auto& desc : root_desc_set.file()) {
- pool.BuildFile(desc);
- }
+ // Building on top of generated pool so default protos in
+ // google.protobuf.descriptor.proto are available.
+ google::protobuf::DescriptorPool pool(
+ google::protobuf::DescriptorPool::generated_pool());
+ ExtendPoolWithBinaryDescriptor(pool, kMetricsDescriptor.data(),
+ kMetricsDescriptor.size());
+ ExtendPoolWithBinaryDescriptor(pool, kCustomOptionsDescriptor.data(),
+ kCustomOptionsDescriptor.size());
if (!options.metric_extra.empty()) {
util::Status status = RegisterExtraMetrics(options.metric_extra, "");
@@ -1028,11 +1068,7 @@
return 1;
}
- auto slash_idx = no_ext_name.rfind('/');
- std::string basename = slash_idx == std::string::npos
- ? no_ext_name
- : no_ext_name.substr(slash_idx + 1);
- metrics[i] = basename;
+ metrics[i] = BaseName(no_ext_name);
}
OutputFormat format;
diff --git a/src/trace_processor/trace_processor_storage_impl.cc b/src/trace_processor/trace_processor_storage_impl.cc
index 0ad11ee..a8d8dee 100644
--- a/src/trace_processor/trace_processor_storage_impl.cc
+++ b/src/trace_processor/trace_processor_storage_impl.cc
@@ -48,6 +48,7 @@
context_.clock_tracker.reset(new ClockTracker(&context_));
context_.heap_profile_tracker.reset(new HeapProfileTracker(&context_));
context_.metadata_tracker.reset(new MetadataTracker(&context_));
+ context_.global_args_tracker.reset(new GlobalArgsTracker(&context_));
context_.modules.emplace_back(new FtraceModule());
// Ftrace module is special, because it has one extra method for parsing
diff --git a/src/trace_processor/trace_storage.cc b/src/trace_processor/trace_storage.cc
index 4d96c7e..b8d79f4 100644
--- a/src/trace_processor/trace_storage.cc
+++ b/src/trace_processor/trace_storage.cc
@@ -43,7 +43,7 @@
void DbTableMaybeUpdateMinMax(const TypedColumn<int64_t>& column,
int64_t* min_value,
int64_t* max_value) {
- if (column.row_map().size() == 0)
+ if (column.row_map().empty())
return;
SqlValue col_min = *column.Min();
@@ -77,11 +77,19 @@
return map.ref();
}
-TraceStorage::TraceStorage(const Config& config)
- : string_pool_(config.string_pool_block_size_bytes) {
+TraceStorage::TraceStorage(const Config&) {
// Upid/utid 0 is reserved for idle processes/threads.
- unique_processes_.emplace_back(0);
- unique_threads_.emplace_back(0);
+ tables::ThreadTable::Row thread_row;
+ thread_row.tid = 0;
+ thread_table_.Insert(thread_row);
+
+ tables::ProcessTable::Row process_row;
+ process_row.pid = 0;
+ process_table_.Insert(process_row);
+
+ for (uint32_t i = 0; i < variadic_type_ids_.size(); ++i) {
+ variadic_type_ids_[i] = InternString(Variadic::kTypeNames[i]);
+ }
}
TraceStorage::~TraceStorage() {}
@@ -131,15 +139,16 @@
int64_t end_ns = std::numeric_limits<int64_t>::min();
MaybeUpdateMinMax(slices_.start_ns().begin(), slices_.start_ns().end(),
&start_ns, &end_ns);
- MaybeUpdateMinMax(raw_events_.timestamps().begin(),
- raw_events_.timestamps().end(), &start_ns, &end_ns);
+ DbTableMaybeUpdateMinMax(raw_table_.ts(), &start_ns, &end_ns);
DbTableMaybeUpdateMinMax(counter_table_.ts(), &start_ns, &end_ns);
DbTableMaybeUpdateMinMax(slice_table_.ts(), &start_ns, &end_ns);
DbTableMaybeUpdateMinMax(heap_profile_allocation_table_.ts(), &start_ns,
&end_ns);
DbTableMaybeUpdateMinMax(instant_table_.ts(), &start_ns, &end_ns);
DbTableMaybeUpdateMinMax(android_log_table_.ts(), &start_ns, &end_ns);
+ DbTableMaybeUpdateMinMax(heap_graph_object_table_.graph_sample_ts(),
+ &start_ns, &end_ns);
if (start_ns == std::numeric_limits<int64_t>::max()) {
return std::make_pair(0, 0);
diff --git a/src/trace_processor/trace_storage.h b/src/trace_processor/trace_storage.h
index 83a609b..67c6358 100644
--- a/src/trace_processor/trace_storage.h
+++ b/src/trace_processor/trace_storage.h
@@ -42,7 +42,7 @@
#include "src/trace_processor/tables/profiler_tables.h"
#include "src/trace_processor/tables/slice_tables.h"
#include "src/trace_processor/tables/track_tables.h"
-#include "src/trace_processor/variadic.h"
+#include "src/trace_processor/types/variadic.h"
namespace perfetto {
namespace trace_processor {
@@ -58,20 +58,7 @@
// StringId is an offset into |string_pool_|.
using StringId = StringPool::Id;
-static const StringId kNullStringId = StringId(0);
-
-// Identifiers for all the tables in the database.
-enum class TableId : uint8_t {
- kInvalid = 0,
- kCounterValues = 1,
- kRawEvents = 2,
- kInstants = 3,
- kSched = 4,
- kNestableSlices = 5,
- kMetadataTable = 6,
- kTrack = 7,
- kVulkanMemoryAllocation = 8,
-};
+static const StringId kNullStringId = StringId::Null();
using ArgSetId = uint32_t;
static const ArgSetId kInvalidArgSetId = 0;
@@ -86,8 +73,18 @@
using MappingId = tables::StackProfileMappingTable::Id;
+using FrameId = tables::StackProfileFrameTable::Id;
+
+using SymbolId = tables::SymbolTable::Id;
+
+using CallsiteId = tables::StackProfileCallsiteTable::Id;
+
using MetadataId = tables::MetadataTable::Id;
+using RawId = tables::RawTable::Id;
+
+using VulkanAllocId = tables::VulkanMemoryAllocationsTable::Id;
+
// TODO(lalitm): this is a temporary hack while migrating the counters table and
// will be removed when the migration is complete.
static const TrackId kInvalidTrackId =
@@ -116,117 +113,6 @@
virtual ~TraceStorage();
- // Information about a unique process seen in a trace.
- struct Process {
- explicit Process(uint32_t p) : pid(p) {}
- int64_t start_ns = 0;
- int64_t end_ns = 0;
- StringId name_id = 0;
- uint32_t pid = 0;
- base::Optional<UniquePid> parent_upid;
- base::Optional<uint32_t> uid;
- };
-
- // Information about a unique thread seen in a trace.
- struct Thread {
- explicit Thread(uint32_t t) : tid(t) {}
- int64_t start_ns = 0;
- int64_t end_ns = 0;
- StringId name_id = 0;
- base::Optional<UniquePid> upid;
- uint32_t tid = 0;
- };
-
- // Generic key value storage which can be referenced by other tables.
- class Args {
- public:
- struct Arg {
- StringId flat_key = 0;
- StringId key = 0;
- Variadic value = Variadic::Integer(0);
-
- TableId table;
- uint32_t row;
- };
-
- struct ArgHasher {
- uint64_t operator()(const Arg& arg) const noexcept {
- base::Hash hash;
- hash.Update(arg.key);
- // We don't hash arg.flat_key because it's a subsequence of arg.key.
- switch (arg.value.type) {
- case Variadic::Type::kInt:
- hash.Update(arg.value.int_value);
- break;
- case Variadic::Type::kUint:
- hash.Update(arg.value.uint_value);
- break;
- case Variadic::Type::kString:
- hash.Update(arg.value.string_value);
- break;
- case Variadic::Type::kReal:
- hash.Update(arg.value.real_value);
- break;
- case Variadic::Type::kPointer:
- hash.Update(arg.value.pointer_value);
- break;
- case Variadic::Type::kBool:
- hash.Update(arg.value.bool_value);
- break;
- case Variadic::Type::kJson:
- hash.Update(arg.value.json_value);
- break;
- }
- return hash.digest();
- }
- };
-
- const std::deque<ArgSetId>& set_ids() const { return set_ids_; }
- const std::deque<StringId>& flat_keys() const { return flat_keys_; }
- const std::deque<StringId>& keys() const { return keys_; }
- const std::deque<Variadic>& arg_values() const { return arg_values_; }
- uint32_t args_count() const {
- return static_cast<uint32_t>(set_ids_.size());
- }
-
- ArgSetId AddArgSet(const std::vector<Arg>& args,
- uint32_t begin,
- uint32_t end) {
- base::Hash hash;
- for (uint32_t i = begin; i < end; i++) {
- hash.Update(ArgHasher()(args[i]));
- }
-
- ArgSetHash digest = hash.digest();
- auto it = arg_row_for_hash_.find(digest);
- if (it != arg_row_for_hash_.end()) {
- return set_ids_[it->second];
- }
-
- // The +1 ensures that nothing has an id == kInvalidArgSetId == 0.
- ArgSetId id = static_cast<uint32_t>(arg_row_for_hash_.size()) + 1;
- arg_row_for_hash_.emplace(digest, args_count());
- for (uint32_t i = begin; i < end; i++) {
- const auto& arg = args[i];
- set_ids_.emplace_back(id);
- flat_keys_.emplace_back(arg.flat_key);
- keys_.emplace_back(arg.key);
- arg_values_.emplace_back(arg.value);
- }
- return id;
- }
-
- private:
- using ArgSetHash = uint64_t;
-
- std::deque<ArgSetId> set_ids_;
- std::deque<StringId> flat_keys_;
- std::deque<StringId> keys_;
- std::deque<Variadic> arg_values_;
-
- std::unordered_map<ArgSetHash, uint32_t> arg_row_for_hash_;
- };
-
class Slices {
public:
inline size_t AddSlice(uint32_t cpu,
@@ -439,42 +325,6 @@
std::deque<int64_t> times_ended_;
};
- class RawEvents {
- public:
- inline uint32_t AddRawEvent(int64_t timestamp,
- StringId name_id,
- uint32_t cpu,
- UniqueTid utid) {
- timestamps_.emplace_back(timestamp);
- name_ids_.emplace_back(name_id);
- cpus_.emplace_back(cpu);
- utids_.emplace_back(utid);
- arg_set_ids_.emplace_back(kInvalidArgSetId);
- return static_cast<uint32_t>(raw_event_count() - 1);
- }
-
- void set_arg_set_id(uint32_t row, ArgSetId id) { arg_set_ids_[row] = id; }
-
- size_t raw_event_count() const { return timestamps_.size(); }
-
- const std::deque<int64_t>& timestamps() const { return timestamps_; }
-
- const std::deque<StringId>& name_ids() const { return name_ids_; }
-
- const std::deque<uint32_t>& cpus() const { return cpus_; }
-
- const std::deque<UniqueTid>& utids() const { return utids_; }
-
- const std::deque<ArgSetId>& arg_set_ids() const { return arg_set_ids_; }
-
- private:
- std::deque<int64_t> timestamps_;
- std::deque<StringId> name_ids_;
- std::deque<uint32_t> cpus_;
- std::deque<UniqueTid> utids_;
- std::deque<ArgSetId> arg_set_ids_;
- };
-
struct Stats {
using IndexMap = std::map<int, int64_t>;
int64_t value = 0;
@@ -482,16 +332,6 @@
};
using StatsMap = std::array<Stats, stats::kNumKeys>;
- UniqueTid AddEmptyThread(uint32_t tid) {
- unique_threads_.emplace_back(tid);
- return static_cast<UniqueTid>(unique_threads_.size() - 1);
- }
-
- UniquePid AddEmptyProcess(uint32_t pid) {
- unique_processes_.emplace_back(pid);
- return static_cast<UniquePid>(unique_processes_.size() - 1);
- }
-
// Return an unqiue identifier for the contents of each string.
// The string is copied internally and can be destroyed after this called.
// Virtual for testing.
@@ -499,16 +339,6 @@
return string_pool_.InternString(str);
}
- Process* GetMutableProcess(UniquePid upid) {
- PERFETTO_DCHECK(upid < unique_processes_.size());
- return &unique_processes_[upid];
- }
-
- Thread* GetMutableThread(UniqueTid utid) {
- PERFETTO_DCHECK(utid < unique_threads_.size());
- return &unique_threads_[utid];
- }
-
// Example usage: SetStats(stats::android_log_num_failed, 42);
void SetStats(size_t key, int64_t value) {
PERFETTO_DCHECK(key < stats::kNumKeys);
@@ -582,17 +412,11 @@
return string_pool_.Get(id);
}
- const Process& GetProcess(UniquePid upid) const {
- PERFETTO_DCHECK(upid < unique_processes_.size());
- return unique_processes_[upid];
- }
+ const tables::ThreadTable& thread_table() const { return thread_table_; }
+ tables::ThreadTable* mutable_thread_table() { return &thread_table_; }
- // Virtual for testing.
- virtual const Thread& GetThread(UniqueTid utid) const {
- // Allow utid == 0 for idle thread retrieval.
- PERFETTO_DCHECK(utid < unique_threads_.size());
- return unique_threads_[utid];
- }
+ const tables::ProcessTable& process_table() const { return process_table_; }
+ tables::ProcessTable* mutable_process_table() { return &process_table_; }
const tables::TrackTable& track_table() const { return track_table_; }
tables::TrackTable* mutable_track_table() { return &track_table_; }
@@ -704,11 +528,11 @@
}
tables::MetadataTable* mutable_metadata_table() { return &metadata_table_; }
- const Args& args() const { return args_; }
- Args* mutable_args() { return &args_; }
+ const tables::ArgTable& arg_table() const { return arg_table_; }
+ tables::ArgTable* mutable_arg_table() { return &arg_table_; }
- const RawEvents& raw_events() const { return raw_events_; }
- RawEvents* mutable_raw_events() { return &raw_events_; }
+ const tables::RawTable& raw_table() const { return raw_table_; }
+ tables::RawTable* mutable_raw_table() { return &raw_table_; }
const tables::StackProfileMappingTable& stack_profile_mapping_table() const {
return stack_profile_mapping_table_;
@@ -739,6 +563,7 @@
tables::HeapProfileAllocationTable* mutable_heap_profile_allocation_table() {
return &heap_profile_allocation_table_;
}
+
const tables::CpuProfileStackSampleTable& cpu_profile_stack_sample_table()
const {
return cpu_profile_stack_sample_table_;
@@ -783,14 +608,7 @@
}
const StringPool& string_pool() const { return string_pool_; }
-
- // |unique_processes_| always contains at least 1 element because the 0th ID
- // is reserved to indicate an invalid process.
- size_t process_count() const { return unique_processes_.size(); }
-
- // |unique_threads_| always contains at least 1 element because the 0th ID
- // is reserved to indicate an invalid thread.
- size_t thread_count() const { return unique_threads_.size(); }
+ StringPool* mutable_string_pool() { return &string_pool_; }
// Number of interned strings in the pool. Includes the empty string w/ ID=0.
size_t string_count() const { return string_pool_.size(); }
@@ -800,7 +618,8 @@
std::pair<int64_t, int64_t> GetTraceTimestampBoundsNs() const;
// TODO(lalitm): remove this when we have a better home.
- std::vector<int64_t> FindMappingRow(StringId name, StringId build_id) const {
+ std::vector<MappingId> FindMappingRow(StringId name,
+ StringId build_id) const {
auto it = stack_profile_mapping_index_.find(std::make_pair(name, build_id));
if (it == stack_profile_mapping_index_.end())
return {};
@@ -808,13 +627,14 @@
}
// TODO(lalitm): remove this when we have a better home.
- void InsertMappingRow(StringId name, StringId build_id, uint32_t row) {
+ void InsertMappingId(StringId name, StringId build_id, MappingId row) {
auto pair = std::make_pair(name, build_id);
stack_profile_mapping_index_[pair].emplace_back(row);
}
// TODO(lalitm): remove this when we have a better home.
- std::vector<int64_t> FindFrameRow(size_t mapping_row, uint64_t rel_pc) const {
+ std::vector<FrameId> FindFrameIds(MappingId mapping_row,
+ uint64_t rel_pc) const {
auto it =
stack_profile_frame_index_.find(std::make_pair(mapping_row, rel_pc));
if (it == stack_profile_frame_index_.end())
@@ -823,11 +643,48 @@
}
// TODO(lalitm): remove this when we have a better home.
- void InsertFrameRow(size_t mapping_row, uint64_t rel_pc, uint32_t row) {
+ void InsertFrameRow(MappingId mapping_row, uint64_t rel_pc, FrameId row) {
auto pair = std::make_pair(mapping_row, rel_pc);
stack_profile_frame_index_[pair].emplace_back(row);
}
+ Variadic GetArgValue(uint32_t row) const {
+ Variadic v;
+ v.type = *GetVariadicTypeForId(arg_table_.value_type()[row]);
+
+ // Force initialization of union to stop GCC complaining.
+ v.int_value = 0;
+
+ switch (v.type) {
+ case Variadic::Type::kBool:
+ v.bool_value = static_cast<bool>(*arg_table_.int_value()[row]);
+ break;
+ case Variadic::Type::kInt:
+ v.int_value = *arg_table_.int_value()[row];
+ break;
+ case Variadic::Type::kUint:
+ v.uint_value = static_cast<uint64_t>(*arg_table_.int_value()[row]);
+ break;
+ case Variadic::Type::kString:
+ v.string_value = arg_table_.string_value()[row];
+ break;
+ case Variadic::Type::kPointer:
+ v.pointer_value = static_cast<uint64_t>(*arg_table_.int_value()[row]);
+ break;
+ case Variadic::Type::kReal:
+ v.real_value = *arg_table_.real_value()[row];
+ break;
+ case Variadic::Type::kJson:
+ v.json_value = arg_table_.string_value()[row];
+ break;
+ }
+ return v;
+ }
+
+ StringId GetIdForVariadicType(Variadic::Type type) const {
+ return variadic_type_ids_[type];
+ }
+
private:
using StringHash = uint64_t;
@@ -837,13 +694,23 @@
TraceStorage(TraceStorage&&) = delete;
TraceStorage& operator=(TraceStorage&&) = delete;
- // TODO(lalitm): remove this when we find a better home for this.
- using MappingKey = std::pair<StringId /* name */, StringId /* build id */>;
- std::map<MappingKey, std::vector<int64_t>> stack_profile_mapping_index_;
+ base::Optional<Variadic::Type> GetVariadicTypeForId(StringId id) const {
+ auto it =
+ std::find(variadic_type_ids_.begin(), variadic_type_ids_.end(), id);
+ if (it == variadic_type_ids_.end())
+ return base::nullopt;
+
+ int64_t idx = std::distance(variadic_type_ids_.begin(), it);
+ return static_cast<Variadic::Type>(idx);
+ }
// TODO(lalitm): remove this when we find a better home for this.
- using FrameKey = std::pair<size_t /* mapping row */, uint64_t /* rel_pc */>;
- std::map<MappingKey, std::vector<int64_t>> stack_profile_frame_index_;
+ using MappingKey = std::pair<StringId /* name */, StringId /* build id */>;
+ std::map<MappingKey, std::vector<MappingId>> stack_profile_mapping_index_;
+
+ // TODO(lalitm): remove this when we find a better home for this.
+ using FrameKey = std::pair<MappingId, uint64_t /* rel_pc */>;
+ std::map<FrameKey, std::vector<FrameId>> stack_profile_frame_index_;
// One entry for each unique string in the trace.
StringPool string_pool_;
@@ -881,15 +748,11 @@
Slices slices_;
// Args for all other tables.
- Args args_;
+ tables::ArgTable arg_table_{&string_pool_, nullptr};
- // One entry for each UniquePid, with UniquePid as the index.
- // Never hold on to pointers to Process, as vector resize will
- // invalidate them.
- std::vector<Process> unique_processes_;
-
- // One entry for each UniqueTid, with UniqueTid as the index.
- std::deque<Thread> unique_threads_;
+ // Information about all the threads and processes in the trace.
+ tables::ThreadTable thread_table_{&string_pool_, nullptr};
+ tables::ProcessTable process_table_{&string_pool_, nullptr};
// Slices coming from userspace events (e.g. Chromium TRACE_EVENT macros).
tables::SliceTable slice_table_{&string_pool_, nullptr};
@@ -903,7 +766,7 @@
// Additional attributes for gpu track slices (sub-type of
// NestableSlices).
- tables::GpuSliceTable gpu_slice_table_{&string_pool_, nullptr};
+ tables::GpuSliceTable gpu_slice_table_{&string_pool_, &slice_table_};
// The values from the Counter events from the trace. This includes CPU
// frequency events as well systrace trace_marker counter events.
@@ -920,7 +783,7 @@
// the timestamp and the pid. The args for the raw event will be in the
// args table. This table can be used to generate a text version of the
// trace.
- RawEvents raw_events_;
+ tables::RawTable raw_table_{&string_pool_, nullptr};
tables::AndroidLogTable android_log_table_{&string_pool_, nullptr};
tables::StackProfileMappingTable stack_profile_mapping_table_{&string_pool_,
@@ -942,6 +805,10 @@
tables::VulkanMemoryAllocationsTable vulkan_memory_allocations_table_{
&string_pool_, nullptr};
+
+ // The below array allow us to map between enums and their string
+ // representations.
+ std::array<StringId, Variadic::kMaxType + 1> variadic_type_ids_;
};
} // namespace trace_processor
diff --git a/src/trace_processor/track_tracker.cc b/src/trace_processor/track_tracker.cc
index 944e674..0ff0bd3 100644
--- a/src/trace_processor/track_tracker.cc
+++ b/src/trace_processor/track_tracker.cc
@@ -17,6 +17,7 @@
#include "src/trace_processor/track_tracker.h"
#include "src/trace_processor/args_tracker.h"
+#include "src/trace_processor/process_tracker.h"
namespace perfetto {
namespace trace_processor {
@@ -30,6 +31,7 @@
source_id_is_process_scoped_key_(
context->storage->InternString("source_id_is_process_scoped")),
source_scope_key_(context->storage->InternString("source_scope")),
+ parent_track_id_key_(context->storage->InternString("parent_track_id")),
fuchsia_source_(context->storage->InternString("fuchsia")),
chrome_source_(context->storage->InternString("chrome")),
android_source_(context->storage->InternString("android")),
@@ -50,6 +52,18 @@
return id;
}
+TrackId TrackTracker::InternProcessTrack(UniquePid upid) {
+ auto it = process_tracks_.find(upid);
+ if (it != process_tracks_.end())
+ return it->second;
+
+ tables::ProcessTrackTable::Row row;
+ row.upid = upid;
+ auto id = context_->storage->mutable_process_track_table()->Insert(row);
+ process_tracks_[upid] = id;
+ return id;
+}
+
TrackId TrackTracker::InternFuchsiaAsyncTrack(StringId name,
int64_t correlation_id) {
auto it = fuchsia_async_tracks_.find(correlation_id);
@@ -60,15 +74,15 @@
auto id = context_->storage->mutable_track_table()->Insert(row);
fuchsia_async_tracks_[correlation_id] = id;
- ArgsTracker::BoundInserter inserter(context_->args_tracker.get(),
- TableId::kTrack, id.value);
- inserter.AddArg(source_key_, Variadic::String(fuchsia_source_));
- inserter.AddArg(source_id_key_, Variadic::Integer(correlation_id));
+ context_->args_tracker->AddArgsTo(id)
+ .AddArg(source_key_, Variadic::String(fuchsia_source_))
+ .AddArg(source_id_key_, Variadic::Integer(correlation_id));
+
return id;
}
TrackId TrackTracker::InternGpuTrack(const tables::GpuTrackTable::Row& row) {
- GpuTrackTuple tuple{row.name.id, row.scope, row.context_id.value_or(0)};
+ GpuTrackTuple tuple{row.name, row.scope, row.context_id.value_or(0)};
auto it = gpu_tracks_.find(tuple);
if (it != gpu_tracks_.end())
@@ -102,13 +116,13 @@
TrackId id = context_->storage->mutable_process_track_table()->Insert(track);
chrome_tracks_[tuple] = id;
- ArgsTracker::BoundInserter inserter(context_->args_tracker.get(),
- TableId::kTrack, id.value);
- inserter.AddArg(source_key_, Variadic::String(chrome_source_));
- inserter.AddArg(source_id_key_, Variadic::Integer(source_id));
- inserter.AddArg(source_id_is_process_scoped_key_,
- Variadic::Boolean(source_id_is_process_scoped));
- inserter.AddArg(source_scope_key_, Variadic::String(source_scope));
+ context_->args_tracker->AddArgsTo(id)
+ .AddArg(source_key_, Variadic::String(chrome_source_))
+ .AddArg(source_id_key_, Variadic::Integer(source_id))
+ .AddArg(source_id_is_process_scoped_key_,
+ Variadic::Boolean(source_id_is_process_scoped))
+ .AddArg(source_scope_key_, Variadic::String(source_scope));
+
return id;
}
@@ -126,10 +140,10 @@
auto id = context_->storage->mutable_process_track_table()->Insert(row);
android_async_tracks_[tuple] = id;
- ArgsTracker::BoundInserter inserter(context_->args_tracker.get(),
- TableId::kTrack, id.value);
- inserter.AddArg(source_key_, Variadic::String(android_source_));
- inserter.AddArg(source_id_key_, Variadic::Integer(cookie));
+ context_->args_tracker->AddArgsTo(id)
+ .AddArg(source_key_, Variadic::String(android_source_))
+ .AddArg(source_id_key_, Variadic::Integer(cookie));
+
return id;
}
@@ -143,8 +157,9 @@
auto id = context_->storage->mutable_process_track_table()->Insert(row);
chrome_process_instant_tracks_[upid] = id;
- context_->args_tracker->AddArg(TableId::kTrack, id.value, source_key_,
- source_key_, Variadic::String(chrome_source_));
+ context_->args_tracker->AddArgsTo(id).AddArg(
+ source_key_, Variadic::String(chrome_source_));
+
return id;
}
@@ -153,157 +168,236 @@
chrome_global_instant_track_id_ =
context_->storage->mutable_track_table()->Insert({});
- context_->args_tracker->AddArg(
- TableId::kTrack, chrome_global_instant_track_id_->value, source_key_,
- source_key_, Variadic::String(chrome_source_));
+ context_->args_tracker->AddArgsTo(*chrome_global_instant_track_id_)
+ .AddArg(source_key_, Variadic::String(chrome_source_));
}
return *chrome_global_instant_track_id_;
}
-TrackId TrackTracker::UpdateDescriptorTrack(uint64_t uuid,
- StringId name,
- base::Optional<UniquePid> upid,
- base::Optional<UniqueTid> utid) {
- auto it = descriptor_tracks_.find(uuid);
- if (it != descriptor_tracks_.end()) {
- // Update existing track for |uuid|.
- TrackId track_id = it->second;
- if (name != kNullStringId) {
- auto* track = context_->storage->mutable_track_table();
- auto row = *track->id().IndexOf(track_id);
- track->mutable_name()->Set(row, name);
- }
+void TrackTracker::ReserveDescriptorProcessTrack(uint64_t uuid,
+ uint32_t pid,
+ int64_t timestamp) {
+ DescriptorTrackReservation reservation;
+ reservation.min_timestamp = timestamp;
+ reservation.pid = pid;
-#if PERFETTO_DLOG_IS_ON()
- if (upid) {
- // Verify that upid didn't change.
- auto process_track_row =
- context_->storage->process_track_table().id().IndexOf(track_id);
- if (!process_track_row) {
- PERFETTO_DLOG("Can't update non-scoped track with uuid %" PRIu64
- " to a scoped track.",
- uuid);
- } else {
- auto old_upid =
- context_->storage->process_track_table().upid()[*process_track_row];
- if (old_upid != upid) {
- PERFETTO_DLOG("Ignoring upid change for track with uuid %" PRIu64
- " from %" PRIu32 " to %" PRIu32 ".",
- uuid, old_upid, *upid);
- }
- }
- }
+ std::map<uint64_t, DescriptorTrackReservation>::iterator it;
+ bool inserted;
+ std::tie(it, inserted) =
+ reserved_descriptor_tracks_.insert(std::make_pair<>(uuid, reservation));
- if (utid) {
- // Verify that utid didn't change.
- auto thread_track_row =
- context_->storage->thread_track_table().id().IndexOf(track_id);
- if (!thread_track_row) {
- PERFETTO_DLOG("Can't update non-thread track with uuid %" PRIu64
- " to a thread track.",
- uuid);
- } else {
- auto old_utid =
- context_->storage->thread_track_table().utid()[*thread_track_row];
- if (old_utid != utid) {
- PERFETTO_DLOG("Ignoring utid change for track with uuid %" PRIu64
- " from %" PRIu32 " to %" PRIu32 ".",
- uuid, old_utid, *utid);
- }
- }
- }
-#endif // PERFETTO_DLOG_IS_ON()
+ if (inserted)
+ return;
- return track_id;
+ if (!it->second.IsForSameTrack(reservation)) {
+ // Process tracks should not be reassigned to a different pid later (neither
+ // should the type of the track change).
+ PERFETTO_DLOG("New track reservation for process track with uuid %" PRIu64
+ " doesn't match earlier one",
+ uuid);
+ context_->storage->IncrementStats(stats::track_event_tokenizer_errors);
+ return;
}
- TrackId track_id;
-
- if (utid) {
- // Update existing track for the thread if we have previously created one
- // in GetOrCreateDescriptorTrackForThread().
- auto utid_it = descriptor_tracks_by_utid_.find(*utid);
- if (utid_it != descriptor_tracks_by_utid_.end()) {
- TrackId candidate_track_id = utid_it->second;
- // Only update this track if it hasn't been associated with a different
- // UUID already.
- auto descriptor_it = std::find_if(
- descriptor_tracks_.begin(), descriptor_tracks_.end(),
- [candidate_track_id](const std::pair<uint64_t, TrackId>& entry) {
- return entry.second == candidate_track_id;
- });
- if (descriptor_it == descriptor_tracks_.end()) {
- descriptor_tracks_[uuid] = candidate_track_id;
- context_->args_tracker->AddArg(
- TableId::kTrack, candidate_track_id.value, source_id_key_,
- source_id_key_, Variadic::Integer(static_cast<int64_t>(uuid)));
-
- return candidate_track_id;
- }
- }
-
- // New thread track.
- tables::ThreadTrackTable::Row row(name);
- row.utid = *utid;
- track_id = context_->storage->mutable_thread_track_table()->Insert(row);
- if (descriptor_tracks_by_utid_.find(*utid) ==
- descriptor_tracks_by_utid_.end()) {
- descriptor_tracks_by_utid_[*utid] = track_id;
- }
- } else if (upid) {
- // New process-scoped async track.
- tables::ProcessTrackTable::Row track(name);
- track.upid = *upid;
- track_id = context_->storage->mutable_process_track_table()->Insert(track);
- } else {
- // New global async track.
- tables::TrackTable::Row track(name);
- track_id = context_->storage->mutable_track_table()->Insert(track);
- }
-
- descriptor_tracks_[uuid] = track_id;
-
- ArgsTracker::BoundInserter inserter(context_->args_tracker.get(),
- TableId::kTrack, track_id.value);
- inserter.AddArg(source_key_, Variadic::String(descriptor_source_));
- inserter.AddArg(source_id_key_,
- Variadic::Integer(static_cast<int64_t>(uuid)));
- return track_id;
+ it->second.min_timestamp = std::min(it->second.min_timestamp, timestamp);
}
-base::Optional<TrackId> TrackTracker::GetDescriptorTrack(uint64_t uuid) const {
- auto it = descriptor_tracks_.find(uuid);
- if (it == descriptor_tracks_.end())
- return base::nullopt;
+void TrackTracker::ReserveDescriptorThreadTrack(uint64_t uuid,
+ uint64_t parent_uuid,
+ uint32_t pid,
+ uint32_t tid,
+ int64_t timestamp) {
+ DescriptorTrackReservation reservation;
+ reservation.min_timestamp = timestamp;
+ reservation.parent_uuid = parent_uuid;
+ reservation.pid = pid;
+ reservation.tid = tid;
+
+ std::map<uint64_t, DescriptorTrackReservation>::iterator it;
+ bool inserted;
+ std::tie(it, inserted) =
+ reserved_descriptor_tracks_.insert(std::make_pair<>(uuid, reservation));
+
+ if (inserted)
+ return;
+
+ if (!it->second.IsForSameTrack(reservation)) {
+ // Thread tracks should not be reassigned to a different pid/tid later
+ // (neither should the type of the track change).
+ PERFETTO_DLOG("New track reservation for thread track with uuid %" PRIu64
+ " doesn't match earlier one",
+ uuid);
+ context_->storage->IncrementStats(stats::track_event_tokenizer_errors);
+ return;
+ }
+
+ it->second.min_timestamp = std::min(it->second.min_timestamp, timestamp);
+}
+
+void TrackTracker::ReserveDescriptorChildTrack(uint64_t uuid,
+ uint64_t parent_uuid) {
+ DescriptorTrackReservation reservation;
+ reservation.parent_uuid = parent_uuid;
+
+ std::map<uint64_t, DescriptorTrackReservation>::iterator it;
+ bool inserted;
+ std::tie(it, inserted) =
+ reserved_descriptor_tracks_.insert(std::make_pair<>(uuid, reservation));
+
+ if (inserted || it->second.IsForSameTrack(reservation))
+ return;
+
+ // Child tracks should not be reassigned to a different parent track later
+ // (neither should the type of the track change).
+ PERFETTO_DLOG("New track reservation for child track with uuid %" PRIu64
+ " doesn't match earlier one",
+ uuid);
+ context_->storage->IncrementStats(stats::track_event_tokenizer_errors);
+}
+
+base::Optional<TrackId> TrackTracker::GetDescriptorTrack(uint64_t uuid) {
+ auto it = resolved_descriptor_tracks_.find(uuid);
+ if (it == resolved_descriptor_tracks_.end()) {
+ auto reservation_it = reserved_descriptor_tracks_.find(uuid);
+ if (reservation_it == reserved_descriptor_tracks_.end())
+ return base::nullopt;
+ TrackId track_id = ResolveDescriptorTrack(uuid, reservation_it->second);
+ resolved_descriptor_tracks_[uuid] = track_id;
+ return track_id;
+ }
return it->second;
}
-TrackId TrackTracker::GetOrCreateDescriptorTrackForThread(UniqueTid utid) {
- auto it = descriptor_tracks_by_utid_.find(utid);
- if (it != descriptor_tracks_by_utid_.end()) {
- return it->second;
+TrackId TrackTracker::ResolveDescriptorTrack(
+ uint64_t uuid,
+ const DescriptorTrackReservation& reservation) {
+ base::Optional<TrackId> parent_track_id;
+ if (reservation.parent_uuid) {
+ // Ensure that parent track is resolved.
+ parent_track_id = GetDescriptorTrack(reservation.parent_uuid);
+ if (!parent_track_id) {
+ PERFETTO_ELOG("Unknown parent track %" PRIu64 " for track %" PRIu64,
+ reservation.parent_uuid, uuid);
+ }
}
- // TODO(eseckler): How should this track receive its name?
- tables::ThreadTrackTable::Row row(/*name=*/kNullStringId);
- row.utid = utid;
- TrackId track_id =
- context_->storage->mutable_thread_track_table()->Insert(row);
- descriptor_tracks_by_utid_[utid] = track_id;
- context_->args_tracker->AddArg(TableId::kTrack, track_id.value, source_key_,
- source_key_,
- Variadic::String(descriptor_source_));
- return track_id;
+ if (reservation.tid) {
+ UniqueTid utid = context_->process_tracker->UpdateThread(*reservation.tid,
+ *reservation.pid);
+ auto it_and_inserted =
+ descriptor_uuids_by_utid_.insert(std::make_pair<>(utid, uuid));
+ if (!it_and_inserted.second) {
+ // We already saw a another track with a different uuid for this thread.
+ // Since there should only be one descriptor track for each thread, we
+ // assume that its tid was reused. So, start a new thread.
+ uint64_t old_uuid = it_and_inserted.first->second;
+ PERFETTO_DCHECK(old_uuid != uuid); // Every track is only resolved once.
+
+ PERFETTO_DLOG("Detected tid reuse (pid: %" PRIu32 " tid: %" PRIu32
+ ") from track descriptors (old uuid: %" PRIu64
+ " new uuid: %" PRIu64 " timestamp: %" PRId64 ")",
+ *reservation.pid, *reservation.tid, old_uuid, uuid,
+ reservation.min_timestamp);
+
+ utid = context_->process_tracker->StartNewThread(
+ base::nullopt, *reservation.tid, kNullStringId);
+
+ // Associate the new thread with its process.
+ PERFETTO_CHECK(context_->process_tracker->UpdateThread(
+ *reservation.tid, *reservation.pid) == utid);
+
+ descriptor_uuids_by_utid_[utid] = uuid;
+ }
+ return InternThreadTrack(utid);
+ }
+
+ if (reservation.pid) {
+ UniquePid upid =
+ context_->process_tracker->GetOrCreateProcess(*reservation.pid);
+ auto it_and_inserted =
+ descriptor_uuids_by_upid_.insert(std::make_pair<>(upid, uuid));
+ if (!it_and_inserted.second) {
+ // We already saw a another track with a different uuid for this process.
+ // Since there should only be one descriptor track for each process, we
+ // assume that its pid was reused. So, start a new process.
+ uint64_t old_uuid = it_and_inserted.first->second;
+ PERFETTO_DCHECK(old_uuid != uuid); // Every track is only resolved once.
+
+ PERFETTO_DLOG("Detected pid reuse (pid: %" PRIu32
+ ") from track descriptors (old uuid: %" PRIu64
+ " new uuid: %" PRIu64 " timestamp: %" PRId64 ")",
+ *reservation.pid, old_uuid, uuid,
+ reservation.min_timestamp);
+
+ upid = context_->process_tracker->StartNewProcess(
+ base::nullopt, base::nullopt, *reservation.pid, kNullStringId);
+
+ descriptor_uuids_by_upid_[upid] = uuid;
+ }
+ return InternProcessTrack(upid);
+ }
+
+ base::Optional<TrackId> track_id;
+ if (parent_track_id) {
+ // If parent is a thread track, create another thread-associated track.
+ base::Optional<uint32_t> thread_track_index =
+ context_->storage->thread_track_table().id().IndexOf(*parent_track_id);
+ if (thread_track_index) {
+ auto* thread_tracks = context_->storage->mutable_thread_track_table();
+ tables::ThreadTrackTable::Row row;
+ row.utid = thread_tracks->utid()[*thread_track_index];
+ track_id = thread_tracks->Insert(row);
+ } else {
+ // If parent is a process track, create another process-associated track.
+ base::Optional<uint32_t> process_track_index =
+ context_->storage->process_track_table().id().IndexOf(
+ *parent_track_id);
+ if (process_track_index) {
+ auto* process_tracks = context_->storage->mutable_process_track_table();
+ tables::ProcessTrackTable::Row track;
+ track.upid = process_tracks->upid()[*process_track_index];
+ track_id = process_tracks->Insert(track);
+ }
+ }
+ }
+
+ // Otherwise create a global track.
+ if (!track_id) {
+ tables::TrackTable::Row track;
+ track_id = context_->storage->mutable_track_table()->Insert(track);
+ // The global track with no uuid is the default global track (e.g. for
+ // global instant events). Any other global tracks are considered children
+ // of the default track.
+ if (!parent_track_id && uuid)
+ parent_track_id = GetOrCreateDefaultDescriptorTrack();
+ }
+
+ auto args = context_->args_tracker->AddArgsTo(*track_id);
+ args.AddArg(source_key_, Variadic::String(descriptor_source_))
+ .AddArg(source_id_key_, Variadic::Integer(static_cast<int64_t>(uuid)));
+ if (parent_track_id) {
+ args.AddArg(parent_track_id_key_,
+ Variadic::Integer(parent_track_id->value));
+ }
+ return *track_id;
}
TrackId TrackTracker::GetOrCreateDefaultDescriptorTrack() {
- base::Optional<TrackId> opt_track_id =
+ // If the default track was already reserved (e.g. because a producer emitted
+ // a descriptor for it) or created, resolve and return it.
+ base::Optional<TrackId> track_id =
GetDescriptorTrack(kDefaultDescriptorTrackUuid);
- if (opt_track_id)
- return *opt_track_id;
+ if (track_id)
+ return *track_id;
- return UpdateDescriptorTrack(kDefaultDescriptorTrackUuid,
- default_descriptor_track_name_);
+ // Otherwise reserve a new track and resolve it.
+ ReserveDescriptorChildTrack(kDefaultDescriptorTrackUuid, /*parent_uuid=*/0);
+ track_id = GetDescriptorTrack(kDefaultDescriptorTrackUuid);
+
+ auto* tracks = context_->storage->mutable_track_table();
+ tracks->mutable_name()->Set(*tracks->id().IndexOf(*track_id),
+ default_descriptor_track_name_);
+ return *track_id;
}
TrackId TrackTracker::InternGlobalCounterTrack(StringId name) {
diff --git a/src/trace_processor/track_tracker.h b/src/trace_processor/track_tracker.h
index 3a2b0ba..ddd6f11 100644
--- a/src/trace_processor/track_tracker.h
+++ b/src/trace_processor/track_tracker.h
@@ -31,6 +31,9 @@
// Interns a thread track into the storage.
TrackId InternThreadTrack(UniqueTid utid);
+ // Interns a process track into the storage.
+ TrackId InternProcessTrack(UniquePid upid);
+
// Interns a Fuchsia async track into the storage.
TrackId InternFuchsiaAsyncTrack(StringId name, int64_t correlation_id);
@@ -56,21 +59,50 @@
// Lazily creates the track for legacy Chrome global instant events.
TrackId GetOrCreateLegacyChromeGlobalInstantTrack();
- // Create or update the track for the TrackDescriptor with the given |uuid|.
- // Optionally, associate the track with a process or thread.
- TrackId UpdateDescriptorTrack(uint64_t uuid,
- StringId name,
- base::Optional<UniquePid> upid = base::nullopt,
- base::Optional<UniqueTid> utid = base::nullopt);
+ // Associate a TrackDescriptor track identified by the given |uuid| with a
+ // process's |pid|. This is called during tokenization. If a reservation for
+ // the same |uuid| already exists, verifies that the present reservation
+ // matches the new one.
+ //
+ // The track will be resolved to the process track (see InternProcessTrack())
+ // upon the first call to GetDescriptorTrack() with the same |uuid|. At this
+ // time, |pid| will also be resolved to a |upid|.
+ void ReserveDescriptorProcessTrack(uint64_t uuid,
+ uint32_t pid,
+ int64_t timestamp);
+
+ // Associate a TrackDescriptor track identified by the given |uuid| with a
+ // thread's |pid| and |tid|. This is called during tokenization. If a
+ // reservation for the same |uuid| already exists, verifies that the present
+ // reservation matches the new one.
+ //
+ // The track will be resolved to the thread track (see InternThreadTrack())
+ // upon the first call to GetDescriptorTrack() with the same |uuid|. At this
+ // time, |pid| will also be resolved to a |upid|.
+ void ReserveDescriptorThreadTrack(uint64_t uuid,
+ uint64_t parent_uuid,
+ uint32_t pid,
+ uint32_t tid,
+ int64_t timestamp);
+
+ // Associate a TrackDescriptor track identified by the given |uuid| with a
+ // parent track (usually a process- or thread-associated track). This is
+ // called during tokenization. If a reservation for the same |uuid| already
+ // exists, will attempt to update it.
+ //
+ // The track will be created upon the first call to GetDescriptorTrack() with
+ // the same |uuid|. If |parent_uuid| is 0, the track will become a global
+ // track. Otherwise, it will become a new track of the same type as its parent
+ // track.
+ void ReserveDescriptorChildTrack(uint64_t uuid, uint64_t parent_uuid);
// Returns the ID of the track for the TrackDescriptor with the given |uuid|.
- // Returns nullopt if no TrackDescriptor with this |uuid| has been parsed yet.
- base::Optional<TrackId> GetDescriptorTrack(uint64_t uuid) const;
-
- // Returns the ID of the TrackDescriptor track associated with the given utid.
- // If the trace contained multiple tracks associated with the utid, the first
- // created track is returned. Creates a new track if no such track exists.
- TrackId GetOrCreateDescriptorTrackForThread(UniqueTid utid);
+ // This is called during parsing. The first call to GetDescriptorTrack() for
+ // each |uuid| resolves and inserts the track (and its parent tracks,
+ // following the parent_uuid chain recursively) based on reservations made for
+ // the |uuid|. Returns nullopt if no track for a descriptor with this |uuid|
+ // has been reserved.
+ base::Optional<TrackId> GetDescriptorTrack(uint64_t uuid);
// Returns the ID of the implicit trace-global default TrackDescriptor track.
TrackId GetOrCreateDefaultDescriptorTrack();
@@ -99,8 +131,8 @@
// Creates a counter track associated with a GPU into the storage.
TrackId CreateGpuCounterTrack(StringId name,
uint32_t gpu_id,
- StringId description = 0,
- StringId unit = 0);
+ StringId description = StringId::Null(),
+ StringId unit = StringId::Null());
private:
struct GpuTrackTuple {
@@ -116,7 +148,7 @@
struct ChromeTrackTuple {
base::Optional<int64_t> upid;
int64_t source_id = 0;
- StringId source_scope = 0;
+ StringId source_scope = StringId::Null();
friend bool operator<(const ChromeTrackTuple& l,
const ChromeTrackTuple& r) {
@@ -135,18 +167,37 @@
std::tie(r.upid, r.cookie, r.name);
}
};
+ struct DescriptorTrackReservation {
+ uint64_t parent_uuid = 0;
+ base::Optional<uint32_t> pid;
+ base::Optional<uint32_t> tid;
+ int64_t min_timestamp = 0; // only set if |pid| and/or |tid| is set.
+
+ // Whether |other| is a valid descriptor for this track reservation. A track
+ // should always remain nested underneath its original parent.
+ bool IsForSameTrack(const DescriptorTrackReservation& other) {
+ // Note that |timestamp| is ignored for this comparison.
+ return std::tie(parent_uuid, pid, tid) ==
+ std::tie(other.parent_uuid, pid, tid);
+ }
+ };
+
+ TrackId ResolveDescriptorTrack(uint64_t uuid,
+ const DescriptorTrackReservation&);
static constexpr uint64_t kDefaultDescriptorTrackUuid = 0u;
- std::map<UniqueTid /* utid */, TrackId> thread_tracks_;
+ std::map<UniqueTid, TrackId> thread_tracks_;
+ std::map<UniquePid, TrackId> process_tracks_;
std::map<int64_t /* correlation_id */, TrackId> fuchsia_async_tracks_;
std::map<GpuTrackTuple, TrackId> gpu_tracks_;
std::map<ChromeTrackTuple, TrackId> chrome_tracks_;
std::map<AndroidAsyncTrackTuple, TrackId> android_async_tracks_;
std::map<UniquePid, TrackId> chrome_process_instant_tracks_;
base::Optional<TrackId> chrome_global_instant_track_id_;
- std::map<uint64_t /* uuid */, TrackId> descriptor_tracks_;
- std::map<UniqueTid, TrackId> descriptor_tracks_by_utid_;
+ std::map<uint64_t /* uuid */, DescriptorTrackReservation>
+ reserved_descriptor_tracks_;
+ std::map<uint64_t /* uuid */, TrackId> resolved_descriptor_tracks_;
std::map<StringId, TrackId> global_counter_tracks_by_name_;
std::map<std::pair<StringId, uint32_t>, TrackId> cpu_counter_tracks_;
@@ -156,17 +207,23 @@
std::map<std::pair<StringId, int32_t>, TrackId> softirq_counter_tracks_;
std::map<std::pair<StringId, uint32_t>, TrackId> gpu_counter_tracks_;
- const StringId source_key_ = 0;
- const StringId source_id_key_ = 0;
- const StringId source_id_is_process_scoped_key_ = 0;
- const StringId source_scope_key_ = 0;
+ // Stores the descriptor uuid used for the primary process/thread track
+ // for the given upid / utid. Used for pid/tid reuse detection.
+ std::map<UniquePid, uint64_t /*uuid*/> descriptor_uuids_by_upid_;
+ std::map<UniqueTid, uint64_t /*uuid*/> descriptor_uuids_by_utid_;
- const StringId fuchsia_source_ = 0;
- const StringId chrome_source_ = 0;
- const StringId android_source_ = 0;
- const StringId descriptor_source_ = 0;
+ const StringId source_key_ = kNullStringId;
+ const StringId source_id_key_ = kNullStringId;
+ const StringId source_id_is_process_scoped_key_ = kNullStringId;
+ const StringId source_scope_key_ = kNullStringId;
+ const StringId parent_track_id_key_ = kNullStringId;
- const StringId default_descriptor_track_name_ = 0;
+ const StringId fuchsia_source_ = kNullStringId;
+ const StringId chrome_source_ = kNullStringId;
+ const StringId android_source_ = kNullStringId;
+ const StringId descriptor_source_ = kNullStringId;
+
+ const StringId default_descriptor_track_name_ = kNullStringId;
TraceProcessorContext* const context_;
};
diff --git a/src/trace_processor/types/BUILD.gn b/src/trace_processor/types/BUILD.gn
new file mode 100644
index 0000000..b86ba23
--- /dev/null
+++ b/src/trace_processor/types/BUILD.gn
@@ -0,0 +1,27 @@
+# Copyright (C) 2020 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.
+
+source_set("types") {
+ sources = [
+ "gfp_flags.cc",
+ "gfp_flags.h",
+ "variadic.cc",
+ "variadic.h",
+ ]
+ deps = [
+ "../../../gn:default_deps",
+ "../../../include/perfetto/ext/base",
+ "../containers",
+ ]
+}
diff --git a/src/trace_processor/gfp_flags.cc b/src/trace_processor/types/gfp_flags.cc
similarity index 99%
rename from src/trace_processor/gfp_flags.cc
rename to src/trace_processor/types/gfp_flags.cc
index 2d5b587..74f7511 100644
--- a/src/trace_processor/gfp_flags.cc
+++ b/src/trace_processor/types/gfp_flags.cc
@@ -14,7 +14,8 @@
* limitations under the License.
*/
-#include "src/trace_processor/gfp_flags.h"
+#include "src/trace_processor/types/gfp_flags.h"
+
#include <array>
namespace perfetto {
diff --git a/src/trace_processor/gfp_flags.h b/src/trace_processor/types/gfp_flags.h
similarity index 88%
rename from src/trace_processor/gfp_flags.h
rename to src/trace_processor/types/gfp_flags.h
index 9d4cd7d..837b284 100644
--- a/src/trace_processor/gfp_flags.h
+++ b/src/trace_processor/types/gfp_flags.h
@@ -14,8 +14,8 @@
* limitations under the License.
*/
-#ifndef SRC_TRACE_PROCESSOR_GFP_FLAGS_H_
-#define SRC_TRACE_PROCESSOR_GFP_FLAGS_H_
+#ifndef SRC_TRACE_PROCESSOR_TYPES_GFP_FLAGS_H_
+#define SRC_TRACE_PROCESSOR_TYPES_GFP_FLAGS_H_
#include <tuple>
#include "perfetto/ext/base/string_writer.h"
@@ -33,4 +33,4 @@
} // namespace trace_processor
} // namespace perfetto
-#endif // SRC_TRACE_PROCESSOR_GFP_FLAGS_H_
+#endif // SRC_TRACE_PROCESSOR_TYPES_GFP_FLAGS_H_
diff --git a/test/task_runner_thread_delegates.cc b/src/trace_processor/types/variadic.cc
similarity index 68%
copy from test/task_runner_thread_delegates.cc
copy to src/trace_processor/types/variadic.cc
index 291482f..837bfeb 100644
--- a/test/task_runner_thread_delegates.cc
+++ b/src/trace_processor/types/variadic.cc
@@ -1,5 +1,5 @@
-/*
- * Copyright (C) 2019 The Android Open Source Project
+#/*
+ * Copyright (C) 2018 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.
@@ -14,12 +14,12 @@
* limitations under the License.
*/
-#include "test/task_runner_thread_delegates.h"
+#include "src/trace_processor/types/variadic.h"
namespace perfetto {
+namespace trace_processor {
-ServiceDelegate::~ServiceDelegate() = default;
-ProbesProducerDelegate::~ProbesProducerDelegate() = default;
-FakeProducerDelegate::~FakeProducerDelegate() = default;
+constexpr const char* Variadic::kTypeNames[];
+} // namespace trace_processor
} // namespace perfetto
diff --git a/src/trace_processor/variadic.h b/src/trace_processor/types/variadic.h
similarity index 89%
rename from src/trace_processor/variadic.h
rename to src/trace_processor/types/variadic.h
index 0444721..7a929e5 100644
--- a/src/trace_processor/variadic.h
+++ b/src/trace_processor/types/variadic.h
@@ -14,8 +14,8 @@
* limitations under the License.
*/
-#ifndef SRC_TRACE_PROCESSOR_VARIADIC_H_
-#define SRC_TRACE_PROCESSOR_VARIADIC_H_
+#ifndef SRC_TRACE_PROCESSOR_TYPES_VARIADIC_H_
+#define SRC_TRACE_PROCESSOR_TYPES_VARIADIC_H_
#include "src/trace_processor/containers/string_pool.h"
@@ -24,7 +24,19 @@
// Variadic type representing value of different possible types.
struct Variadic {
- enum Type { kInt, kUint, kString, kReal, kPointer, kBool, kJson };
+ enum Type : size_t {
+ kInt,
+ kUint,
+ kString,
+ kReal,
+ kPointer,
+ kBool,
+ kJson,
+ kMaxType = kJson,
+ };
+
+ static constexpr const char* const kTypeNames[] = {
+ "int", "uint", "string", "real", "pointer", "bool", "json"};
static Variadic Integer(int64_t int_value) {
Variadic variadic;
@@ -121,4 +133,4 @@
} // namespace trace_processor
} // namespace perfetto
-#endif // SRC_TRACE_PROCESSOR_VARIADIC_H_
+#endif // SRC_TRACE_PROCESSOR_TYPES_VARIADIC_H_
diff --git a/src/traced/probes/BUILD.gn b/src/traced/probes/BUILD.gn
index 6acb64a..4bdfba5 100644
--- a/src/traced/probes/BUILD.gn
+++ b/src/traced/probes/BUILD.gn
@@ -22,44 +22,37 @@
"../../../gn:default_deps",
"../../../include/perfetto/ext/traced",
]
- sources = [
- "main.cc",
- ]
+ sources = [ "main.cc" ]
assert_no_deps = [ "//gn:protobuf_lite" ]
}
# Contains all the implementation but not the main() entry point. This target
# is shared both by the executable and tests.
source_set("probes") {
- public_deps = [
- "../../../include/perfetto/ext/traced",
- ]
+ public_deps = [ "../../../include/perfetto/ext/traced" ]
deps = [
":probes_src",
"../../../gn:default_deps",
- "../../tracing:ipc",
+ "../../tracing/ipc/producer",
]
if (enable_perfetto_version_gen) {
deps += [ "//gn/standalone:gen_git_revision" ]
}
- sources = [
- "probes.cc",
- ]
+ sources = [ "probes.cc" ]
}
source_set("probes_src") {
- public_deps = [
- "ftrace",
- ]
+ public_deps = [ "ftrace" ]
deps = [
":data_source",
"../../../gn:default_deps",
"../../../include/perfetto/ext/traced",
"../../../protos/perfetto/config/ftrace:cpp",
+ "../../../protos/perfetto/trace:zero",
"../../../protos/perfetto/trace/ps:zero",
"../../base",
- "../../tracing:ipc",
- "../../tracing:tracing",
+ "../../tracing/core",
+ "../../tracing/ipc/producer",
"android_log",
"filesystem",
"metatrace",
@@ -79,7 +72,7 @@
source_set("data_source") {
deps = [
"../../../gn:default_deps",
- "../../tracing",
+ "../../tracing/core",
]
sources = [
"probes_data_source.cc",
@@ -93,7 +86,7 @@
":probes_src",
"../../../gn:default_deps",
"../../../gn:gtest_and_gmock",
- "../../tracing:test_support",
+ "../../tracing/test:test_support",
"android_log:unittests",
"filesystem:unittests",
"packages_list:unittests",
diff --git a/src/traced/probes/android_log/BUILD.gn b/src/traced/probes/android_log/BUILD.gn
index cc25cd4..9c3dc72 100644
--- a/src/traced/probes/android_log/BUILD.gn
+++ b/src/traced/probes/android_log/BUILD.gn
@@ -15,15 +15,14 @@
import("../../../../gn/test.gni")
source_set("android_log") {
- public_deps = [
- "../../../tracing",
- ]
+ public_deps = [ "../../../tracing/core" ]
deps = [
"..:data_source",
"../../../../gn:default_deps",
"../../../../include/perfetto/ext/traced",
"../../../../protos/perfetto/common:zero",
"../../../../protos/perfetto/config/android:zero",
+ "../../../../protos/perfetto/trace:zero",
"../../../../protos/perfetto/trace/android:zero",
"../../../base",
]
@@ -43,9 +42,7 @@
"../../../../protos/perfetto/config/android:cpp",
"../../../../protos/perfetto/trace/android:cpp",
"../../../../src/base:test_support",
- "../../../../src/tracing:test_support",
+ "../../../../src/tracing/test:test_support",
]
- sources = [
- "android_log_data_source_unittest.cc",
- ]
+ sources = [ "android_log_data_source_unittest.cc" ]
}
diff --git a/src/traced/probes/filesystem/BUILD.gn b/src/traced/probes/filesystem/BUILD.gn
index d3aeba5..faf101a 100644
--- a/src/traced/probes/filesystem/BUILD.gn
+++ b/src/traced/probes/filesystem/BUILD.gn
@@ -17,13 +17,14 @@
source_set("filesystem") {
public_deps = [
"../../../../protos/perfetto/trace/filesystem:zero",
- "../../../tracing",
+ "../../../tracing/core",
]
deps = [
"..:data_source",
"../../../../gn:default_deps",
"../../../../include/perfetto/ext/traced",
"../../../../protos/perfetto/config/inode_file:zero",
+ "../../../../protos/perfetto/trace:zero",
"../../../base",
]
sources = [
diff --git a/src/traced/probes/filesystem/inode_file_data_source.h b/src/traced/probes/filesystem/inode_file_data_source.h
index ac5275c..8ccab1a 100644
--- a/src/traced/probes/filesystem/inode_file_data_source.h
+++ b/src/traced/probes/filesystem/inode_file_data_source.h
@@ -25,8 +25,8 @@
#include <string>
#include <unordered_map>
+#include "perfetto/base/flat_set.h"
#include "perfetto/base/task_runner.h"
-#include "perfetto/ext/base/flat_set.h"
#include "perfetto/ext/base/weak_ptr.h"
#include "perfetto/ext/traced/data_source_types.h"
#include "perfetto/ext/tracing/core/basic_types.h"
diff --git a/src/traced/probes/ftrace/BUILD.gn b/src/traced/probes/ftrace/BUILD.gn
index 02ef384..5d9cd70 100644
--- a/src/traced/probes/ftrace/BUILD.gn
+++ b/src/traced/probes/ftrace/BUILD.gn
@@ -32,9 +32,7 @@
"../../../base:test_support",
"../../../protozero",
]
- public_deps = [
- "../../../protozero",
- ]
+ public_deps = [ "../../../protozero" ]
sources = [
"test/cpu_reader_support.cc",
@@ -57,7 +55,7 @@
"../../../../protos/perfetto/trace/ftrace:cpp",
"../../../../protos/perfetto/trace/ftrace:zero",
"../../../base:test_support",
- "../../../tracing:test_support",
+ "../../../tracing/test:test_support",
]
sources = [
"cpu_reader_unittest.cc",
@@ -78,9 +76,7 @@
"lite",
"zero",
]
- sources = [
- "test/test_messages.proto",
- ]
+ sources = [ "test/test_messages.proto" ]
proto_path = perfetto_root_path
}
@@ -94,24 +90,23 @@
"../../../../gn:default_deps",
"../../../../gn:gtest_and_gmock",
"../../../base",
- "../../../tracing",
+ "../../../tracing/core",
]
- sources = [
- "ftrace_procfs_integrationtest.cc",
- ]
+ sources = [ "ftrace_procfs_integrationtest.cc" ]
}
source_set("ftrace") {
public_deps = [
"../../../../protos/perfetto/config/ftrace:cpp",
"../../../../protos/perfetto/trace/ftrace:zero",
- "../../../tracing",
+ "../../../tracing/core",
]
deps = [
":format_parser",
"..:data_source",
"../../../../gn:default_deps",
"../../../../include/perfetto/ext/traced",
+ "../../../../protos/perfetto/trace:zero",
"../../../android_internal:lazy_library_loader",
"../../../base",
"../../../protozero",
@@ -169,17 +164,13 @@
"../../../../gn:benchmark",
"../../../../gn:default_deps",
]
- sources = [
- "cpu_reader_benchmark.cc",
- ]
+ sources = [ "cpu_reader_benchmark.cc" ]
}
}
perfetto_fuzzer_test("cpu_reader_fuzzer") {
testonly = true
- sources = [
- "cpu_reader_fuzzer.cc",
- ]
+ sources = [ "cpu_reader_fuzzer.cc" ]
deps = [
":ftrace",
":test_support",
diff --git a/src/traced/probes/ftrace/cpu_reader_benchmark.cc b/src/traced/probes/ftrace/cpu_reader_benchmark.cc
index 58b4e20..ee6d246 100644
--- a/src/traced/probes/ftrace/cpu_reader_benchmark.cc
+++ b/src/traced/probes/ftrace/cpu_reader_benchmark.cc
@@ -315,8 +315,8 @@
ProtoTranslationTable* table = GetTable(test_case->name);
auto page = PageFromXxd(test_case->data);
- FtraceDataSourceConfig ds_config{EventFilter{},
- DisabledCompactSchedConfigForTesting()};
+ FtraceDataSourceConfig ds_config{
+ EventFilter{}, DisabledCompactSchedConfigForTesting(), {}, {}};
ds_config.event_filter.AddEnabledEvent(
table->EventToFtraceId(GroupAndName("sched", "sched_switch")));
diff --git a/src/traced/probes/ftrace/cpu_reader_fuzzer.cc b/src/traced/probes/ftrace/cpu_reader_fuzzer.cc
index 61d5b80..27e5db3 100644
--- a/src/traced/probes/ftrace/cpu_reader_fuzzer.cc
+++ b/src/traced/probes/ftrace/cpu_reader_fuzzer.cc
@@ -52,8 +52,8 @@
memcpy(g_page, data, std::min(base::kPageSize, size));
FtraceMetadata metadata{};
- FtraceDataSourceConfig ds_config{EventFilter{},
- DisabledCompactSchedConfigForTesting()};
+ FtraceDataSourceConfig ds_config{
+ EventFilter{}, DisabledCompactSchedConfigForTesting(), {}, {}};
ds_config.event_filter.AddEnabledEvent(
table->EventToFtraceId(GroupAndName("sched", "sched_switch")));
ds_config.event_filter.AddEnabledEvent(
diff --git a/src/traced/probes/ftrace/cpu_reader_unittest.cc b/src/traced/probes/ftrace/cpu_reader_unittest.cc
index 61cdc23..2d10829 100644
--- a/src/traced/probes/ftrace/cpu_reader_unittest.cc
+++ b/src/traced/probes/ftrace/cpu_reader_unittest.cc
@@ -60,6 +60,11 @@
namespace {
+FtraceDataSourceConfig EmptyConfig() {
+ return FtraceDataSourceConfig{
+ EventFilter{}, DisabledCompactSchedConfigForTesting(), {}, {}};
+}
+
constexpr uint64_t kNanoInSecond = 1000 * 1000 * 1000;
constexpr uint64_t kNanoInMicro = 1000;
@@ -378,8 +383,7 @@
ProtoTranslationTable* table = GetTable(test_case->name);
auto page = PageFromXxd(test_case->data);
- FtraceDataSourceConfig ds_config{EventFilter{},
- DisabledCompactSchedConfigForTesting()};
+ FtraceDataSourceConfig ds_config = EmptyConfig();
ds_config.event_filter.AddEnabledEvent(
table->EventToFtraceId(GroupAndName("ftrace", "print")));
@@ -507,8 +511,7 @@
ProtoTranslationTable* table = GetTable(test_case->name);
auto page = PageFromXxd(test_case->data);
- FtraceDataSourceConfig ds_config{EventFilter{},
- DisabledCompactSchedConfigForTesting()};
+ FtraceDataSourceConfig ds_config = EmptyConfig();
ds_config.event_filter.AddEnabledEvent(
table->EventToFtraceId(GroupAndName("ftrace", "print")));
@@ -557,8 +560,7 @@
ProtoTranslationTable* table = GetTable(test_case->name);
auto page = PageFromXxd(test_case->data);
- FtraceDataSourceConfig ds_config{EventFilter{},
- DisabledCompactSchedConfigForTesting()};
+ FtraceDataSourceConfig ds_config = EmptyConfig();
ds_config.event_filter.AddEnabledEvent(
table->EventToFtraceId(GroupAndName("ftrace", "print")));
@@ -598,8 +600,7 @@
ProtoTranslationTable* table = GetTable(test_case->name);
auto page = PageFromXxd(test_case->data);
- FtraceDataSourceConfig ds_config{EventFilter{},
- DisabledCompactSchedConfigForTesting()};
+ FtraceDataSourceConfig ds_config = EmptyConfig();
FtraceMetadata metadata{};
CompactSchedBuffer compact_buffer;
@@ -662,8 +663,7 @@
ProtoTranslationTable* table = GetTable(test_case->name);
auto page = PageFromXxd(test_case->data);
- FtraceDataSourceConfig ds_config{EventFilter{},
- DisabledCompactSchedConfigForTesting()};
+ FtraceDataSourceConfig ds_config = EmptyConfig();
ds_config.event_filter.AddEnabledEvent(
table->EventToFtraceId(GroupAndName("ftrace", "print")));
@@ -772,8 +772,7 @@
ProtoTranslationTable* table = GetTable(test_case->name);
auto page = PageFromXxd(test_case->data);
- FtraceDataSourceConfig ds_config{EventFilter{},
- DisabledCompactSchedConfigForTesting()};
+ FtraceDataSourceConfig ds_config = EmptyConfig();
ds_config.event_filter.AddEnabledEvent(
table->EventToFtraceId(GroupAndName("sched", "sched_switch")));
@@ -819,8 +818,8 @@
ProtoTranslationTable* table = GetTable(test_case->name);
auto page = PageFromXxd(test_case->data);
- FtraceDataSourceConfig ds_config{EventFilter{},
- EnabledCompactSchedConfigForTesting()};
+ FtraceDataSourceConfig ds_config{
+ EventFilter{}, EnabledCompactSchedConfigForTesting(), {}, {}};
ds_config.event_filter.AddEnabledEvent(
table->EventToFtraceId(GroupAndName("sched", "sched_switch")));
@@ -1160,8 +1159,7 @@
BundleProvider bundle_provider(base::kPageSize);
ProtoTranslationTable* table = GetTable("synthetic");
FtraceMetadata metadata{};
- FtraceDataSourceConfig ds_config{EventFilter{},
- DisabledCompactSchedConfigForTesting()};
+ FtraceDataSourceConfig ds_config = EmptyConfig();
ds_config.event_filter.AddEnabledEvent(
table->EventToFtraceId(GroupAndName("sched", "sched_switch")));
@@ -1618,8 +1616,7 @@
ProtoTranslationTable* table = GetTable(test_case->name);
auto page = PageFromXxd(test_case->data);
- FtraceDataSourceConfig ds_config{EventFilter{},
- DisabledCompactSchedConfigForTesting()};
+ FtraceDataSourceConfig ds_config = EmptyConfig();
ds_config.event_filter.AddEnabledEvent(
table->EventToFtraceId(GroupAndName("sched", "sched_switch")));
@@ -2063,8 +2060,7 @@
ProtoTranslationTable* table = GetTable(test_case->name);
auto page = PageFromXxd(test_case->data);
- FtraceDataSourceConfig ds_config{EventFilter{},
- DisabledCompactSchedConfigForTesting()};
+ FtraceDataSourceConfig ds_config = EmptyConfig();
ds_config.event_filter.AddEnabledEvent(
table->EventToFtraceId(GroupAndName("sched", "sched_switch")));
diff --git a/src/traced/probes/ftrace/format_parser.cc b/src/traced/probes/ftrace/format_parser.cc
index c5ce2c1..d4e119f 100644
--- a/src/traced/probes/ftrace/format_parser.cc
+++ b/src/traced/probes/ftrace/format_parser.cc
@@ -141,7 +141,7 @@
for (base::StringSplitter ss(std::move(input), '\n'); ss.Next();) {
const char* line = ss.cur_token();
- if (!has_id && sscanf(line, "ID: %d", &id) == 1) {
+ if (!has_id && sscanf(line, "ID: %u", &id) == 1) {
has_id = true;
continue;
}
diff --git a/src/traced/probes/ftrace/ftrace_config_muxer.cc b/src/traced/probes/ftrace/ftrace_config_muxer.cc
index f0cf926..5a93e5f 100644
--- a/src/traced/probes/ftrace/ftrace_config_muxer.cc
+++ b/src/traced/probes/ftrace/ftrace_config_muxer.cc
@@ -22,6 +22,7 @@
#include <unistd.h>
#include <algorithm>
+#include <iterator>
#include "perfetto/ext/base/utils.h"
#include "protos/perfetto/trace/ftrace/sched.pbzero.h"
@@ -67,6 +68,28 @@
event.substr(slash_pos + 1));
}
+void UnionInPlace(const std::vector<std::string>& unsorted_a,
+ std::vector<std::string>* out) {
+ std::vector<std::string> a = unsorted_a;
+ std::sort(a.begin(), a.end());
+ std::sort(out->begin(), out->end());
+ std::vector<std::string> v;
+ std::set_union(a.begin(), a.end(), out->begin(), out->end(),
+ std::back_inserter(v));
+ *out = std::move(v);
+}
+
+void IntersectInPlace(const std::vector<std::string>& unsorted_a,
+ std::vector<std::string>* out) {
+ std::vector<std::string> a = unsorted_a;
+ std::sort(a.begin(), a.end());
+ std::sort(out->begin(), out->end());
+ std::vector<std::string> v;
+ std::set_intersection(a.begin(), a.end(), out->begin(), out->end(),
+ std::back_inserter(v));
+ *out = std::move(v);
+}
+
} // namespace
std::set<GroupAndName> FtraceConfigMuxer::GetFtraceEvents(
@@ -453,10 +476,14 @@
auto compact_sched =
CreateCompactSchedConfig(request, table_->compact_sched_format());
- FtraceConfigId id = ++last_id_;
- ds_configs_.emplace(std::piecewise_construct, std::forward_as_tuple(id),
- std::forward_as_tuple(std::move(filter), compact_sched));
+ std::vector<std::string> apps(request.atrace_apps());
+ std::vector<std::string> categories(request.atrace_categories());
+ FtraceConfigId id = ++last_id_;
+ ds_configs_.emplace(
+ std::piecewise_construct, std::forward_as_tuple(id),
+ std::forward_as_tuple(std::move(filter), compact_sched, std::move(apps),
+ std::move(categories)));
return id;
}
@@ -487,9 +514,29 @@
if (!config_id || !ds_configs_.erase(config_id))
return false;
EventFilter expected_ftrace_events;
- for (const auto& ds_config : ds_configs_) {
- expected_ftrace_events.EnableEventsFrom(ds_config.second.event_filter);
+ std::vector<std::string> expected_apps;
+ std::vector<std::string> expected_categories;
+ for (const auto& id_config : ds_configs_) {
+ const perfetto::FtraceDataSourceConfig& config = id_config.second;
+ expected_ftrace_events.EnableEventsFrom(config.event_filter);
+ UnionInPlace(config.atrace_apps, &expected_apps);
+ UnionInPlace(config.atrace_categories, &expected_categories);
}
+ // At this point expected_{apps,categories} contains the union of the
+ // leftover configs (if any) that should be still on. However we did not
+ // necessarily succeed in turning on atrace for each of those configs
+ // previously so we now intersect the {apps,categories} that we *did* manage
+ // to turn on with those we want on to determine the new state we should aim
+ // for:
+ IntersectInPlace(current_state_.atrace_apps, &expected_apps);
+ IntersectInPlace(current_state_.atrace_categories, &expected_categories);
+ // Work out if there is any difference between the current state and the
+ // desired state: It's sufficient to compare sizes here (since we know from
+ // above that expected_{apps,categories} is now a subset of
+ // atrace_{apps,categories}:
+ bool atrace_changed =
+ (current_state_.atrace_apps.size() != expected_apps.size()) ||
+ (current_state_.atrace_categories.size() != expected_categories.size());
// Disable any events that are currently enabled, but are not in any configs
// anymore.
@@ -524,8 +571,22 @@
current_state_.cpu_buffer_size_pages = 1;
ftrace_->DisableAllEvents();
ftrace_->ClearTrace();
- if (current_state_.atrace_on)
+ }
+
+ if (current_state_.atrace_on) {
+ if (expected_apps.empty() && expected_categories.empty()) {
DisableAtrace();
+ } else if (atrace_changed) {
+ // Update atrace to remove the no longer wanted categories/apps. For
+ // some categories this won't disable them (e.g. categories that just
+ // enable ftrace events) for those there is nothing we can do till the
+ // last ftrace config is removed.
+ if (StartAtrace(expected_apps, expected_categories)) {
+ // Update current_state_ to reflect this change.
+ current_state_.atrace_apps = expected_apps;
+ current_state_.atrace_categories = expected_categories;
+ }
+ }
}
return true;
@@ -564,29 +625,58 @@
}
void FtraceConfigMuxer::UpdateAtrace(const FtraceConfig& request) {
+ // We want to avoid poisoning current_state_.atrace_{categories, apps}
+ // if for some reason these args make atrace unhappy so we stash the
+ // union into temps and only update current_state_ if we successfully
+ // run atrace.
+
+ std::vector<std::string> combined_categories = request.atrace_categories();
+ UnionInPlace(current_state_.atrace_categories, &combined_categories);
+
+ std::vector<std::string> combined_apps = request.atrace_apps();
+ UnionInPlace(current_state_.atrace_apps, &combined_apps);
+
+ if (current_state_.atrace_on &&
+ combined_apps.size() == current_state_.atrace_apps.size() &&
+ combined_categories.size() == current_state_.atrace_categories.size()) {
+ return;
+ }
+
+ if (StartAtrace(combined_apps, combined_categories)) {
+ current_state_.atrace_categories = combined_categories;
+ current_state_.atrace_apps = combined_apps;
+ current_state_.atrace_on = true;
+ }
+}
+
+// static
+bool FtraceConfigMuxer::StartAtrace(
+ const std::vector<std::string>& apps,
+ const std::vector<std::string>& categories) {
PERFETTO_DLOG("Update atrace config...");
std::vector<std::string> args;
args.push_back("atrace"); // argv0 for exec()
args.push_back("--async_start");
args.push_back("--only_userspace");
- for (const auto& category : request.atrace_categories())
+
+ for (const auto& category : categories)
args.push_back(category);
- if (!request.atrace_apps().empty()) {
+
+ if (!apps.empty()) {
args.push_back("-a");
std::string arg = "";
- for (const auto& app : request.atrace_apps()) {
+ for (const auto& app : apps) {
arg += app;
- if (app != request.atrace_apps().back())
- arg += ",";
+ arg += ",";
}
+ arg.resize(arg.size() - 1);
args.push_back(arg);
}
- if (RunAtrace(args))
- current_state_.atrace_on = true;
-
- PERFETTO_DLOG("...done");
+ bool result = RunAtrace(args);
+ PERFETTO_DLOG("...done (%s)", result ? "success" : "fail");
+ return result;
}
void FtraceConfigMuxer::DisableAtrace() {
@@ -594,8 +684,11 @@
PERFETTO_DLOG("Stop atrace...");
- if (RunAtrace({"atrace", "--async_stop", "--only_userspace"}))
+ if (RunAtrace({"atrace", "--async_stop", "--only_userspace"})) {
+ current_state_.atrace_categories.clear();
+ current_state_.atrace_apps.clear();
current_state_.atrace_on = false;
+ }
PERFETTO_DLOG("...done");
}
diff --git a/src/traced/probes/ftrace/ftrace_config_muxer.h b/src/traced/probes/ftrace/ftrace_config_muxer.h
index 416a38b..16883c4 100644
--- a/src/traced/probes/ftrace/ftrace_config_muxer.h
+++ b/src/traced/probes/ftrace/ftrace_config_muxer.h
@@ -32,8 +32,13 @@
// that data source's config.
struct FtraceDataSourceConfig {
FtraceDataSourceConfig(EventFilter _event_filter,
- CompactSchedConfig _compact_sched)
- : event_filter(std::move(_event_filter)), compact_sched(_compact_sched) {}
+ CompactSchedConfig _compact_sched,
+ std::vector<std::string> _atrace_apps,
+ std::vector<std::string> _atrace_categories)
+ : event_filter(std::move(_event_filter)),
+ compact_sched(_compact_sched),
+ atrace_apps(std::move(_atrace_apps)),
+ atrace_categories(std::move(_atrace_categories)) {}
// The event filter allows to quickly check if a certain ftrace event with id
// x is enabled for this data source.
@@ -41,6 +46,10 @@
// Configuration of the optional compact encoding of scheduling events.
const CompactSchedConfig compact_sched;
+
+ // Used only in Android for ATRACE_EVENT/os.Trace() userspace annotations.
+ std::vector<std::string> atrace_apps;
+ std::vector<std::string> atrace_categories;
};
// Ftrace is a bunch of globally modifiable persistent state.
@@ -103,11 +112,17 @@
}
private:
+ static bool StartAtrace(const std::vector<std::string>& apps,
+ const std::vector<std::string>& categories);
+
struct FtraceState {
EventFilter ftrace_events;
+ // Used only in Android for ATRACE_EVENT/os.Trace() userspace
+ std::vector<std::string> atrace_apps;
+ std::vector<std::string> atrace_categories;
+ size_t cpu_buffer_size_pages = 0;
bool tracing_on = false;
bool atrace_on = false;
- size_t cpu_buffer_size_pages = 0;
};
FtraceConfigMuxer(const FtraceConfigMuxer&) = delete;
diff --git a/src/traced/probes/ftrace/ftrace_config_muxer_unittest.cc b/src/traced/probes/ftrace/ftrace_config_muxer_unittest.cc
index 890e07a..0b069c2 100644
--- a/src/traced/probes/ftrace/ftrace_config_muxer_unittest.cc
+++ b/src/traced/probes/ftrace/ftrace_config_muxer_unittest.cc
@@ -509,7 +509,7 @@
atrace,
RunAtrace(ElementsAreArray(
{"atrace", "--async_start", "--only_userspace", "-a",
- "com.google.android.gms.persistent,com.google.android.gms"})))
+ "com.google.android.gms,com.google.android.gms.persistent"})))
.WillOnce(Return(true));
FtraceConfigId id = model.SetupConfig(config);
@@ -526,6 +526,211 @@
ASSERT_TRUE(model.RemoveConfig(id));
}
+TEST_F(FtraceConfigMuxerTest, AtraceMultipleConfigs) {
+ NiceMock<MockFtraceProcfs> ftrace;
+ MockRunAtrace atrace;
+
+ FtraceConfig config_a = CreateFtraceConfig({});
+ *config_a.add_atrace_apps() = "app_a";
+ *config_a.add_atrace_categories() = "cat_a";
+
+ FtraceConfig config_b = CreateFtraceConfig({});
+ *config_b.add_atrace_apps() = "app_b";
+ *config_b.add_atrace_categories() = "cat_b";
+
+ FtraceConfig config_c = CreateFtraceConfig({});
+ *config_c.add_atrace_apps() = "app_c";
+ *config_c.add_atrace_categories() = "cat_c";
+
+ FtraceConfigMuxer model(&ftrace, table_.get());
+
+ EXPECT_CALL(atrace, RunAtrace(ElementsAreArray({"atrace", "--async_start",
+ "--only_userspace", "cat_a",
+ "-a", "app_a"})))
+ .WillOnce(Return(true));
+ FtraceConfigId id_a = model.SetupConfig(config_a);
+ ASSERT_TRUE(id_a);
+
+ EXPECT_CALL(
+ atrace,
+ RunAtrace(ElementsAreArray({"atrace", "--async_start", "--only_userspace",
+ "cat_a", "cat_b", "-a", "app_a,app_b"})))
+ .WillOnce(Return(true));
+ FtraceConfigId id_b = model.SetupConfig(config_b);
+ ASSERT_TRUE(id_b);
+
+ EXPECT_CALL(atrace,
+ RunAtrace(ElementsAreArray({"atrace", "--async_start",
+ "--only_userspace", "cat_a", "cat_b",
+ "cat_c", "-a", "app_a,app_b,app_c"})))
+ .WillOnce(Return(true));
+ FtraceConfigId id_c = model.SetupConfig(config_c);
+ ASSERT_TRUE(id_c);
+
+ EXPECT_CALL(
+ atrace,
+ RunAtrace(ElementsAreArray({"atrace", "--async_start", "--only_userspace",
+ "cat_a", "cat_c", "-a", "app_a,app_c"})))
+ .WillOnce(Return(true));
+ ASSERT_TRUE(model.RemoveConfig(id_b));
+
+ EXPECT_CALL(atrace, RunAtrace(ElementsAreArray({"atrace", "--async_start",
+ "--only_userspace", "cat_c",
+ "-a", "app_c"})))
+ .WillOnce(Return(true));
+ ASSERT_TRUE(model.RemoveConfig(id_a));
+
+ EXPECT_CALL(atrace, RunAtrace(ElementsAreArray(
+ {"atrace", "--async_stop", "--only_userspace"})))
+ .WillOnce(Return(true));
+ ASSERT_TRUE(model.RemoveConfig(id_c));
+}
+
+TEST_F(FtraceConfigMuxerTest, AtraceFailedConfig) {
+ NiceMock<MockFtraceProcfs> ftrace;
+ MockRunAtrace atrace;
+
+ FtraceConfig config_a = CreateFtraceConfig({});
+ *config_a.add_atrace_apps() = "app_1";
+ *config_a.add_atrace_apps() = "app_2";
+ *config_a.add_atrace_categories() = "cat_1";
+ *config_a.add_atrace_categories() = "cat_2";
+
+ FtraceConfig config_b = CreateFtraceConfig({});
+ *config_b.add_atrace_apps() = "app_fail";
+ *config_b.add_atrace_categories() = "cat_fail";
+
+ FtraceConfig config_c = CreateFtraceConfig({});
+ *config_c.add_atrace_apps() = "app_1";
+ *config_c.add_atrace_apps() = "app_3";
+ *config_c.add_atrace_categories() = "cat_1";
+ *config_c.add_atrace_categories() = "cat_3";
+
+ FtraceConfigMuxer model(&ftrace, table_.get());
+
+ EXPECT_CALL(
+ atrace,
+ RunAtrace(ElementsAreArray({"atrace", "--async_start", "--only_userspace",
+ "cat_1", "cat_2", "-a", "app_1,app_2"})))
+ .WillOnce(Return(true));
+ FtraceConfigId id_a = model.SetupConfig(config_a);
+ ASSERT_TRUE(id_a);
+
+ EXPECT_CALL(atrace,
+ RunAtrace(ElementsAreArray(
+ {"atrace", "--async_start", "--only_userspace", "cat_1",
+ "cat_2", "cat_fail", "-a", "app_1,app_2,app_fail"})))
+ .WillOnce(Return(false));
+ FtraceConfigId id_b = model.SetupConfig(config_b);
+ ASSERT_TRUE(id_b);
+
+ EXPECT_CALL(atrace,
+ RunAtrace(ElementsAreArray({"atrace", "--async_start",
+ "--only_userspace", "cat_1", "cat_2",
+ "cat_3", "-a", "app_1,app_2,app_3"})))
+ .WillOnce(Return(true));
+ FtraceConfigId id_c = model.SetupConfig(config_c);
+ ASSERT_TRUE(id_c);
+
+ EXPECT_CALL(
+ atrace,
+ RunAtrace(ElementsAreArray({"atrace", "--async_start", "--only_userspace",
+ "cat_1", "cat_2", "-a", "app_1,app_2"})))
+ .WillOnce(Return(true));
+ ASSERT_TRUE(model.RemoveConfig(id_c));
+
+ // Removing the config we failed to enable doesn't change the atrace state
+ // so we don't expect a call here.
+ ASSERT_TRUE(model.RemoveConfig(id_b));
+
+ EXPECT_CALL(atrace, RunAtrace(ElementsAreArray(
+ {"atrace", "--async_stop", "--only_userspace"})))
+ .WillOnce(Return(true));
+ ASSERT_TRUE(model.RemoveConfig(id_a));
+}
+
+TEST_F(FtraceConfigMuxerTest, AtraceDuplicateConfigs) {
+ NiceMock<MockFtraceProcfs> ftrace;
+ MockRunAtrace atrace;
+
+ FtraceConfig config_a = CreateFtraceConfig({});
+ *config_a.add_atrace_apps() = "app_1";
+ *config_a.add_atrace_categories() = "cat_1";
+
+ FtraceConfig config_b = CreateFtraceConfig({});
+ *config_b.add_atrace_apps() = "app_1";
+ *config_b.add_atrace_categories() = "cat_1";
+
+ FtraceConfigMuxer model(&ftrace, table_.get());
+
+ EXPECT_CALL(atrace, RunAtrace(ElementsAreArray({"atrace", "--async_start",
+ "--only_userspace", "cat_1",
+ "-a", "app_1"})))
+ .WillOnce(Return(true));
+ FtraceConfigId id_a = model.SetupConfig(config_a);
+ ASSERT_TRUE(id_a);
+
+ FtraceConfigId id_b = model.SetupConfig(config_b);
+ ASSERT_TRUE(id_b);
+
+ ASSERT_TRUE(model.RemoveConfig(id_a));
+
+ EXPECT_CALL(atrace, RunAtrace(ElementsAreArray(
+ {"atrace", "--async_stop", "--only_userspace"})))
+ .WillOnce(Return(true));
+ ASSERT_TRUE(model.RemoveConfig(id_b));
+}
+
+TEST_F(FtraceConfigMuxerTest, AtraceAndFtraceConfigs) {
+ NiceMock<MockFtraceProcfs> ftrace;
+ MockRunAtrace atrace;
+
+ FtraceConfig config_a = CreateFtraceConfig({"sched/sched_cpu_hotplug"});
+
+ FtraceConfig config_b = CreateFtraceConfig({"sched/sched_switch"});
+ *config_b.add_atrace_categories() = "b";
+
+ FtraceConfig config_c = CreateFtraceConfig({"sched/sched_switch"});
+
+ FtraceConfig config_d = CreateFtraceConfig({"sched/sched_cpu_hotplug"});
+ *config_d.add_atrace_categories() = "d";
+
+ FtraceConfigMuxer model(&ftrace, table_.get());
+
+ FtraceConfigId id_a = model.SetupConfig(config_a);
+ ASSERT_TRUE(id_a);
+
+ EXPECT_CALL(atrace, RunAtrace(ElementsAreArray({"atrace", "--async_start",
+ "--only_userspace", "b"})))
+ .WillOnce(Return(true));
+ FtraceConfigId id_b = model.SetupConfig(config_b);
+ ASSERT_TRUE(id_b);
+
+ FtraceConfigId id_c = model.SetupConfig(config_c);
+ ASSERT_TRUE(id_c);
+
+ EXPECT_CALL(atrace,
+ RunAtrace(ElementsAreArray(
+ {"atrace", "--async_start", "--only_userspace", "b", "d"})))
+ .WillOnce(Return(true));
+ FtraceConfigId id_d = model.SetupConfig(config_d);
+ ASSERT_TRUE(id_d);
+
+ EXPECT_CALL(atrace, RunAtrace(ElementsAreArray({"atrace", "--async_start",
+ "--only_userspace", "b"})))
+ .WillOnce(Return(true));
+ ASSERT_TRUE(model.RemoveConfig(id_d));
+
+ ASSERT_TRUE(model.RemoveConfig(id_c));
+
+ EXPECT_CALL(atrace, RunAtrace(ElementsAreArray(
+ {"atrace", "--async_stop", "--only_userspace"})))
+ .WillOnce(Return(true));
+ ASSERT_TRUE(model.RemoveConfig(id_b));
+
+ ASSERT_TRUE(model.RemoveConfig(id_a));
+}
+
TEST_F(FtraceConfigMuxerTest, SetupClockForTesting) {
MockFtraceProcfs ftrace;
FtraceConfig config;
diff --git a/src/traced/probes/ftrace/ftrace_data_source.cc b/src/traced/probes/ftrace/ftrace_data_source.cc
index f576f16..f28a491 100644
--- a/src/traced/probes/ftrace/ftrace_data_source.cc
+++ b/src/traced/probes/ftrace/ftrace_data_source.cc
@@ -36,12 +36,12 @@
: ProbesDataSource(session_id, kTypeId),
config_(config),
writer_(std::move(writer)),
- controller_weak_(std::move(controller_weak)){};
+ controller_weak_(std::move(controller_weak)) {}
FtraceDataSource::~FtraceDataSource() {
if (controller_weak_)
controller_weak_->RemoveDataSource(this);
-};
+}
void FtraceDataSource::Initialize(
FtraceConfigId config_id,
diff --git a/src/traced/probes/ftrace/ftrace_metadata.h b/src/traced/probes/ftrace/ftrace_metadata.h
index de9d89a..8294f25 100644
--- a/src/traced/probes/ftrace/ftrace_metadata.h
+++ b/src/traced/probes/ftrace/ftrace_metadata.h
@@ -23,8 +23,8 @@
#include <bitset>
+#include "perfetto/base/flat_set.h"
#include "perfetto/base/logging.h"
-#include "perfetto/ext/base/flat_set.h"
#include "perfetto/ext/traced/data_source_types.h"
namespace perfetto {
diff --git a/src/traced/probes/ftrace/kallsyms/BUILD.gn b/src/traced/probes/ftrace/kallsyms/BUILD.gn
new file mode 100644
index 0000000..0c42b98
--- /dev/null
+++ b/src/traced/probes/ftrace/kallsyms/BUILD.gn
@@ -0,0 +1,52 @@
+# Copyright (C) 2019 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.
+
+import("../../../../../gn/test.gni")
+
+source_set("kallsyms") {
+ deps = [
+ "../../../../../gn:default_deps",
+ "../../../../../include/perfetto/protozero",
+ "../../../../base",
+ ]
+ sources = [
+ "kernel_symbol_map.cc",
+ "kernel_symbol_map.h",
+ ]
+}
+
+perfetto_unittest_source_set("unittests") {
+ testonly = true
+ deps = [
+ ":kallsyms",
+ "../../../../../gn:default_deps",
+ "../../../../../gn:gtest_and_gmock",
+ "../../../../base",
+ ]
+ sources = [ "kernel_symbol_map_unittest.cc" ]
+}
+
+if (enable_perfetto_benchmarks) {
+ source_set("benchmarks") {
+ testonly = true
+ deps = [
+ ":kallsyms",
+ "../../../../../gn:benchmark",
+ "../../../../../gn:default_deps",
+ "../../../../base",
+ "../../../../base:test_support",
+ ]
+ sources = [ "kernel_symbol_map_benchmark.cc" ]
+ }
+}
diff --git a/src/traced/probes/ftrace/kallsyms/kernel_symbol_map.cc b/src/traced/probes/ftrace/kallsyms/kernel_symbol_map.cc
new file mode 100644
index 0000000..f2d55f0
--- /dev/null
+++ b/src/traced/probes/ftrace/kallsyms/kernel_symbol_map.cc
@@ -0,0 +1,407 @@
+/*
+ * Copyright (C) 2019 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.
+ */
+
+#include "src/traced/probes/ftrace/kallsyms/kernel_symbol_map.h"
+
+#include "perfetto/base/logging.h"
+#include "perfetto/ext/base/metatrace.h"
+#include "perfetto/ext/base/paged_memory.h"
+#include "perfetto/ext/base/scoped_file.h"
+#include "perfetto/ext/base/string_view.h"
+#include "perfetto/ext/base/utils.h"
+#include "perfetto/protozero/proto_utils.h"
+
+#include <inttypes.h>
+#include <stdio.h>
+
+#include <algorithm>
+#include <functional>
+#include <map>
+#include <utility>
+
+namespace perfetto {
+
+// On a Pixel 3 this gives an avg. lookup time of 600 ns and a memory usage
+// of 1.1 MB for 65k symbols. See go/kallsyms-parser-bench.
+size_t KernelSymbolMap::kSymIndexSampling = 16;
+size_t KernelSymbolMap::kTokenIndexSampling = 4;
+
+namespace {
+
+using TokenId = KernelSymbolMap::TokenTable::TokenId;
+constexpr size_t kSymNameMaxLen = 128;
+
+// Reads a kallsyms file in blocks of 4 pages each and decode its lines using
+// a simple FSM. Calls the passed lambda for each valid symbol.
+// It skips undefined symbols and other useless stuff.
+template <typename Lambda /* void(uint64_t, const char*) */>
+void ForEachSym(const std::string& kallsyms_path, Lambda fn) {
+ base::ScopedFile fd = base::OpenFile(kallsyms_path.c_str(), O_RDONLY);
+ if (!fd) {
+ PERFETTO_PLOG("Cannot open %s", kallsyms_path.c_str());
+ return;
+ }
+
+ // /proc/kallsyms looks as follows:
+ // 0000000000026a80 A bpf_trace_sds
+ //
+ // ffffffffc03a6000 T cpufreq_gov_powersave_init<TAB> [cpufreq_powersave]
+ // ffffffffc035d000 T cpufreq_gov_userspace_init<TAB> [cpufreq_userspace]
+ //
+ // We parse it with a state machine that has four states, one for each column.
+ // We don't care about the part in the square brackets and ignore everything
+ // after the symbol name.
+
+ static constexpr size_t kBufSize = 16 * 1024;
+ base::PagedMemory buffer = base::PagedMemory::Allocate(kBufSize);
+ enum { kSymAddr, kSymType, kSymName, kEatRestOfLine } state = kSymAddr;
+ uint64_t sym_addr = 0;
+ char sym_type = '\0';
+ char sym_name[kSymNameMaxLen + 1];
+ size_t sym_name_len = 0;
+ for (;;) {
+ char* buf = static_cast<char*>(buffer.Get());
+ auto rsize = PERFETTO_EINTR(read(*fd, buf, kBufSize));
+ if (rsize < 0) {
+ PERFETTO_PLOG("read(%s) failed", kallsyms_path.c_str());
+ return;
+ }
+ if (rsize == 0)
+ return; // EOF
+ for (size_t i = 0; i < static_cast<size_t>(rsize); i++) {
+ char c = buf[i];
+ const bool is_space = c == ' ' || c == '\t';
+ switch (state) {
+ case kSymAddr:
+ if (c >= '0' && c <= '9') {
+ sym_addr = (sym_addr << 4) | static_cast<uint8_t>(c - '0');
+ } else if (c >= 'a' && c <= 'f') {
+ sym_addr = (sym_addr << 4) | static_cast<uint8_t>(c - 'a' + 10);
+ } else if (is_space) {
+ state = kSymType;
+ } else if (c == '\0') {
+ return;
+ } else {
+ PERFETTO_ELOG("kallsyms parser error: chr 0x%x @ off=%zu", c, i);
+ return;
+ }
+ break;
+
+ case kSymType:
+ if (is_space)
+ break; // Eat leading spaces.
+ sym_type = c;
+ state = kSymName;
+ sym_name_len = 0;
+ break;
+
+ case kSymName:
+ if (is_space && sym_name_len == 0)
+ break; // Eat leading spaces.
+ if (c && c != '\n' && !is_space && sym_name_len < kSymNameMaxLen) {
+ sym_name[sym_name_len++] = c;
+ break;
+ }
+ sym_name[sym_name_len] = '\0';
+ fn(sym_addr, sym_type, sym_name);
+ sym_addr = 0;
+ sym_type = '\0';
+ state = c == '\n' ? kSymAddr : kEatRestOfLine;
+ break;
+
+ case kEatRestOfLine:
+ if (c == '\n')
+ state = kSymAddr;
+ break;
+ } // switch(state)
+ } // for (char in buf)
+ } // for (read chunk)
+}
+
+// Splits a symbol name into tokens using '_' as a separator, calling the passed
+// lambda for each token. It splits tokens in a way that allows the original
+// string to be rebuilt as-is by re-joining using a '_' between each token.
+// For instance:
+// _fo_a_b -> ["", fo, a, b]
+// __fo_a_b -> [_, fo, a, b]
+// __fo_a_b_ -> [_, fo, a, b, ""]
+// __fo_a_b____ -> [_, fo, a, b, ___]
+template <typename Lambda /* void(base::StringView) */>
+void Tokenize(const char* name, Lambda fn) {
+ const char* tok_start = name;
+ bool is_start_of_token = true;
+ bool tok_is_sep = false;
+ for (const char* ptr = name;; ptr++) {
+ const char c = *ptr;
+ if (is_start_of_token) {
+ tok_is_sep = *tok_start == '_'; // Deals with tokens made of '_'s.
+ is_start_of_token = false;
+ }
+ // Scan until either the end of string or the next character (which is a '_'
+ // in nominal cases, or anything != '_' for tokens made by 1+ '_').
+ if (c == '\0' || (!tok_is_sep && c == '_') || (tok_is_sep && c != '_')) {
+ size_t tok_len = static_cast<size_t>(ptr - tok_start);
+ if (tok_is_sep && c != '\0')
+ --tok_len;
+ fn(base::StringView(tok_start, tok_len));
+ if (c == '\0')
+ return;
+ tok_start = tok_is_sep ? ptr : ptr + 1;
+ is_start_of_token = true;
+ }
+ }
+}
+
+} // namespace
+
+KernelSymbolMap::TokenTable::TokenTable() {
+ // Insert a null token as id 0. We can't just add "" because the empty string
+ // is special-cased and doesn't insert an actual token. So we push a string of
+ // size one that contains only the null character instead.
+ char null_tok = 0;
+ Add(std::string(&null_tok, 1));
+}
+
+KernelSymbolMap::TokenTable::~TokenTable() = default;
+
+// Adds a new token to the db. Does not dedupe identical token (with the
+// exception of the empty string). The caller has to deal with that.
+// Supports only ASCII characters in the range [1, 127].
+// The last character of the token will have the MSB set.
+TokenId KernelSymbolMap::TokenTable::Add(const std::string& token) {
+ const size_t token_size = token.size();
+ if (token_size == 0)
+ return 0;
+ TokenId id = num_tokens_++;
+
+ const size_t buf_size_before_insertion = buf_.size();
+ if (id % kTokenIndexSampling == 0)
+ index_.emplace_back(buf_size_before_insertion);
+
+ const size_t prev_size = buf_.size();
+ buf_.resize(prev_size + token_size);
+ char* tok_wptr = &buf_[prev_size];
+ for (size_t i = 0; i < token_size - 1; i++) {
+ PERFETTO_DCHECK((token.at(i) & 0x80) == 0); // |token| must be ASCII only.
+ *(tok_wptr++) = token.at(i) & 0x7f;
+ }
+ *(tok_wptr++) = token.at(token_size - 1) | 0x80;
+ PERFETTO_DCHECK(tok_wptr == &buf_[buf_.size()]);
+ return id;
+}
+
+// NOTE: the caller need to mask the returned chars with 0x7f. The last char of
+// the StringView will have its MSB set (it's used as a EOF char internally).
+base::StringView KernelSymbolMap::TokenTable::Lookup(TokenId id) {
+ if (id == 0)
+ return base::StringView();
+ if (id > num_tokens_)
+ return base::StringView("<error>");
+ // We don't know precisely where the id-th token starts in the buffer. We
+ // store only one position every kTokenIndexSampling. From there, the token
+ // can be found with a linear scan of at most kTokenIndexSampling steps.
+ size_t index_off = id / kTokenIndexSampling;
+ PERFETTO_DCHECK(index_off < index_.size());
+ TokenId cur_id = static_cast<TokenId>(index_off * kTokenIndexSampling);
+ uint32_t begin = index_[index_off];
+ PERFETTO_DCHECK(begin == 0 || buf_[begin - 1] & 0x80);
+ const size_t buf_size = buf_.size();
+ for (uint32_t off = begin; off < buf_size; ++off) {
+ // Advance |off| until the end of the token (which has the MSB set).
+ if ((buf_[off] & 0x80) == 0)
+ continue;
+ if (cur_id == id)
+ return base::StringView(&buf_[begin], off - begin + 1);
+ ++cur_id;
+ begin = off + 1;
+ }
+ return base::StringView();
+}
+
+size_t KernelSymbolMap::Parse(const std::string& kallsyms_path) {
+ PERFETTO_METATRACE_SCOPED(TAG_FTRACE, KALLSYMS_PARSE);
+ using SymAddr = uint64_t;
+
+ struct TokenInfo {
+ uint32_t count = 0;
+ TokenId id = 0;
+ };
+
+ // Note if changing the container: the code below relies on stable iterators.
+ using TokenMap = std::map<std::string, TokenInfo>;
+ using TokenMapPtr = TokenMap::value_type*;
+ TokenMap tokens;
+
+ // Keep the (ordered) list of tokens for each symbol.
+ std::multimap<SymAddr, TokenMapPtr> symbols;
+
+ ForEachSym(kallsyms_path, [&](SymAddr addr, char type, const char* name) {
+ if (addr == 0 || (type != 't' && type != 'T') || name[0] == '$') {
+ return;
+ }
+
+ // Split each symbol name in tokens, using '_' as a separator (so that
+ // "foo_bar" -> ["foo", "bar"]). For each token hash:
+ // 1. Keep track of the frequency of each token.
+ // 2. Keep track of the list of token hashes for each symbol.
+ Tokenize(name, [&tokens, &symbols, addr](base::StringView token) {
+ // Strip the .cfi part if present.
+ if (token.substr(token.size() - 4) == ".cfi")
+ token = token.substr(0, token.size() - 4);
+ auto it_and_ins = tokens.emplace(token.ToStdString(), TokenInfo{});
+ it_and_ins.first->second.count++;
+ symbols.emplace(addr, &*it_and_ins.first);
+ });
+ });
+
+ // At this point we have broken down each symbol into a set of token hashes.
+ // Now generate the token ids, putting high freq tokens first, so they use
+ // only one byte to varint encode.
+
+ // This block limits the lifetime of |tokens_by_freq|.
+ {
+ std::vector<TokenMapPtr> tokens_by_freq;
+ tokens_by_freq.resize(tokens.size());
+ size_t tok_idx = 0;
+ for (auto& kv : tokens)
+ tokens_by_freq[tok_idx++] = &kv;
+
+ auto comparer = [](TokenMapPtr a, TokenMapPtr b) {
+ PERFETTO_DCHECK(a && b);
+ return b->second.count < a->second.count;
+ };
+ std::sort(tokens_by_freq.begin(), tokens_by_freq.end(), comparer);
+ for (TokenMapPtr tinfo : tokens_by_freq) {
+ tinfo->second.id = tokens_.Add(tinfo->first);
+ }
+ }
+ tokens_.shrink_to_fit();
+
+ buf_.resize(2 * 1024 * 1024); // Based on real-word observations.
+ base_addr_ = symbols.empty() ? 0 : symbols.begin()->first;
+ SymAddr prev_sym_addr = base_addr_;
+ uint8_t* wptr = buf_.data();
+
+ for (auto it = symbols.begin(); it != symbols.end();) {
+ const SymAddr sym_addr = it->first;
+
+ // Find the iterator to the first token of the next symbol (or the end).
+ auto sym_start = it;
+ auto sym_end = it;
+ while (sym_end != symbols.end() && sym_end->first == sym_addr)
+ ++sym_end;
+
+ // The range [sym_start, sym_end) has all the tokens for the current symbol.
+ uint32_t size_before = static_cast<uint32_t>(wptr - buf_.data());
+
+ // Make sure there is enough headroom to write the symbol.
+ if (buf_.size() - size_before < 1024) {
+ buf_.resize(buf_.size() + 32768);
+ wptr = buf_.data() + size_before;
+ }
+
+ uint32_t sym_rel_addr = static_cast<uint32_t>(sym_addr - base_addr_);
+ const size_t sym_num = num_syms_++;
+ if (sym_num % kSymIndexSampling == 0)
+ index_.emplace_back(std::make_pair(sym_rel_addr, size_before));
+ PERFETTO_DCHECK(sym_addr >= prev_sym_addr);
+ uint32_t delta = static_cast<uint32_t>(sym_addr - prev_sym_addr);
+ wptr = protozero::proto_utils::WriteVarInt(delta, wptr);
+ // Append all the token ids.
+ for (it = sym_start; it != sym_end;) {
+ PERFETTO_DCHECK(it->first == sym_addr);
+ TokenId token_id = it->second->second.id << 1;
+ ++it;
+ token_id |= (it == sym_end) ? 1 : 0; // Last one has LSB set to 1.
+ wptr = protozero::proto_utils::WriteVarInt(token_id, wptr);
+ }
+ prev_sym_addr = sym_addr;
+ } // for (symbols)
+
+ buf_.resize(static_cast<size_t>(wptr - buf_.data()));
+ buf_.shrink_to_fit();
+
+ PERFETTO_DLOG(
+ "Loaded %zu kalllsyms entries. Mem usage: %zu B (addresses) + %zu B "
+ "(tokens), total: %zu B",
+ num_syms_, addr_bytes(), tokens_.size_bytes(), size_bytes());
+
+ return num_syms_;
+}
+
+std::string KernelSymbolMap::Lookup(uint64_t sym_addr) {
+ if (index_.empty() || sym_addr < base_addr_)
+ return "";
+
+ // First find the highest symbol address <= sym_addr.
+ // Start with a binary search using the sparse index.
+
+ const uint32_t sym_rel_addr = static_cast<uint32_t>(sym_addr - base_addr_);
+ auto it = std::upper_bound(index_.cbegin(), index_.cend(),
+ std::make_pair(sym_rel_addr, 0u));
+ if (it != index_.cbegin())
+ --it;
+
+ // Then continue with a linear scan (of at most kSymIndexSampling steps).
+ uint32_t addr = it->first;
+ uint32_t off = it->second;
+ const uint8_t* rdptr = &buf_[off];
+ const uint8_t* const buf_end = &buf_[buf_.size()];
+ bool parsing_addr = true;
+ const uint8_t* next_rdptr = nullptr;
+ for (bool is_first_addr = true;; is_first_addr = false) {
+ uint64_t v = 0;
+ const auto* prev_rdptr = rdptr;
+ rdptr = protozero::proto_utils::ParseVarInt(rdptr, buf_end, &v);
+ if (rdptr == prev_rdptr)
+ break;
+ if (parsing_addr) {
+ addr += is_first_addr ? 0 : static_cast<uint32_t>(v);
+ parsing_addr = false;
+ if (addr > sym_rel_addr)
+ break;
+ next_rdptr = rdptr;
+ } else {
+ // This is a token. Wait for the EOF maker.
+ parsing_addr = (v & 1) == 1;
+ }
+ }
+
+ if (!next_rdptr)
+ return "";
+
+ // The address has been found. Now rejoin the tokens to form the symbol name.
+
+ rdptr = next_rdptr;
+ std::string sym_name;
+ sym_name.reserve(kSymNameMaxLen);
+ for (bool eof = false, is_first_token = true; !eof; is_first_token = false) {
+ uint64_t v = 0;
+ const auto* old = rdptr;
+ rdptr = protozero::proto_utils::ParseVarInt(rdptr, buf_end, &v);
+ if (rdptr == old)
+ break;
+ eof = v & 1;
+ base::StringView token = tokens_.Lookup(static_cast<TokenId>(v >> 1));
+ if (!is_first_token)
+ sym_name.push_back('_');
+ for (size_t i = 0; i < token.size(); i++)
+ sym_name.push_back(token.at(i) & 0x7f);
+ }
+ return sym_name;
+}
+
+} // namespace perfetto
diff --git a/src/traced/probes/ftrace/kallsyms/kernel_symbol_map.h b/src/traced/probes/ftrace/kallsyms/kernel_symbol_map.h
new file mode 100644
index 0000000..c13546a
--- /dev/null
+++ b/src/traced/probes/ftrace/kallsyms/kernel_symbol_map.h
@@ -0,0 +1,182 @@
+/*
+ * Copyright (C) 2019 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.
+ */
+
+#ifndef SRC_TRACED_PROBES_FTRACE_KALLSYMS_KERNEL_SYMBOL_MAP_H_
+#define SRC_TRACED_PROBES_FTRACE_KALLSYMS_KERNEL_SYMBOL_MAP_H_
+
+#include <stdint.h>
+#include <array>
+#include <forward_list>
+#include <vector>
+
+namespace perfetto {
+
+namespace base {
+class StringView;
+}
+
+// A parser and memory-efficient container for /proc/kallsyms.
+// It can store a full kernel symbol table in ~1.2MB of memory and perform fast
+// lookups using logarithmic binary searches + bounded linear scans.
+//
+// /proc/kallsyms is a ~10 MB text file that contains the map of kernel symbols,
+// as follows:
+// ffffff8f77682f8c t el0_sync_invalid
+// ffffff8f77683060 t el0_irq_invalid
+// ...
+// In a typipcal Android kernel, it consists of 213K lines. Out of these, only
+// 116K are interesting for the sake of symbolizing kernel functions, the rest
+// are .rodata (variables), weak or other useless symbols.
+// Still, even keeping around 116K pointers would require 116K * 8 ~= 1 MB of
+// memory, without accounting for any strings for the symbols names.
+// The SUM(str.len) for the 116K symbol names adds up to 2.7 MB (without
+// counting their addresses).
+// However consider the following:
+// - Symbol addresses are mostly contiguous. Modulo the initial KASLR loading
+// address, most symbols are few hundreds bytes apart from each other.
+// - Symbol names are made of tokens that are quite frequent (token: the result
+// of name.split('_')). If we tokenize the 2.7 MB of strings, the resulting
+// SUM(distinct_token.len) goes down 2.7MB -> 146 KB. This is because tokens
+// like "get", "set" or "event" show up thousands of times.
+// - Symbol names are ASCII strings using only 7 out of 8 bits.
+//
+// In the light of this, the in-memory architecture of this data structure is
+// as follows:
+// We keep two tables around: (1) a token table and (2) a symbol table. Both
+// table are a flat byte vector with some sparse lookaside index to make lookups
+// faster and avoid full linear scans.
+//
+// Token table
+// -----------
+// The token table is a flat char buffer. Tokens are variable size (>0). Each
+// token is identified by its ordinality, so token id 3 is the 3rd token in
+// the table. All tokens are concatenated together.
+// Given the ASCII encoding, the MSB is used as a terminator. So instead of
+// wasting an extra NUL byte for each string, the last char of each token has
+// the MSB set.
+// Furthermore, a lookaside index stores the offset of tokens (i.e. Token N
+// starts at offset O in the buffer) to allow fast lookups. In order to avoid
+// wasting too much memory, the index is sparse and track the offsets of only
+// one every kTokenIndexSamplinig tokens.
+// When looking up a token ID N, the table seeks at the offset of the closest
+// token <= N, and then scans linearly the next (at most kTokenIndexSamplinig)
+// tokens, counting the MSBs found, until the right token id is found.
+// buf: set*get*kernel*load*fpsimd*return*wrapper*el0*skip*sync*neon*bit*aes
+// ^ ^ ^
+// | | |
+// index: 0@0 4@15 8@21
+
+// Symbol table
+// ------------
+// The symbol table is a flat char buffer that stores for each symbol: its
+// address + the list of token indexes in the token table. The main caveats are
+// that:
+// - Symbol addresses are delta encoded (delta from prev symbol's addr).
+// - Both delta addresses and token indexes are var-int encoded.
+// - The LSB of token indexes is used as EOF marker (i.e. the next varint is
+// the delta-addr for the next symbol). This time the LSB is used because of
+// the varint encoding.
+// At parsing time symbols are ordered by address and tokens are sorted by
+// frequency, so that the top used 64 tokens can be represented with 1 byte.
+// (Rationale for 64: 1 byte = 8 bits. The MSB bit of each byte is used for the
+// varint encoding, the LSB bit of each number is used as end-of-tokens marker.
+// There are 6 bits left -> 64 indexes can be represented using one byte).
+// In summary the symbol table looks as follows:
+//
+// Base address: 0xbeef0000
+// Symbol buffer:
+// 0 1|0 4|0 6|1 // 0xbeef0000: 1,4,6 -> get_fpsimd_wrapper
+// 8 7|0 3|1 // 0xbeef0008: 7,3 -> el0_load
+// ...
+// Like in the case of the token table, a lookaside index keeps track of the
+// offset of one every kSymIndexSamplinig addresses.
+// The Lookup(ADDR) function operates as follows:
+// 1. Performs a logarithmic binary search in the symbols index, finding the
+// offset of the closest addres <= ADDR.
+// 2. Skip over at most kSymIndexSamplinig until the symbol is found.
+// 3. For each token index, lookup the corresponding token string and
+// concatenate them to build the symbol name.
+
+class KernelSymbolMap {
+ public:
+ // The two constants below are changeable only for the benchmark use.
+ // Trades off size of the root |index_| vs worst-case linear scans size.
+ // A higher number makes the index more sparse.
+ static size_t kSymIndexSampling;
+
+ // Trades off size of the TokenTable |index_| vs worst-case linear scans size.
+ static size_t kTokenIndexSampling;
+
+ // Parses a kallsyms file. Returns the number of valid symbols decoded.
+ size_t Parse(const std::string& kallsyms_path);
+
+ // Looks up the closest symbol (i.e. the one with the highest address <=
+ // |addr|) from its absolute 64-bit address.
+ // Returns an empty string if the symbol is not found (which can happen only
+ // if the passed |addr| is < min(addr)).
+ std::string Lookup(uint64_t addr);
+
+ // Returns the numberr of valid symbols decoded.
+ size_t num_syms() const { return num_syms_; }
+
+ // Returns the size in bytes used by the adddress table (without counting
+ // the tokens).
+ size_t addr_bytes() const { return buf_.size() + index_.size() * 8; }
+
+ // Returns the total memory usage in bytes.
+ size_t size_bytes() const { return addr_bytes() + tokens_.size_bytes(); }
+
+ // Token table.
+ class TokenTable {
+ public:
+ using TokenId = uint32_t;
+ TokenTable();
+ ~TokenTable();
+ TokenId Add(const std::string&);
+ base::StringView Lookup(TokenId);
+ size_t size_bytes() const { return buf_.size() + index_.size() * 4; }
+
+ void shrink_to_fit() {
+ buf_.shrink_to_fit();
+ index_.shrink_to_fit();
+ }
+
+ private:
+ TokenId num_tokens_ = 0;
+
+ std::vector<char> buf_; // Token buffer.
+
+ // The value i-th in the vector contains the offset (within |buf_|) of the
+ // (i * kTokenIndexSamplinig)-th token.
+ std::vector<uint32_t> index_;
+ };
+
+ private:
+ TokenTable tokens_; // Token table.
+
+ uint64_t base_addr_ = 0; // Address of the first symbol (after sorting).
+ size_t num_syms_ = 0; // Number of valid symbols stored.
+ std::vector<uint8_t> buf_; // Symbol buffer.
+
+ // The key is (address - base_addr_), the value is the byte offset in |buf_|
+ // where the symbol entry starts (i.e. the start of the varint that tells the
+ // delta from the previous symbol).
+ std::vector<std::pair<uint32_t /*rel_addr*/, uint32_t /*offset*/>> index_;
+};
+
+} // namespace perfetto
+
+#endif // SRC_TRACED_PROBES_FTRACE_KALLSYMS_KERNEL_SYMBOL_MAP_H_
diff --git a/src/traced/probes/ftrace/kallsyms/kernel_symbol_map_benchmark.cc b/src/traced/probes/ftrace/kallsyms/kernel_symbol_map_benchmark.cc
new file mode 100644
index 0000000..cdd4e38
--- /dev/null
+++ b/src/traced/probes/ftrace/kallsyms/kernel_symbol_map_benchmark.cc
@@ -0,0 +1,116 @@
+// Copyright (C) 2019 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.
+
+#include <random>
+#include <set>
+#include <unordered_set>
+
+#include <benchmark/benchmark.h>
+
+#include "perfetto/base/logging.h"
+#include "perfetto/ext/base/utils.h"
+#include "src/base/test/utils.h"
+#include "src/traced/probes/ftrace/kallsyms/kernel_symbol_map.h"
+
+namespace {
+
+bool IsBenchmarkFunctionalOnly() {
+ return getenv("BENCHMARK_FUNCTIONAL_TEST_ONLY") != nullptr;
+}
+
+void BenchmarkArgs(benchmark::internal::Benchmark* b) {
+ if (IsBenchmarkFunctionalOnly()) {
+ b->Ranges({{16, 16}, {16, 16}});
+ } else {
+ b->RangeMultiplier(2)->Ranges({{4, 512}, {4, 512}});
+ }
+}
+
+struct ExpectedSym {
+ uint64_t addr;
+ const char* name;
+};
+
+// This set of symbols has been chosen by randomly picking 40 random symbols
+// from the original kallsyms.
+ExpectedSym kExpectedSyms[] = {
+ {0xffffff8f79c0d978, "__map_memblock"},
+ {0xffffff8f78fddbb8, "smack_inode_getsecid"},
+ {0xffffff8f78fe43b4, "msm_smmu_set_attribute"},
+ {0xffffff8f79d23e20, "__initcall_41_dm_verity_init6"},
+ {0xffffff8f74206c5c, "sme_update_fast_transition_enabled"},
+ {0xffffff8f74878c8c, "tavil_hph_idle_detect_put"},
+ {0xffffff8f78fd7db0, "privileged_wrt_inode_uidgid"},
+ {0xffffff8f78ffe030, "__hrtimer_tasklet_trampoline"},
+ {0xffffff8f78fd86b0, "store_enable"},
+ {0xffffff8f78ffbcb8, "raw6_exit_net"},
+ {0xffffff8f78ffa6ec, "idProduct_show"},
+ {0xffffff8f78fd99c0, "perf_tp_event"},
+ {0xffffff8f78fe1468, "rpmh_tx_done"},
+ {0xffffff8f78fda274, "page_unlock_anon_vma_read"},
+ {0xffffff8f78ffedfc, "vmstat_period_ms_operations_open"},
+ {0xffffff8f78fe0148, "devm_gpio_request"},
+ {0xffffff8f77915028, "ctx_sched_out"},
+ {0xffffff8f77ccdc2c, "gcm_hash_crypt_remain_continue"},
+ {0xffffff8f790022ec, "loop_init"},
+ {0xffffff8f78ff0004, "pcim_release"},
+ {0xffffff8f78fe1d8c, "uart_close"},
+ {0xffffff8f78fda9d4, "pipe_lock"},
+ {0xffffff8f78e62c68, "local_bh_enable.117091"},
+ {0xffffff8f78fd918c, "fork_idle"},
+ {0xffffff8f78fe24c4, "drm_dp_downstream_debug"},
+ {0xffffff8f78ff41d0, "inet_addr_onlink"},
+ {0xffffff8f78fdf2d4, "idr_alloc"},
+ {0xffffff8f78ff073c, "fts_remove"},
+ {0xffffff8f78ffe294, "xfrm4_local_error"},
+ {0xffffff8f79001994, "cpu_feature_match_PMULL_init"},
+ {0xffffff8f78ff4740, "xfrm_state_find"},
+ {0xffffff8f78ff58b0, "inet_del_offload"},
+ {0xffffff8f742041ac, "csr_is_conn_state_connected_infra"},
+ {0xffffff8f78fe1fd4, "diag_add_client"},
+ {0xffffff8f78ffc000, "trace_raw_output_mm_vmscan_kswapd_sleep"},
+ {0xffffff8f78fe6388, "scsi_queue_insert"},
+ {0xffffff8f78fdd480, "selinux_sb_clone_mnt_opts"},
+ {0xffffff8f78fe0e9c, "clk_fixed_rate_recalc_rate"},
+ {0xffffff8f78fedaec, "cap_inode_killpriv"},
+ {0xffffff8f79002b64, "audio_amrwb_init"},
+};
+
+} // namespace
+
+static void BM_KallSyms(benchmark::State& state) {
+ perfetto::KernelSymbolMap::kTokenIndexSampling =
+ static_cast<size_t>(state.range(0));
+ perfetto::KernelSymbolMap::kSymIndexSampling =
+ static_cast<size_t>(state.range(1));
+ perfetto::KernelSymbolMap kallsyms;
+
+ // Don't run the benchmark on the CI as it requires pushing all test data,
+ // which slows down significantly the CI.
+ const bool skip = IsBenchmarkFunctionalOnly();
+ if (!skip) {
+ kallsyms.Parse(perfetto::base::GetTestDataPath("test/data/kallsyms.txt"));
+ }
+
+ for (auto _ : state) {
+ for (size_t i = 0; i < perfetto::base::ArraySize(kExpectedSyms); i++) {
+ const auto& exp = kExpectedSyms[i];
+ PERFETTO_CHECK(skip || kallsyms.Lookup(exp.addr) == exp.name);
+ }
+ }
+
+ state.counters["mem"] = kallsyms.size_bytes();
+}
+
+BENCHMARK(BM_KallSyms)->Apply(BenchmarkArgs);
diff --git a/src/traced/probes/ftrace/kallsyms/kernel_symbol_map_unittest.cc b/src/traced/probes/ftrace/kallsyms/kernel_symbol_map_unittest.cc
new file mode 100644
index 0000000..942820a
--- /dev/null
+++ b/src/traced/probes/ftrace/kallsyms/kernel_symbol_map_unittest.cc
@@ -0,0 +1,162 @@
+/*
+ * Copyright (C) 2019 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.
+ */
+
+#include "src/traced/probes/ftrace/kallsyms/kernel_symbol_map.h"
+
+#include <inttypes.h>
+
+#include <random>
+#include <unordered_map>
+
+#include "perfetto/ext/base/file_utils.h"
+#include "perfetto/ext/base/string_view.h"
+#include "perfetto/ext/base/temp_file.h"
+
+#include "test/gtest_and_gmock.h"
+
+namespace perfetto {
+namespace {
+
+using TokenId = KernelSymbolMap::TokenTable::TokenId;
+
+std::string Lookup(KernelSymbolMap::TokenTable& tokens, TokenId id) {
+ base::StringView sv = tokens.Lookup(id);
+ std::string str;
+ str.reserve(sv.size() + 1);
+ for (const char c : sv)
+ str.push_back(c & 0x7f);
+ return str;
+}
+
+TEST(KernelSymbolMapTest, TokenTable) {
+ KernelSymbolMap::TokenTable tokens;
+ ASSERT_EQ(tokens.Add("a"), 1u);
+ ASSERT_EQ(tokens.Add("bb"), 2u);
+ ASSERT_EQ(tokens.Add("ccc"), 3u);
+ ASSERT_EQ(tokens.Add("foobar"), 4u);
+ ASSERT_EQ(tokens.Add("foobaz"), 5u);
+ ASSERT_EQ(tokens.Add("_"), 6u);
+ ASSERT_EQ(Lookup(tokens, 0), "");
+ ASSERT_EQ(Lookup(tokens, 1), "a");
+ ASSERT_EQ(Lookup(tokens, 2), "bb");
+ ASSERT_EQ(Lookup(tokens, 3), "ccc");
+ ASSERT_EQ(Lookup(tokens, 4), "foobar");
+ ASSERT_EQ(Lookup(tokens, 5), "foobaz");
+ ASSERT_EQ(Lookup(tokens, 6), "_");
+ ASSERT_EQ(Lookup(tokens, 0), "");
+ ASSERT_EQ(Lookup(tokens, 42), "<error>");
+}
+
+TEST(KernelSymbolMapTest, ManyTokens) {
+ KernelSymbolMap::TokenTable tokens;
+ std::unordered_map<TokenId, std::string> tok_map;
+ static std::minstd_rand rng(0);
+ for (int rep = 0; rep < 10000; rep++) {
+ static const size_t kNameMax = 128;
+ std::string sym_name;
+ sym_name.reserve(kNameMax);
+ size_t len = 1 + (rng() % kNameMax);
+ for (size_t j = 0; j < len; j++)
+ sym_name.push_back(rng() & 0x7f);
+ TokenId id = tokens.Add(sym_name);
+ ASSERT_EQ(tok_map.count(id), 0u);
+ tok_map[id] = sym_name;
+ }
+ for (const auto& kv : tok_map) {
+ ASSERT_EQ(Lookup(tokens, kv.first), kv.second);
+ }
+}
+
+TEST(KernelSymbolMapTest, EdgeCases) {
+ base::TempFile tmp = base::TempFile::Create();
+ static const char kContents[] = R"(ffffff8f73e2fa10 t one
+ffffff8f73e2fa20 t two_
+ffffff8f73e2fa30 t _three [module_name_ignored]
+ffffff8f73e2fa40 x ignore
+ffffff8f73e2fa40 t _fo_ur_
+ffffff8f73e2fa50 t _five__.cfi
+ffffff8f73e2fa60 t __si__x__
+ffffff8f73e2fa70 t ___se___v_e__n___
+ffffff8f73e2fa80 t _eight_omg_this_name_is_so_loooooooooooooooooooooooooooooooooooong_should_be_truncated_exactly_here_because_this_is_the_128_char_TRUNCATED_HERE
+ffffff8f73e2fa90 t NiNe
+)";
+ base::WriteAll(tmp.fd(), kContents, sizeof(kContents));
+ base::FlushFile(tmp.fd());
+
+ KernelSymbolMap kallsyms;
+ EXPECT_EQ(kallsyms.Lookup(0x42), "");
+
+ kallsyms.Parse(tmp.path().c_str());
+ EXPECT_EQ(kallsyms.num_syms(), 9u);
+
+ // Test first exact lookups.
+ EXPECT_EQ(kallsyms.Lookup(0xffffff8f73e2fa10ULL), "one");
+ EXPECT_EQ(kallsyms.Lookup(0xffffff8f73e2fa20ULL), "two_");
+ EXPECT_EQ(kallsyms.Lookup(0xffffff8f73e2fa30LL), "_three");
+ EXPECT_EQ(kallsyms.Lookup(0xffffff8f73e2fa40ULL), "_fo_ur_");
+ EXPECT_EQ(kallsyms.Lookup(0xffffff8f73e2fa50ULL), "_five__");
+ EXPECT_EQ(kallsyms.Lookup(0xffffff8f73e2fa60ULL), "__si__x__");
+ EXPECT_EQ(kallsyms.Lookup(0xffffff8f73e2fa70ULL), "___se___v_e__n___");
+ EXPECT_EQ(
+ kallsyms.Lookup(0xffffff8f73e2fa80ULL),
+ "_eight_omg_this_name_is_so_loooooooooooooooooooooooooooooooooooong_"
+ "should_be_truncated_exactly_here_because_this_is_the_128_char");
+ EXPECT_EQ(kallsyms.Lookup(0xffffff8f73e2fa90ULL), "NiNe");
+
+ // Now check bound searches.
+ EXPECT_EQ(kallsyms.Lookup(0xffffff8f73e2fa00ULL), "");
+ EXPECT_EQ(kallsyms.Lookup(0xffffff8f73e2fa11ULL), "one");
+ EXPECT_EQ(kallsyms.Lookup(0xffffff8f73e2fa19ULL), "one");
+ EXPECT_EQ(kallsyms.Lookup(0xffffff8f73e2fa71ULL), "___se___v_e__n___");
+ EXPECT_EQ(kallsyms.Lookup(0xffffff8f73e2fa91ULL), "NiNe");
+ EXPECT_EQ(kallsyms.Lookup(0xffffff8fffffffffULL), "NiNe");
+}
+
+TEST(KernelSymbolMapTest, GoldenTest) {
+ std::string fake_kallsyms;
+ fake_kallsyms.reserve(8 * 1024 * 1024);
+ static std::minstd_rand rng(0);
+ static const size_t kNameMax = 64;
+ std::map<uint64_t, std::string> symbols;
+ for (int rep = 0; rep < 1000; rep++) {
+ uint64_t addr = static_cast<uint64_t>(rng());
+ if (symbols.count(addr))
+ continue;
+ static const char kCharset[] = "_abcdef";
+ char sym_name[kNameMax + 1]; // Deliberately not initialized.
+ size_t sym_name_len = 1 + (rng() % kNameMax);
+ for (size_t i = 0; i < sym_name_len; i++)
+ sym_name[i] = kCharset[rng() % strlen(kCharset)];
+ sym_name[sym_name_len] = '\0';
+ char line[kNameMax + 40];
+ sprintf(line, "%" PRIx64 " t %s\n", addr, sym_name);
+ symbols[addr] = sym_name;
+ fake_kallsyms += line;
+ }
+ base::TempFile tmp = base::TempFile::Create();
+ base::WriteAll(tmp.fd(), fake_kallsyms.data(), fake_kallsyms.size());
+ base::FlushFile(tmp.fd());
+
+ KernelSymbolMap kallsyms;
+ kallsyms.Parse(tmp.path().c_str());
+ ASSERT_EQ(kallsyms.num_syms(), symbols.size());
+ for (const auto& kv : symbols) {
+ ASSERT_EQ(kallsyms.Lookup(kv.first), kv.second);
+ }
+}
+
+} // namespace
+} // namespace perfetto
diff --git a/src/traced/probes/ftrace/proto_translation_table.cc b/src/traced/probes/ftrace/proto_translation_table.cc
index 86c61f0..ceb0973 100644
--- a/src/traced/probes/ftrace/proto_translation_table.cc
+++ b/src/traced/probes/ftrace/proto_translation_table.cc
@@ -521,12 +521,12 @@
group_to_events_[e->group].push_back(&events_.at(e->ftrace_event_id));
return e;
-};
+}
const char* ProtoTranslationTable::InternString(const std::string& str) {
auto it_and_inserted = interned_strings_.insert(str);
return it_and_inserted.first->c_str();
-};
+}
uint16_t ProtoTranslationTable::CreateGenericEventField(
const FtraceEvent::Field& ftrace_field,
diff --git a/src/traced/probes/ftrace/test/test_messages.proto b/src/traced/probes/ftrace/test/test_messages.proto
index 5118d62..1e6ece4 100644
--- a/src/traced/probes/ftrace/test/test_messages.proto
+++ b/src/traced/probes/ftrace/test/test_messages.proto
@@ -15,7 +15,6 @@
*/
syntax = "proto2";
-option optimize_for = LITE_RUNTIME;
message FakeFtraceEvent {
optional uint32 common_field = 1;
diff --git a/src/traced/probes/metatrace/BUILD.gn b/src/traced/probes/metatrace/BUILD.gn
index 489b85a..c53789b 100644
--- a/src/traced/probes/metatrace/BUILD.gn
+++ b/src/traced/probes/metatrace/BUILD.gn
@@ -14,15 +14,17 @@
source_set("metatrace") {
public_deps = [
- "../../../tracing",
+ "../../../tracing/core",
+ "../../../tracing/core:service",
]
deps = [
"..:data_source",
"../../../../gn:default_deps",
"../../../../include/perfetto/ext/traced",
+ "../../../../protos/perfetto/trace:zero",
"../../../../protos/perfetto/trace/perfetto:zero",
"../../../base",
- "../../../tracing",
+ "../../../tracing/core",
]
sources = [
"metatrace_data_source.cc",
diff --git a/src/traced/probes/packages_list/BUILD.gn b/src/traced/probes/packages_list/BUILD.gn
index eaee21d..0f17596 100644
--- a/src/traced/probes/packages_list/BUILD.gn
+++ b/src/traced/probes/packages_list/BUILD.gn
@@ -15,15 +15,14 @@
import("../../../../gn/test.gni")
source_set("packages_list") {
- public_deps = [
- "../../../tracing",
- ]
+ public_deps = [ "../../../tracing/core" ]
deps = [
"..:data_source",
"../../../../gn:default_deps",
"../../../../include/perfetto/ext/traced",
"../../../../protos/perfetto/common:zero",
"../../../../protos/perfetto/config/android:zero",
+ "../../../../protos/perfetto/trace:zero",
"../../../../protos/perfetto/trace/android:zero",
"../../../base",
]
@@ -42,9 +41,7 @@
"../../../../protos/perfetto/trace/android:cpp",
"../../../../protos/perfetto/trace/android:zero",
"../../../../src/base:test_support",
- "../../../../src/tracing:test_support",
+ "../../../../src/tracing/test:test_support",
]
- sources = [
- "packages_list_data_source_unittest.cc",
- ]
+ sources = [ "packages_list_data_source_unittest.cc" ]
}
diff --git a/src/traced/probes/power/BUILD.gn b/src/traced/probes/power/BUILD.gn
index d3af4a3..7b75c6a 100644
--- a/src/traced/probes/power/BUILD.gn
+++ b/src/traced/probes/power/BUILD.gn
@@ -13,14 +13,13 @@
# limitations under the License.
source_set("power") {
- public_deps = [
- "../../../tracing",
- ]
+ public_deps = [ "../../../tracing/core" ]
deps = [
"..:data_source",
"../../../../gn:default_deps",
"../../../../include/perfetto/ext/traced",
"../../../../protos/perfetto/config/power:zero",
+ "../../../../protos/perfetto/trace:zero",
"../../../../protos/perfetto/trace/power:zero",
"../../../android_internal:lazy_library_loader",
"../../../base",
diff --git a/src/traced/probes/ps/BUILD.gn b/src/traced/probes/ps/BUILD.gn
index 85c24bc..d373ba3 100644
--- a/src/traced/probes/ps/BUILD.gn
+++ b/src/traced/probes/ps/BUILD.gn
@@ -15,14 +15,13 @@
import("../../../../gn/test.gni")
source_set("ps") {
- public_deps = [
- "../../../tracing",
- ]
+ public_deps = [ "../../../tracing/core" ]
deps = [
"..:data_source",
"../../../../gn:default_deps",
"../../../../include/perfetto/ext/traced",
"../../../../protos/perfetto/config/process_stats:zero",
+ "../../../../protos/perfetto/trace:zero",
"../../../../protos/perfetto/trace/ps:zero",
"../../../base",
]
@@ -41,9 +40,7 @@
"../../../../protos/perfetto/config/process_stats:cpp",
"../../../../protos/perfetto/trace/ps:cpp",
"../../../../src/base:test_support",
- "../../../../src/tracing:test_support",
+ "../../../../src/tracing/test:test_support",
]
- sources = [
- "process_stats_data_source_unittest.cc",
- ]
+ sources = [ "process_stats_data_source_unittest.cc" ]
}
diff --git a/src/traced/probes/ps/process_stats_data_source.cc b/src/traced/probes/ps/process_stats_data_source.cc
index fe73990..511aa23 100644
--- a/src/traced/probes/ps/process_stats_data_source.cc
+++ b/src/traced/probes/ps/process_stats_data_source.cc
@@ -241,6 +241,10 @@
std::string cmdline = ReadProcPidFile(pid, "cmdline");
if (!cmdline.empty()) {
+ if (cmdline.back() != '\0') {
+ // Some kernels can miss the NUL terminator due to a bug. b/147438623.
+ cmdline.push_back('\0');
+ }
using base::StringSplitter;
for (StringSplitter ss(&cmdline[0], cmdline.size(), '\0'); ss.Next();)
proc->add_cmdline(ss.cur_token());
diff --git a/src/traced/probes/ps/process_stats_data_source.h b/src/traced/probes/ps/process_stats_data_source.h
index 04c683e..100ef62 100644
--- a/src/traced/probes/ps/process_stats_data_source.h
+++ b/src/traced/probes/ps/process_stats_data_source.h
@@ -23,7 +23,7 @@
#include <unordered_map>
#include <vector>
-#include "perfetto/ext/base/flat_set.h"
+#include "perfetto/base/flat_set.h"
#include "perfetto/ext/base/scoped_file.h"
#include "perfetto/ext/base/weak_ptr.h"
#include "perfetto/ext/tracing/core/basic_types.h"
diff --git a/src/traced/probes/ps/process_stats_data_source_unittest.cc b/src/traced/probes/ps/process_stats_data_source_unittest.cc
index 532a27e..e3e4b9d 100644
--- a/src/traced/probes/ps/process_stats_data_source_unittest.cc
+++ b/src/traced/probes/ps/process_stats_data_source_unittest.cc
@@ -91,6 +91,25 @@
ASSERT_THAT(first_process.cmdline(), ElementsAreArray({"foo", "bar", "baz"}));
}
+// Regression test for b/147438623.
+TEST_F(ProcessStatsDataSourceTest, NonNulTerminatedCmdline) {
+ auto data_source = GetProcessStatsDataSource(DataSourceConfig());
+ EXPECT_CALL(*data_source, ReadProcPidFile(42, "status"))
+ .WillOnce(Return(
+ "Name: foo\nTgid:\t42\nPid: 42\nPPid: 17\nUid: 43 44 45 56\n"));
+ EXPECT_CALL(*data_source, ReadProcPidFile(42, "cmdline"))
+ .WillOnce(Return(std::string("surfaceflinger", 14)));
+
+ data_source->OnPids({42});
+
+ auto trace = writer_raw_->GetAllTracePackets();
+ ASSERT_EQ(trace.size(), 1u);
+ auto ps_tree = trace[0].process_tree();
+ ASSERT_EQ(ps_tree.processes_size(), 1);
+ auto first_process = ps_tree.processes()[0];
+ ASSERT_THAT(first_process.cmdline(), ElementsAreArray({"surfaceflinger"}));
+}
+
TEST_F(ProcessStatsDataSourceTest, DontRescanCachedPIDsAndTIDs) {
// assertion helpers
auto expected_process = [](int pid) {
diff --git a/src/traced/probes/sys_stats/BUILD.gn b/src/traced/probes/sys_stats/BUILD.gn
index efea7a9..9c02da8 100644
--- a/src/traced/probes/sys_stats/BUILD.gn
+++ b/src/traced/probes/sys_stats/BUILD.gn
@@ -15,9 +15,7 @@
import("../../../../gn/test.gni")
source_set("sys_stats") {
- public_deps = [
- "../../../tracing",
- ]
+ public_deps = [ "../../../tracing/core" ]
deps = [
"..:data_source",
"../../../../gn:default_deps",
@@ -25,6 +23,7 @@
"../../../../include/perfetto/ext/traced:sys_stats_counters",
"../../../../protos/perfetto/common:zero",
"../../../../protos/perfetto/config/sys_stats:zero",
+ "../../../../protos/perfetto/trace:zero",
"../../../../protos/perfetto/trace/sys_stats:zero",
"../../../base",
]
@@ -43,9 +42,7 @@
"../../../../protos/perfetto/config/sys_stats:cpp",
"../../../../protos/perfetto/trace/sys_stats:cpp",
"../../../../src/base:test_support",
- "../../../../src/tracing:test_support",
+ "../../../../src/tracing/test:test_support",
]
- sources = [
- "sys_stats_data_source_unittest.cc",
- ]
+ sources = [ "sys_stats_data_source_unittest.cc" ]
}
diff --git a/src/traced/service/BUILD.gn b/src/traced/service/BUILD.gn
index 340d3fa..2b7798b 100644
--- a/src/traced/service/BUILD.gn
+++ b/src/traced/service/BUILD.gn
@@ -27,23 +27,20 @@
"../../../gn:default_deps",
"../../../include/perfetto/ext/traced",
]
- sources = [
- "main.cc",
- ]
+ sources = [ "main.cc" ]
assert_no_deps = [ "//gn:protobuf_lite" ]
}
# Contains all the implementation but not the main() entry point. This target
# is shared both by the executable and tests.
source_set("service") {
- public_deps = [
- "../../../include/perfetto/ext/traced",
- ]
+ public_deps = [ "../../../include/perfetto/ext/traced" ]
deps = [
"../../../gn:default_deps",
"../../base",
- "../../tracing",
- "../../tracing:ipc",
+ "../../tracing/core",
+ "../../tracing/core:service",
+ "../../tracing/ipc/service",
]
if (enable_perfetto_version_gen) {
deps += [ "//gn/standalone:gen_git_revision" ]
@@ -63,9 +60,7 @@
"../../../gn:gtest_and_gmock",
"../../base",
"../../base:test_support",
- "../../tracing",
+ "../../tracing/core",
]
- sources = [
- "builtin_producer_unittest.cc",
- ]
+ sources = [ "builtin_producer_unittest.cc" ]
}
diff --git a/src/tracing/BUILD.gn b/src/tracing/BUILD.gn
index aa7c6f6..936eb2d 100644
--- a/src/tracing/BUILD.gn
+++ b/src/tracing/BUILD.gn
@@ -17,184 +17,51 @@
import("../../gn/perfetto.gni")
import("../../gn/test.gni")
-# Core tracing library, platform independent, no transport layer.
-source_set("tracing") {
+# Full version of the client API. Supports both the in-process backend and the
+# system backend (on posix systems and if enabled by the enable_perfetto_ipc).
+# It has a larger binary footprint due to the service code for the in-proecss
+# backend.
+group("client_api") {
public_deps = [
- ":common",
- "../../include/perfetto/ext/tracing/core",
- "../../protos/perfetto/trace:zero",
- "../../protos/perfetto/trace/interned_data:zero",
- "../../protos/perfetto/trace/track_event:zero",
- ]
- deps = [
+ ":client_api_base",
"../../gn:default_deps",
- "../../include/perfetto/tracing",
- "../../protos/perfetto/common:zero",
- "../../protos/perfetto/config:zero",
- "../../protos/perfetto/trace/perfetto:zero", # For MetatraceWriter.
- "../base",
- "../protozero",
]
- sources = [
- "core/id_allocator.cc",
- "core/id_allocator.h",
- "core/metatrace_writer.cc",
- "core/metatrace_writer.h",
- "core/null_trace_writer.cc",
- "core/null_trace_writer.h",
- "core/packet_stream_validator.cc",
- "core/packet_stream_validator.h",
- "core/patch_list.h",
- "core/shared_memory_abi.cc",
- "core/shared_memory_arbiter_impl.cc",
- "core/shared_memory_arbiter_impl.h",
- "core/startup_trace_writer.cc",
- "core/startup_trace_writer_registry.cc",
- "core/trace_buffer.cc",
- "core/trace_buffer.h",
- "core/trace_packet.cc",
- "core/trace_writer_impl.cc",
- "core/trace_writer_impl.h",
- "core/tracing_service_impl.cc",
- "core/tracing_service_impl.h",
- "core/virtual_destructors.cc",
- ]
-}
-
-perfetto_unittest_source_set("unittests") {
- testonly = true
- deps = [
- ":test_support",
- ":tracing",
- "../../gn:default_deps",
- "../../gn:gtest_and_gmock",
- "../../protos/perfetto/trace:cpp",
- "../../protos/perfetto/trace:zero",
- "../../protos/perfetto/trace/ftrace:cpp",
- "../base",
- "../base:test_support",
- ]
- sources = [
- "core/id_allocator_unittest.cc",
- "core/null_trace_writer_unittest.cc",
- "core/packet_stream_validator_unittest.cc",
- "core/patch_list_unittest.cc",
- "core/shared_memory_abi_unittest.cc",
- "core/trace_buffer_unittest.cc",
- "core/trace_packet_unittest.cc",
- "test/aligned_buffer_test.cc",
- "test/aligned_buffer_test.h",
- "test/fake_packet.cc",
- "test/fake_packet.h",
- "test/test_shared_memory.cc",
- "test/test_shared_memory.h",
- ]
-
+ deps = [ ":in_process_backend" ]
if (enable_perfetto_ipc) {
- deps += [ ":ipc" ]
- sources += [
- "ipc/posix_shared_memory_unittest.cc",
- "test/tracing_integration_test.cc",
- ]
- }
-
- # These tests rely on test_task_runner.h which
- # has no Windows implementation.
- if (!is_win) {
- sources += [
- "core/shared_memory_arbiter_impl_unittest.cc",
- "core/startup_trace_writer_unittest.cc",
- "core/trace_writer_impl_unittest.cc",
- "core/tracing_service_impl_unittest.cc",
- "test/fake_producer_endpoint.h",
- "test/mock_consumer.cc",
- "test/mock_consumer.h",
- "test/mock_producer.cc",
- "test/mock_producer.h",
- ]
+ deps += [ ":system_process_backend" ]
+ } else {
+ deps += [ ":system_process_backend_fake" ]
}
}
-source_set("test_support") {
- testonly = true
- public_deps = [
- "../../include/perfetto/ext/tracing/core",
- "../../protos/perfetto/trace:cpp",
- "../../protos/perfetto/trace:zero",
- "../protozero",
- ]
- sources = [
- "core/trace_writer_for_testing.cc",
- "core/trace_writer_for_testing.h",
- ]
-}
-
-if (perfetto_build_standalone || perfetto_build_with_android) {
- executable("consumer_api_test") {
- testonly = true
- deps = [
- ":consumer_api_deprecated",
- "../../gn:default_deps",
- "../../include/perfetto/public",
- "../../protos/perfetto/config:cpp",
- "../../protos/perfetto/config/ftrace:cpp",
- "../../protos/perfetto/trace:cpp",
- "../../protos/perfetto/trace/ftrace:cpp",
- "../base",
- ]
- sources = [
- "api_impl/consumer_api_test.cc",
- ]
- }
-
- # Imlementation of the public-facing consumer API in libperfetto.so (only for
- # Android builds).
- # TODO(primiano): remove this. This is a legacy and deprecated API. The only
- # uses should be moved to the perfetto Client API.
- source_set("consumer_api_deprecated") {
- deps = [
- ":ipc",
- ":tracing",
- "../../gn:default_deps",
- "../../include/perfetto/public",
- "../../protos/perfetto/config:cpp",
- "../base",
- ]
- sources = [
- "api_impl/consumer_api.cc",
- ]
- }
-}
-
+# Slim version of the client API. Works only with the system backend (traced
+# connection over a UNIX socket). Has a lighter binary size impact.
if (enable_perfetto_ipc) {
- # Posix specialization of the tracing library for Linux / Android / Mac.
- # Provides an IPC transport over a UNIX domain socket.
- source_set("ipc") {
+ source_set("client_api_system_backend_only") {
public_deps = [
- "../../include/perfetto/ext/tracing/core",
- "../../include/perfetto/ext/tracing/ipc",
- ]
- sources = [
- "ipc/consumer/consumer_ipc_client_impl.cc",
- "ipc/consumer/consumer_ipc_client_impl.h",
- "ipc/default_socket.cc",
- "ipc/posix_shared_memory.cc",
- "ipc/posix_shared_memory.h",
- "ipc/producer/producer_ipc_client_impl.cc",
- "ipc/producer/producer_ipc_client_impl.h",
- "ipc/service/consumer_ipc_service.cc",
- "ipc/service/consumer_ipc_service.h",
- "ipc/service/producer_ipc_service.cc",
- "ipc/service/producer_ipc_service.h",
- "ipc/service/service_ipc_host_impl.cc",
- "ipc/service/service_ipc_host_impl.h",
+ ":client_api_base",
+ "../../gn:default_deps",
]
deps = [
- ":tracing",
+ ":in_process_backend_fake",
+ ":system_process_backend",
+ ]
+ }
+}
+
+# This target checks only that the "fake" backends compile. This is to detect
+# early if we break them with refactorings, without waiting for TreeHugger or
+# rolls into chromium.
+if (perfetto_build_standalone) {
+ shared_library("client_api_no_backends_compile_test") {
+ public_deps = [
+ ":client_api_base",
"../../gn:default_deps",
- "../../protos/perfetto/ipc",
- "../base",
- "../ipc",
+ ]
+ deps = [
+ ":in_process_backend_fake",
+ ":platform_fake",
+ ":system_process_backend_fake",
]
}
}
@@ -207,12 +74,20 @@
"../../include/perfetto/tracing",
"../base",
]
- sources = [
- "platform_posix.cc",
- ]
+ sources = [ "platform_posix.cc" ]
}
}
+# Fake platform that allows buiding the client lib on all OSes. You can only use
+# those parts of the client lib that do not use the platform.
+source_set("platform_fake") {
+ deps = [
+ "../../gn:default_deps",
+ "../../include/perfetto/tracing",
+ ]
+ sources = [ "platform_fake.cc" ]
+}
+
# Code that both public headers and other non-public sources (e.g.
# src/tracing/core) need to depend on. It cannot be in the root :tracing target
# otherwise there would be a cyclic dependency because public itself needs to
@@ -222,18 +97,16 @@
"../../gn:default_deps",
"../../include/perfetto/tracing",
]
- sources = [
- "trace_writer_base.cc",
- ]
+ sources = [ "trace_writer_base.cc" ]
}
-source_set("client_api") {
+# Base target for the client API. On its own doesn't provide any backend.
+source_set("client_api_base") {
deps = [
- ":common",
"../../include/perfetto/tracing/core",
"../../protos/perfetto/config:cpp",
"../base",
- "../tracing",
+ "core",
]
public_deps = [
"../../gn:default_deps",
@@ -243,78 +116,70 @@
"data_source.cc",
"debug_annotation.cc",
"event_context.cc",
- "internal/in_process_tracing_backend.cc",
"internal/in_process_tracing_backend.h",
+ "internal/system_tracing_backend.h",
"internal/tracing_muxer_impl.cc",
"internal/tracing_muxer_impl.h",
"internal/track_event_internal.cc",
"platform.cc",
"tracing.cc",
+ "track.cc",
"track_event_category_registry.cc",
"virtual_destructors.cc",
]
-
- if (enable_perfetto_ipc) {
- deps += [ ":ipc" ]
- sources += [
- "internal/system_tracing_backend.cc",
- "internal/system_tracing_backend.h",
- ]
- }
}
-if (enable_perfetto_integration_tests) {
- source_set("client_api_integrationtests") {
- testonly = true
+# System backend: connects to an external "traced" instance via a UNIX socket.
+# Requires the IPC layer and is supported only on posix systems.
+if (enable_perfetto_ipc) {
+ source_set("system_process_backend") {
+ public_deps = [ "../../include/perfetto/tracing" ]
deps = [
- ":client_api",
- ":platform_posix",
- "../../:libperfetto_client_experimental",
+ ":client_api_base",
"../../gn:default_deps",
- "../../gn:gtest_and_gmock",
"../../include/perfetto/tracing/core",
- "../../protos/perfetto/trace:cpp",
- "../../protos/perfetto/trace:zero",
- "../../protos/perfetto/trace/interned_data:cpp",
- "../../protos/perfetto/trace/interned_data:zero",
- "../../protos/perfetto/trace/profiling:cpp",
- "../../protos/perfetto/trace/track_event:cpp",
"../base",
- "test:api_test_support",
+ "ipc/consumer",
+ "ipc/producer",
+ "ipc/service",
]
- sources = [
- "api_integrationtest.cc",
- "test/tracing_module.cc",
- "test/tracing_module.h",
- "test/tracing_module2.cc",
- "test/tracing_module_categories.h",
- ]
+ sources = [ "internal/system_tracing_backend.cc" ]
}
}
-if (enable_perfetto_benchmarks) {
- source_set("benchmarks") {
- testonly = true
- deps = [
- ":tracing",
- "../../../../gn:benchmark",
- "../../../../gn:default_deps",
- "../../protos/perfetto/trace:zero",
- "../../protos/perfetto/trace/ftrace:zero",
- "../protozero",
- ]
- sources = [
- "core/packet_stream_validator_benchmark.cc",
- ]
- }
-}
-
-perfetto_fuzzer_test("packet_stream_validator_fuzzer") {
- sources = [
- "core/packet_stream_validator_fuzzer.cc",
- ]
+# System backend fallback: it prints an error message and returns nullptr.
+source_set("system_process_backend_fake") {
+ public_deps = [ "../../include/perfetto/tracing" ]
deps = [
- ":tracing",
- "../../../../gn:default_deps",
+ ":client_api_base",
+ "../../gn:default_deps",
+ "../base",
]
+ sources = [ "internal/system_tracing_backend_fake.cc" ]
+}
+
+# In-process backend: starts the tracing service in-process on a dedicated
+# thread. It depends only on having a valid "platform" target. It has a larger
+# binary size cost because links in all the service code.
+source_set("in_process_backend") {
+ public_deps = [ "../../include/perfetto/tracing" ]
+ deps = [
+ ":client_api_base",
+ "../../gn:default_deps",
+ "../../include/perfetto/tracing/core",
+ "../base",
+ "core:service",
+ ]
+ sources = [ "internal/in_process_tracing_backend.cc" ]
+}
+
+# In-process backend fallback: it prints an error messaage and returns nullptr.
+source_set("in_process_backend_fake") {
+ public_deps = [ "../../include/perfetto/tracing" ]
+ deps = [
+ ":client_api_base",
+ "../../gn:default_deps",
+ "../base",
+ ]
+ sources = [ "internal/in_process_tracing_backend_fake.cc" ]
}
diff --git a/src/tracing/consumer_api_deprecated/BUILD.gn b/src/tracing/consumer_api_deprecated/BUILD.gn
new file mode 100644
index 0000000..1889e41
--- /dev/null
+++ b/src/tracing/consumer_api_deprecated/BUILD.gn
@@ -0,0 +1,50 @@
+# Copyright (C) 2020 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.
+
+# Imlementation of the public-facing consumer API in libperfetto.so (only for
+# Android builds).
+# TODO(primiano): remove this. This is a legacy and deprecated API. The only
+# user is iorap which should be moved to the perfetto Client API.
+
+import("../../../gn/perfetto.gni")
+import("../../../gn/test.gni")
+
+assert(perfetto_build_standalone || perfetto_build_with_android)
+
+source_set("consumer_api_deprecated") {
+ deps = [
+ "../../../gn:default_deps",
+ "../../../include/perfetto/public",
+ "../../../protos/perfetto/config:cpp",
+ "../../base",
+ "../core",
+ "../ipc/consumer",
+ ]
+ sources = [ "consumer_api_deprecated.cc" ]
+}
+
+executable("consumer_api_test") {
+ testonly = true
+ deps = [
+ ":consumer_api_deprecated",
+ "../../../gn:default_deps",
+ "../../../include/perfetto/public",
+ "../../../protos/perfetto/config:cpp",
+ "../../../protos/perfetto/config/ftrace:cpp",
+ "../../../protos/perfetto/trace:cpp",
+ "../../../protos/perfetto/trace/ftrace:cpp",
+ "../../base",
+ ]
+ sources = [ "consumer_api_deprecated_test.cc" ]
+}
diff --git a/src/tracing/api_impl/consumer_api.cc b/src/tracing/consumer_api_deprecated/consumer_api_deprecated.cc
similarity index 100%
rename from src/tracing/api_impl/consumer_api.cc
rename to src/tracing/consumer_api_deprecated/consumer_api_deprecated.cc
diff --git a/src/tracing/api_impl/consumer_api_test.cc b/src/tracing/consumer_api_deprecated/consumer_api_deprecated_test.cc
similarity index 100%
rename from src/tracing/api_impl/consumer_api_test.cc
rename to src/tracing/consumer_api_deprecated/consumer_api_deprecated_test.cc
diff --git a/src/tracing/core/BUILD.gn b/src/tracing/core/BUILD.gn
new file mode 100644
index 0000000..df17b7d
--- /dev/null
+++ b/src/tracing/core/BUILD.gn
@@ -0,0 +1,150 @@
+# Copyright (C) 2020 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.
+
+import("../../../gn/fuzzer.gni")
+import("../../../gn/perfetto.gni")
+import("../../../gn/test.gni")
+
+# Core tracing library, platform independent, no IPC layer, no service.
+source_set("core") {
+ public_deps = [
+ "../../../include/perfetto/ext/tracing/core",
+ "../../protozero",
+ ]
+ deps = [
+ "..:common",
+ "../../../gn:default_deps",
+ "../../../include/perfetto/tracing",
+ "../../../protos/perfetto/trace:zero",
+ "../../base",
+ ]
+ sources = [
+ "id_allocator.cc",
+ "id_allocator.h",
+ "null_trace_writer.cc",
+ "null_trace_writer.h",
+ "patch_list.h",
+ "shared_memory_abi.cc",
+ "shared_memory_arbiter_impl.cc",
+ "shared_memory_arbiter_impl.h",
+ "startup_trace_writer.cc",
+ "startup_trace_writer_registry.cc",
+ "trace_packet.cc",
+ "trace_writer_impl.cc",
+ "trace_writer_impl.h",
+ "virtual_destructors.cc",
+ ]
+}
+
+source_set("service") {
+ public_deps = [
+ "..:common",
+ "../../../include/perfetto/ext/base",
+ "../../../include/perfetto/ext/tracing/core",
+ ]
+ deps = [
+ ":core",
+ "../../../gn:default_deps",
+ "../../../include/perfetto/tracing",
+ "../../../protos/perfetto/common:zero",
+ "../../../protos/perfetto/config:zero",
+ "../../../protos/perfetto/trace:zero",
+ "../../../protos/perfetto/trace/perfetto:zero", # For MetatraceWriter.
+ "../../base",
+ ]
+ sources = [
+ "metatrace_writer.cc",
+ "metatrace_writer.h",
+ "packet_stream_validator.cc",
+ "packet_stream_validator.h",
+ "trace_buffer.cc",
+ "trace_buffer.h",
+ "tracing_service_impl.cc",
+ "tracing_service_impl.h",
+ ]
+}
+
+perfetto_unittest_source_set("unittests") {
+ testonly = true
+ deps = [
+ ":core",
+ ":service",
+ "../../../gn:default_deps",
+ "../../../gn:gtest_and_gmock",
+ "../../../protos/perfetto/trace:cpp",
+ "../../../protos/perfetto/trace:zero",
+ "../../../protos/perfetto/trace/ftrace:cpp",
+ "../../base",
+ "../../base:test_support",
+ "../test:test_support",
+ ]
+ sources = [
+ "id_allocator_unittest.cc",
+ "null_trace_writer_unittest.cc",
+ "packet_stream_validator_unittest.cc",
+ "patch_list_unittest.cc",
+ "shared_memory_abi_unittest.cc",
+ "trace_buffer_unittest.cc",
+ "trace_packet_unittest.cc",
+ ]
+
+ # These tests rely on test_task_runner.h which
+ # has no Windows implementation.
+ if (!is_win) {
+ sources += [
+ "shared_memory_arbiter_impl_unittest.cc",
+ "startup_trace_writer_unittest.cc",
+ "trace_writer_impl_unittest.cc",
+ "tracing_service_impl_unittest.cc",
+ ]
+ }
+}
+
+perfetto_unittest_source_set("test_support") {
+ testonly = true
+ public_deps = [
+ "../../../include/perfetto/ext/tracing/core",
+ "../../../protos/perfetto/trace:cpp",
+ "../../../protos/perfetto/trace:zero",
+ "../../protozero",
+ ]
+ sources = [
+ "trace_writer_for_testing.cc",
+ "trace_writer_for_testing.h",
+ ]
+}
+
+if (enable_perfetto_benchmarks) {
+ source_set("benchmarks") {
+ testonly = true
+ deps = [
+ ":core",
+ ":service",
+ "../../../../../gn:benchmark",
+ "../../../../../gn:default_deps",
+ "../../../protos/perfetto/trace:zero",
+ "../../../protos/perfetto/trace/ftrace:zero",
+ "../../protozero",
+ ]
+ sources = [ "packet_stream_validator_benchmark.cc" ]
+ }
+}
+
+perfetto_fuzzer_test("packet_stream_validator_fuzzer") {
+ sources = [ "packet_stream_validator_fuzzer.cc" ]
+ deps = [
+ ":service",
+ "../../../../../gn:default_deps",
+ ]
+}
diff --git a/src/tracing/core/shared_memory_arbiter_impl_unittest.cc b/src/tracing/core/shared_memory_arbiter_impl_unittest.cc
index 91bd5db..036a8a3 100644
--- a/src/tracing/core/shared_memory_arbiter_impl_unittest.cc
+++ b/src/tracing/core/shared_memory_arbiter_impl_unittest.cc
@@ -50,7 +50,7 @@
BufferExhaustedPolicy) override {
return nullptr;
}
- SharedMemoryArbiter* GetInProcessShmemArbiter() override { return nullptr; }
+ SharedMemoryArbiter* MaybeSharedMemoryArbiter() override { return nullptr; }
MOCK_METHOD2(CommitData, void(const CommitDataRequest&, CommitDataCallback));
MOCK_METHOD2(RegisterTraceWriter, void(uint32_t, uint32_t));
diff --git a/src/tracing/core/tracing_service_impl.cc b/src/tracing/core/tracing_service_impl.cc
index f40606f..24e8a0b 100644
--- a/src/tracing/core/tracing_service_impl.cc
+++ b/src/tracing/core/tracing_service_impl.cc
@@ -25,7 +25,8 @@
#include <regex>
#include <unordered_set>
-#if !PERFETTO_BUILDFLAG(PERFETTO_OS_WIN)
+#if !PERFETTO_BUILDFLAG(PERFETTO_OS_WIN) && \
+ !PERFETTO_BUILDFLAG(PERFETTO_OS_NACL)
#include <sys/uio.h>
#include <sys/utsname.h>
#include <unistd.h>
@@ -76,6 +77,7 @@
constexpr base::TimeMillis kSnapshotsInterval(10 * 1000);
constexpr int kDefaultWriteIntoFilePeriodMs = 5000;
constexpr int kMaxConcurrentTracingSessions = 15;
+constexpr int kMaxConcurrentTracingSessionsPerUid = 5;
constexpr int64_t kMinSecondsBetweenTracesGuardrail = 5 * 60;
constexpr uint32_t kMillisPerHour = 3600000;
@@ -85,7 +87,7 @@
constexpr uint32_t kGuardrailsMaxTracingBufferSizeKb = 128 * 1024;
constexpr uint32_t kGuardrailsMaxTracingDurationMillis = 24 * kMillisPerHour;
-#if PERFETTO_BUILDFLAG(PERFETTO_OS_WIN)
+#if PERFETTO_BUILDFLAG(PERFETTO_OS_WIN) || PERFETTO_BUILDFLAG(PERFETTO_OS_NACL)
struct iovec {
void* iov_base; // Address
size_t iov_len; // Block size
@@ -114,7 +116,8 @@
uid_t geteuid() {
return 0;
}
-#endif // PERFETTO_BUILDFLAG(PERFETTO_OS_WIN)
+#endif // PERFETTO_BUILDFLAG(PERFETTO_OS_WIN) ||
+ // PERFETTO_BUILDFLAG(PERFETTO_OS_NACL)
// Partially encodes a CommitDataRequest in an int32 for the purposes of
// metatracing. Note that it encodes only the bottom 10 bits of the producer id
@@ -466,6 +469,17 @@
}
}
+ const long sessions_for_uid = std::count_if(
+ tracing_sessions_.begin(), tracing_sessions_.end(),
+ [consumer](const decltype(tracing_sessions_)::value_type& s) {
+ return s.second.consumer_uid == consumer->uid_;
+ });
+ if (sessions_for_uid >= kMaxConcurrentTracingSessionsPerUid) {
+ PERFETTO_ELOG("Too many concurrent tracing sesions (%ld) for uid %d",
+ sessions_for_uid, static_cast<int>(consumer->uid_));
+ return false;
+ }
+
// TODO(primiano): This is a workaround to prevent that a producer gets stuck
// in a state where it stalls by design by having more TraceWriterImpl
// instances than free pages in the buffer. This is really a bug in
@@ -2223,7 +2237,8 @@
auto* clock_snapshot = packet->set_clock_snapshot();
#if !PERFETTO_BUILDFLAG(PERFETTO_OS_MACOSX) && \
- !PERFETTO_BUILDFLAG(PERFETTO_OS_WIN)
+ !PERFETTO_BUILDFLAG(PERFETTO_OS_WIN) && \
+ !PERFETTO_BUILDFLAG(PERFETTO_OS_NACL)
struct {
clockid_t id;
protos::pbzero::ClockSnapshot::Clock::BuiltinClocks type;
@@ -2266,8 +2281,9 @@
c->set_timestamp(
static_cast<uint64_t>(base::FromPosixTimespec(clock.ts).count()));
}
-#else // !PERFETTO_BUILDFLAG(PERFETTO_OS_MACOSX) &&
- // !PERFETTO_BUILDFLAG(PERFETTO_OS_WIN)
+#else // !PERFETTO_BUILDFLAG(PERFETTO_OS_MACOSX) &&
+ // !PERFETTO_BUILDFLAG(PERFETTO_OS_WIN) &&
+ // !PERFETTO_BUILDFLAG(PERFETTO_OS_NACL)
auto wall_time_ns = static_cast<uint64_t>(base::GetWallTimeNs().count());
if (set_root_timestamp)
root_timestamp_ns = wall_time_ns;
@@ -2347,7 +2363,8 @@
protozero::HeapBuffered<protos::pbzero::TracePacket> packet;
auto* info = packet->set_system_info();
base::ignore_result(info); // For PERFETTO_OS_WIN.
-#if !PERFETTO_BUILDFLAG(PERFETTO_OS_WIN)
+#if !PERFETTO_BUILDFLAG(PERFETTO_OS_WIN) && \
+ !PERFETTO_BUILDFLAG(PERFETTO_OS_NACL)
struct utsname uname_info;
if (uname(&uname_info) == 0) {
auto* utsname_info = info->set_utsname();
@@ -2803,7 +2820,7 @@
}
SharedMemoryArbiter*
-TracingServiceImpl::ProducerEndpointImpl::GetInProcessShmemArbiter() {
+TracingServiceImpl::ProducerEndpointImpl::MaybeSharedMemoryArbiter() {
if (!inproc_shmem_arbiter_) {
PERFETTO_FATAL(
"The in-process SharedMemoryArbiter can only be used when "
@@ -2820,14 +2837,16 @@
TracingServiceImpl::ProducerEndpointImpl::CreateTraceWriter(
BufferID buf_id,
BufferExhaustedPolicy buffer_exhausted_policy) {
- return GetInProcessShmemArbiter()->CreateTraceWriter(buf_id,
+ PERFETTO_DCHECK(MaybeSharedMemoryArbiter());
+ return MaybeSharedMemoryArbiter()->CreateTraceWriter(buf_id,
buffer_exhausted_policy);
}
void TracingServiceImpl::ProducerEndpointImpl::NotifyFlushComplete(
FlushRequestID id) {
PERFETTO_DCHECK_THREAD(thread_checker_);
- return GetInProcessShmemArbiter()->NotifyFlushComplete(id);
+ PERFETTO_DCHECK(MaybeSharedMemoryArbiter());
+ return MaybeSharedMemoryArbiter()->NotifyFlushComplete(id);
}
void TracingServiceImpl::ProducerEndpointImpl::OnTracingSetup() {
diff --git a/src/tracing/core/tracing_service_impl.h b/src/tracing/core/tracing_service_impl.h
index 61c6ef6..eb53207 100644
--- a/src/tracing/core/tracing_service_impl.h
+++ b/src/tracing/core/tracing_service_impl.h
@@ -90,7 +90,7 @@
std::unique_ptr<TraceWriter> CreateTraceWriter(
BufferID,
BufferExhaustedPolicy) override;
- SharedMemoryArbiter* GetInProcessShmemArbiter() override;
+ SharedMemoryArbiter* MaybeSharedMemoryArbiter() override;
void NotifyFlushComplete(FlushRequestID) override;
void NotifyDataSourceStarted(DataSourceInstanceID) override;
void NotifyDataSourceStopped(DataSourceInstanceID) override;
diff --git a/src/tracing/core/tracing_service_impl_unittest.cc b/src/tracing/core/tracing_service_impl_unittest.cc
index 2643cc7..bedb3f1 100644
--- a/src/tracing/core/tracing_service_impl_unittest.cc
+++ b/src/tracing/core/tracing_service_impl_unittest.cc
@@ -2931,4 +2931,40 @@
EXPECT_EQ(svc_state.data_sources().at(1).ds_descriptor().name(), "p2_ds");
}
+TEST_F(TracingServiceImplTest, LimitSessionsPerUid) {
+ std::vector<std::unique_ptr<MockConsumer>> consumers;
+
+ auto start_new_session = [&](uid_t uid) -> MockConsumer* {
+ TraceConfig trace_config;
+ trace_config.add_buffers()->set_size_kb(128);
+ trace_config.set_duration_ms(0); // Unlimited.
+ consumers.emplace_back(CreateMockConsumer());
+ consumers.back()->Connect(svc.get(), uid);
+ consumers.back()->EnableTracing(trace_config);
+ return &*consumers.back();
+ };
+
+ const int kMaxConcurrentTracingSessionsPerUid = 5;
+ const int kUids = 2;
+
+ // Create a bunch of legit sessions (2 uids * 5 sessions).
+ for (int i = 0; i < kMaxConcurrentTracingSessionsPerUid * kUids; i++) {
+ start_new_session(/*uid=*/i % kUids);
+ }
+
+ // Any other session now should fail for the two uids.
+ for (int i = 0; i <= kUids; i++) {
+ auto* consumer = start_new_session(/*uid=*/i % kUids);
+ auto on_fail = task_runner.CreateCheckpoint("uid_" + std::to_string(i));
+ EXPECT_CALL(*consumer, OnTracingDisabled()).WillOnce(Invoke(on_fail));
+ }
+
+ // Wait for failure (only after both attempts).
+ for (int i = 0; i <= kUids; i++) {
+ task_runner.RunUntilCheckpoint("uid_" + std::to_string(i));
+ }
+
+ // The destruction of |consumers| will tear down and stop the good sessions.
+}
+
} // namespace perfetto
diff --git a/src/tracing/event_context.cc b/src/tracing/event_context.cc
index 2126e2c..a4f1ade 100644
--- a/src/tracing/event_context.cc
+++ b/src/tracing/event_context.cc
@@ -29,6 +29,9 @@
incremental_state_(incremental_state) {}
EventContext::~EventContext() {
+ if (!trace_packet_)
+ return;
+
// When the track event is finalized (i.e., the context is destroyed), we
// should flush any newly seen interned data to the trace. The data has
// earlier been written to a heap allocated protobuf message
diff --git a/src/tracing/internal/in_process_tracing_backend_fake.cc b/src/tracing/internal/in_process_tracing_backend_fake.cc
new file mode 100644
index 0000000..7ffafa8
--- /dev/null
+++ b/src/tracing/internal/in_process_tracing_backend_fake.cc
@@ -0,0 +1,33 @@
+/*
+ * Copyright (C) 2020 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.
+ */
+
+#include "src/tracing/internal/in_process_tracing_backend.h"
+
+#include "perfetto/base/logging.h"
+
+namespace perfetto {
+namespace internal {
+
+// static
+InProcessTracingBackend* InProcessTracingBackend::GetInstance() {
+ PERFETTO_ELOG(
+ "In-process tracing backend not supported by the current build "
+ "configuration");
+ return nullptr;
+}
+
+} // namespace internal
+} // namespace perfetto
diff --git a/test/task_runner_thread_delegates.cc b/src/tracing/internal/system_tracing_backend_fake.cc
similarity index 60%
copy from test/task_runner_thread_delegates.cc
copy to src/tracing/internal/system_tracing_backend_fake.cc
index 291482f..6a940ae 100644
--- a/test/task_runner_thread_delegates.cc
+++ b/src/tracing/internal/system_tracing_backend_fake.cc
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2019 The Android Open Source Project
+ * Copyright (C) 2020 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.
@@ -14,12 +14,20 @@
* limitations under the License.
*/
-#include "test/task_runner_thread_delegates.h"
+#include "src/tracing/internal/system_tracing_backend.h"
+
+#include "perfetto/base/logging.h"
namespace perfetto {
+namespace internal {
-ServiceDelegate::~ServiceDelegate() = default;
-ProbesProducerDelegate::~ProbesProducerDelegate() = default;
-FakeProducerDelegate::~FakeProducerDelegate() = default;
+// static
+SystemTracingBackend* SystemTracingBackend::GetInstance() {
+ PERFETTO_ELOG(
+ "System tracing backend not supported by the current build "
+ "configuration");
+ return nullptr;
+}
+} // namespace internal
} // namespace perfetto
diff --git a/src/tracing/internal/tracing_muxer_impl.cc b/src/tracing/internal/tracing_muxer_impl.cc
index a185f25..e63bc11 100644
--- a/src/tracing/internal/tracing_muxer_impl.cc
+++ b/src/tracing/internal/tracing_muxer_impl.cc
@@ -421,6 +421,12 @@
PERFETTO_DCHECK_THREAD(thread_checker_); // Rebind the thread checker.
auto add_backend = [this, &args](TracingBackend* backend, BackendType type) {
+ if (!backend) {
+ // We skip the log in release builds because the *_backend_fake.cc code
+ // has already an ELOG before returning a nullptr.
+ PERFETTO_DLOG("Backend creation failed, type %d", static_cast<int>(type));
+ return;
+ }
TracingBackendId backend_id = backends_.size();
backends_.emplace_back();
RegisteredBackend& rb = backends_.back();
@@ -437,13 +443,12 @@
rb.producer->Initialize(rb.backend->ConnectProducer(conn_args));
};
- if (args.backends & kSystemBackend) {
-#if (PERFETTO_BUILDFLAG(PERFETTO_IPC))
+ // Both the system and the in-process backends can be disabled at build-time
+ // and replaced with the _fake.cc versions. The "fake" versions will just
+ // ELOG() and return nullptr.
+
+ if (args.backends & kSystemBackend)
add_backend(SystemTracingBackend::GetInstance(), kSystemBackend);
-#else
- PERFETTO_ELOG("System backend not supporteed in the current configuration");
-#endif
- }
if (args.backends & kInProcessBackend)
add_backend(InProcessTracingBackend::GetInstance(), kInProcessBackend);
diff --git a/src/tracing/internal/track_event_internal.cc b/src/tracing/internal/track_event_internal.cc
index 71afc7b..4c0c86b 100644
--- a/src/tracing/internal/track_event_internal.cc
+++ b/src/tracing/internal/track_event_internal.cc
@@ -16,9 +16,9 @@
#include "perfetto/tracing/internal/track_event_internal.h"
+#include "perfetto/base/proc_utils.h"
+#include "perfetto/base/thread_utils.h"
#include "perfetto/base/time.h"
-#include "perfetto/ext/base/proc_utils.h"
-#include "perfetto/ext/base/thread_utils.h"
#include "perfetto/tracing/core/data_source_config.h"
#include "perfetto/tracing/track_event.h"
#include "perfetto/tracing/track_event_category_registry.h"
@@ -28,8 +28,7 @@
#include "protos/perfetto/trace/interned_data/interned_data.pbzero.h"
#include "protos/perfetto/trace/trace_packet_defaults.pbzero.h"
#include "protos/perfetto/trace/track_event/debug_annotation.pbzero.h"
-#include "protos/perfetto/trace/track_event/process_descriptor.pbzero.h"
-#include "protos/perfetto/trace/track_event/thread_descriptor.pbzero.h"
+#include "protos/perfetto/trace/track_event/track_descriptor.pbzero.h"
namespace perfetto {
namespace internal {
@@ -38,7 +37,7 @@
namespace {
-std::atomic<perfetto::base::PlatformThreadID> g_main_thread;
+std::atomic<perfetto::base::PlatformThreadId> g_main_thread;
struct InternedEventCategory
: public TrackEventInternedDataIndex<
@@ -95,49 +94,6 @@
#endif
}
-uint64_t GetTimeNs() {
- if (GetClockType() == protos::pbzero::ClockSnapshot::Clock::BOOTTIME)
- return static_cast<uint64_t>(perfetto::base::GetBootTimeNs().count());
- PERFETTO_DCHECK(GetClockType() ==
- protos::pbzero::ClockSnapshot::Clock::MONOTONIC);
- return static_cast<uint64_t>(perfetto::base::GetWallTimeNs().count());
-}
-
-protozero::MessageHandle<protos::pbzero::TracePacket> NewTracePacket(
- TraceWriterBase* trace_writer,
- uint64_t timestamp) {
- auto packet = trace_writer->NewTracePacket();
- packet->set_timestamp(timestamp);
- // TODO(skyostil): Stop emitting this for every event once the trace processor
- // understands trace packet defaults.
- if (GetClockType() != protos::pbzero::ClockSnapshot::Clock::BOOTTIME)
- packet->set_timestamp_clock_id(GetClockType());
- return packet;
-}
-
-// static
-void WriteSequenceDescriptors(TraceWriterBase* trace_writer,
- uint64_t timestamp) {
- if (perfetto::base::GetThreadId() == g_main_thread) {
- auto packet = NewTracePacket(trace_writer, timestamp);
- packet->set_incremental_state_cleared(true);
- auto defaults = packet->set_trace_packet_defaults();
- defaults->set_timestamp_clock_id(GetClockType());
- auto pd = packet->set_process_descriptor();
- pd->set_pid(static_cast<int32_t>(base::GetProcessId()));
- // TODO(skyostil): Record command line.
- }
- {
- auto packet = NewTracePacket(trace_writer, timestamp);
- packet->set_incremental_state_cleared(true);
- auto defaults = packet->set_trace_packet_defaults();
- defaults->set_timestamp_clock_id(GetClockType());
- auto td = packet->set_thread_descriptor();
- td->set_pid(static_cast<int32_t>(base::GetProcessId()));
- td->set_tid(static_cast<int32_t>(perfetto::base::GetThreadId()));
- }
-}
-
} // namespace
// static
@@ -177,6 +133,57 @@
}
// static
+uint64_t TrackEventInternal::GetTimeNs() {
+ if (GetClockType() == protos::pbzero::ClockSnapshot::Clock::BOOTTIME)
+ return static_cast<uint64_t>(perfetto::base::GetBootTimeNs().count());
+ PERFETTO_DCHECK(GetClockType() ==
+ protos::pbzero::ClockSnapshot::Clock::MONOTONIC);
+ return static_cast<uint64_t>(perfetto::base::GetWallTimeNs().count());
+}
+
+// static
+void TrackEventInternal::ResetIncrementalState(TraceWriterBase* trace_writer,
+ uint64_t timestamp) {
+ auto default_track = ThreadTrack::Current();
+ {
+ // Mark any incremental state before this point invalid. Also set up
+ // defaults so that we don't need to repeat constant data for each packet.
+ auto packet = NewTracePacket(
+ trace_writer, timestamp,
+ protos::pbzero::TracePacket::SEQ_INCREMENTAL_STATE_CLEARED);
+ auto defaults = packet->set_trace_packet_defaults();
+ defaults->set_timestamp_clock_id(GetClockType());
+
+ // Establish the default track for this event sequence.
+ auto track_defaults = defaults->set_track_event_defaults();
+ track_defaults->set_track_uuid(default_track.uuid);
+ }
+
+ // Every thread should write a descriptor for its default track, because most
+ // trace points won't explicitly reference it.
+ WriteTrackDescriptor(default_track, trace_writer);
+
+ // Additionally the main thread should dump the process descriptor.
+ if (perfetto::base::GetThreadId() == g_main_thread)
+ WriteTrackDescriptor(ProcessTrack::Current(), trace_writer);
+}
+
+// static
+protozero::MessageHandle<protos::pbzero::TracePacket>
+TrackEventInternal::NewTracePacket(TraceWriterBase* trace_writer,
+ uint64_t timestamp,
+ uint32_t seq_flags) {
+ auto packet = trace_writer->NewTracePacket();
+ packet->set_timestamp(timestamp);
+ // TODO(skyostil): Stop emitting this for every event once the trace processor
+ // understands trace packet defaults.
+ if (GetClockType() != protos::pbzero::ClockSnapshot::Clock::BOOTTIME)
+ packet->set_timestamp_clock_id(GetClockType());
+ packet->set_sequence_flags(seq_flags);
+ return packet;
+}
+
+// static
EventContext TrackEventInternal::WriteEvent(
TraceWriterBase* trace_writer,
TrackEventIncrementalState* incr_state,
@@ -189,19 +196,22 @@
if (incr_state->was_cleared) {
incr_state->was_cleared = false;
- WriteSequenceDescriptors(trace_writer, timestamp);
+ ResetIncrementalState(trace_writer, timestamp);
}
auto packet = NewTracePacket(trace_writer, timestamp);
+ EventContext ctx(std::move(packet), incr_state);
+
+ auto track_event = ctx.event();
+ if (type != protos::pbzero::TrackEvent::TYPE_UNSPECIFIED)
+ track_event->set_type(type);
// We assume that |category| and |name| point to strings with static lifetime.
// This means we can use their addresses as interning keys.
- EventContext ctx(std::move(packet), incr_state);
- size_t category_iid = InternedEventCategory::Get(&ctx, category);
-
- auto track_event = ctx.event();
- track_event->set_type(type);
- // TODO(skyostil): Handle multiple categories.
- track_event->add_category_iids(category_iid);
+ if (type != protos::pbzero::TrackEvent::TYPE_SLICE_END) {
+ // TODO(skyostil): Handle multiple categories.
+ size_t category_iid = InternedEventCategory::Get(&ctx, category);
+ track_event->add_category_iids(category_iid);
+ }
if (name) {
size_t name_iid = InternedEventName::Get(&ctx, name);
track_event->set_name_iid(name_iid);
diff --git a/src/tracing/ipc/BUILD.gn b/src/tracing/ipc/BUILD.gn
new file mode 100644
index 0000000..0f2bcb6
--- /dev/null
+++ b/src/tracing/ipc/BUILD.gn
@@ -0,0 +1,53 @@
+# Copyright (C) 2020 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.
+
+import("../../../gn/perfetto.gni")
+import("../../../gn/test.gni")
+
+assert(enable_perfetto_ipc)
+
+# The lack of a default "ipc" target is deliberate. Clients need to explicitly
+# depend on ipc/{producer, consumer, service}. This is to avoid binary bloat
+# by always linking everything.
+
+source_set("common") {
+ public_deps = [
+ "../../../include/perfetto/ext/tracing/core",
+ "../../../include/perfetto/ext/tracing/ipc",
+ ]
+ sources = [
+ "default_socket.cc",
+ "posix_shared_memory.cc",
+ "posix_shared_memory.h",
+ ]
+ deps = [
+ "../../../gn:default_deps",
+ "../../../include/perfetto/ext/ipc",
+ "../../base",
+ "../core",
+ ]
+}
+
+perfetto_unittest_source_set("unittests") {
+ testonly = true
+ deps = [
+ ":common",
+ "../../../gn:default_deps",
+ "../../../gn:gtest_and_gmock",
+ "../../../include/perfetto/ext/ipc",
+ "../../base",
+ "../../base:test_support",
+ ]
+ sources = [ "posix_shared_memory_unittest.cc" ]
+}
diff --git a/src/tracing/ipc/consumer/BUILD.gn b/src/tracing/ipc/consumer/BUILD.gn
new file mode 100644
index 0000000..0a2dcc2
--- /dev/null
+++ b/src/tracing/ipc/consumer/BUILD.gn
@@ -0,0 +1,37 @@
+# Copyright (C) 2020 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.
+
+import("../../../../gn/perfetto.gni")
+
+assert(enable_perfetto_ipc)
+
+# Posix specialization of the tracing library for Linux / Android / Mac.
+# Provides an IPC transport over a UNIX socket for the consumer interface.
+source_set("consumer") {
+ public_deps = [
+ "../../../../include/perfetto/ext/tracing/core",
+ "../../../../include/perfetto/ext/tracing/ipc",
+ "../../../../protos/perfetto/ipc",
+ ]
+ sources = [
+ "consumer_ipc_client_impl.cc",
+ "consumer_ipc_client_impl.h",
+ ]
+ deps = [
+ "..:common",
+ "../../../../gn:default_deps",
+ "../../../base",
+ "../../../ipc:client",
+ ]
+}
diff --git a/src/tracing/ipc/consumer/consumer_ipc_client_impl.h b/src/tracing/ipc/consumer/consumer_ipc_client_impl.h
index e65f1fc..66c7943 100644
--- a/src/tracing/ipc/consumer/consumer_ipc_client_impl.h
+++ b/src/tracing/ipc/consumer/consumer_ipc_client_impl.h
@@ -29,6 +29,7 @@
#include "perfetto/ext/tracing/core/tracing_service.h"
#include "perfetto/ext/tracing/ipc/consumer_ipc_client.h"
#include "perfetto/tracing/core/forward_decls.h"
+
#include "protos/perfetto/ipc/consumer_port.ipc.h"
namespace perfetto {
diff --git a/src/tracing/ipc/producer/BUILD.gn b/src/tracing/ipc/producer/BUILD.gn
new file mode 100644
index 0000000..c7e0d8a
--- /dev/null
+++ b/src/tracing/ipc/producer/BUILD.gn
@@ -0,0 +1,37 @@
+# Copyright (C) 2020 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.
+
+import("../../../../gn/perfetto.gni")
+
+assert(enable_perfetto_ipc)
+
+# Posix specialization of the tracing library for Linux / Android / Mac.
+# Provides an IPC transport over a UNIX socket for the producer interface.
+source_set("producer") {
+ public_deps = [
+ "../../../../include/perfetto/ext/tracing/core",
+ "../../../../include/perfetto/ext/tracing/ipc",
+ "../../../../protos/perfetto/ipc",
+ ]
+ sources = [
+ "producer_ipc_client_impl.cc",
+ "producer_ipc_client_impl.h",
+ ]
+ deps = [
+ "..:common",
+ "../../../../gn:default_deps",
+ "../../../base",
+ "../../../ipc:client",
+ ]
+}
diff --git a/src/tracing/ipc/producer/producer_ipc_client_impl.cc b/src/tracing/ipc/producer/producer_ipc_client_impl.cc
index 396bf4c..f06801a 100644
--- a/src/tracing/ipc/producer/producer_ipc_client_impl.cc
+++ b/src/tracing/ipc/producer/producer_ipc_client_impl.cc
@@ -358,9 +358,8 @@
buffer_exhausted_policy);
}
-SharedMemoryArbiter* ProducerIPCClientImpl::GetInProcessShmemArbiter() {
- PERFETTO_DLOG("Cannot GetInProcessShmemArbiter() via the IPC layer.");
- return nullptr;
+SharedMemoryArbiter* ProducerIPCClientImpl::MaybeSharedMemoryArbiter() {
+ return shared_memory_arbiter_.get();
}
void ProducerIPCClientImpl::NotifyFlushComplete(FlushRequestID req_id) {
diff --git a/src/tracing/ipc/producer/producer_ipc_client_impl.h b/src/tracing/ipc/producer/producer_ipc_client_impl.h
index e556fbb..68feeea 100644
--- a/src/tracing/ipc/producer/producer_ipc_client_impl.h
+++ b/src/tracing/ipc/producer/producer_ipc_client_impl.h
@@ -76,7 +76,7 @@
std::unique_ptr<TraceWriter> CreateTraceWriter(
BufferID target_buffer,
BufferExhaustedPolicy) override;
- SharedMemoryArbiter* GetInProcessShmemArbiter() override;
+ SharedMemoryArbiter* MaybeSharedMemoryArbiter() override;
void NotifyFlushComplete(FlushRequestID) override;
SharedMemory* shared_memory() const override;
size_t shared_buffer_page_size_kb() const override;
diff --git a/src/tracing/ipc/service/BUILD.gn b/src/tracing/ipc/service/BUILD.gn
new file mode 100644
index 0000000..0bc401c
--- /dev/null
+++ b/src/tracing/ipc/service/BUILD.gn
@@ -0,0 +1,42 @@
+# Copyright (C) 2020 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.
+
+import("../../../../gn/perfetto.gni")
+
+assert(enable_perfetto_ipc)
+
+# Posix specialization of the tracing library for Linux / Android / Mac.
+# Provides an IPC transport over a UNIX socket for the service interface.
+source_set("service") {
+ public_deps = [
+ "../../../../include/perfetto/ext/tracing/core",
+ "../../../../include/perfetto/ext/tracing/ipc",
+ ]
+ sources = [
+ "consumer_ipc_service.cc",
+ "consumer_ipc_service.h",
+ "producer_ipc_service.cc",
+ "producer_ipc_service.h",
+ "service_ipc_host_impl.cc",
+ "service_ipc_host_impl.h",
+ ]
+ deps = [
+ "..:common",
+ "../../../../gn:default_deps",
+ "../../../../protos/perfetto/ipc",
+ "../../../base",
+ "../../../ipc:host",
+ "../../core:service",
+ ]
+}
diff --git a/test/task_runner_thread_delegates.cc b/src/tracing/platform_fake.cc
similarity index 66%
copy from test/task_runner_thread_delegates.cc
copy to src/tracing/platform_fake.cc
index 291482f..a13e7bf 100644
--- a/test/task_runner_thread_delegates.cc
+++ b/src/tracing/platform_fake.cc
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2019 The Android Open Source Project
+ * Copyright (C) 2020 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.
@@ -14,12 +14,16 @@
* limitations under the License.
*/
-#include "test/task_runner_thread_delegates.h"
+#include "perfetto/tracing/platform.h"
namespace perfetto {
-ServiceDelegate::~ServiceDelegate() = default;
-ProbesProducerDelegate::~ProbesProducerDelegate() = default;
-FakeProducerDelegate::~FakeProducerDelegate() = default;
+// This simply allows building the client library and using those parts of it
+// that do not depend on anything in the platform.
+
+// static
+Platform* Platform::GetDefaultPlatform() {
+ return nullptr;
+}
} // namespace perfetto
diff --git a/src/tracing/test/BUILD.gn b/src/tracing/test/BUILD.gn
index 2c99bc9..6a84532 100644
--- a/src/tracing/test/BUILD.gn
+++ b/src/tracing/test/BUILD.gn
@@ -12,6 +12,94 @@
# See the License for the specific language governing permissions and
# limitations under the License.
+import("../../../gn/fuzzer.gni")
+import("../../../gn/perfetto.gni")
+import("../../../gn/test.gni")
+
+perfetto_unittest_source_set("test_support") {
+ testonly = true
+ public_deps = [ "../core:test_support" ]
+ deps = [
+ "../../../gn:default_deps",
+ "../../../gn:gtest_and_gmock",
+ "../../../protos/perfetto/trace:cpp",
+ "../../../protos/perfetto/trace:zero",
+ "../../../protos/perfetto/trace/ftrace:cpp",
+ "../../base",
+ "../../base:test_support",
+ "../core",
+ "../core:service",
+ "../core:test_support",
+ ]
+ sources = [
+ "aligned_buffer_test.cc",
+ "aligned_buffer_test.h",
+ "fake_packet.cc",
+ "fake_packet.h",
+ "test_shared_memory.cc",
+ "test_shared_memory.h",
+ ]
+
+ # These tests rely on test_task_runner.h which
+ # has no Windows implementation.
+ if (!is_win) {
+ sources += [
+ "fake_producer_endpoint.h",
+ "mock_consumer.cc",
+ "mock_consumer.h",
+ "mock_producer.cc",
+ "mock_producer.h",
+ ]
+ }
+}
+
+if (enable_perfetto_ipc) {
+ perfetto_unittest_source_set("tracing_integration_test") {
+ testonly = true
+ deps = [
+ ":test_support",
+ "../../../gn:default_deps",
+ "../../../gn:gtest_and_gmock",
+ "../../base",
+ "../../base:test_support",
+ "../core:service",
+ "../ipc/consumer",
+ "../ipc/producer",
+ "../ipc/service",
+ ]
+ sources = [ "tracing_integration_test.cc" ]
+ }
+}
+
+if (enable_perfetto_integration_tests) {
+ source_set("client_api_integrationtests") {
+ testonly = true
+ deps = [
+ ":api_test_support",
+ "../:client_api",
+ "../:platform_posix",
+ "../../../:libperfetto_client_experimental",
+ "../../../gn:default_deps",
+ "../../../gn:gtest_and_gmock",
+ "../../../include/perfetto/tracing/core",
+ "../../../protos/perfetto/trace:cpp",
+ "../../../protos/perfetto/trace:zero",
+ "../../../protos/perfetto/trace/interned_data:cpp",
+ "../../../protos/perfetto/trace/interned_data:zero",
+ "../../../protos/perfetto/trace/profiling:cpp",
+ "../../../protos/perfetto/trace/track_event:cpp",
+ "../../base",
+ ]
+ sources = [
+ "api_integrationtest.cc",
+ "tracing_module.cc",
+ "tracing_module.h",
+ "tracing_module2.cc",
+ "tracing_module_categories.h",
+ ]
+ }
+}
+
# api_test_support needs to be self-contained and not leak any other perfetto
# deps. See comment in api_test_support.h
source_set("api_test_support") {
diff --git a/src/tracing/api_integrationtest.cc b/src/tracing/test/api_integrationtest.cc
similarity index 78%
rename from src/tracing/api_integrationtest.cc
rename to src/tracing/test/api_integrationtest.cc
index a9f3fbb..b633582 100644
--- a/src/tracing/api_integrationtest.cc
+++ b/src/tracing/test/api_integrationtest.cc
@@ -21,8 +21,12 @@
#include <functional>
#include <list>
#include <mutex>
+#include <thread>
#include <vector>
+// We also want to test legacy trace events.
+#define PERFETTO_ENABLE_LEGACY_TRACE_EVENTS 1
+
#include "perfetto/tracing.h"
#include "test/gtest_and_gmock.h"
@@ -50,20 +54,26 @@
#include "protos/perfetto/trace/trace.gen.h"
#include "protos/perfetto/trace/trace_packet.gen.h"
#include "protos/perfetto/trace/trace_packet.pbzero.h"
+#include "protos/perfetto/trace/track_event/chrome_process_descriptor.gen.h"
+#include "protos/perfetto/trace/track_event/chrome_process_descriptor.pbzero.h"
#include "protos/perfetto/trace/track_event/debug_annotation.gen.h"
#include "protos/perfetto/trace/track_event/debug_annotation.pbzero.h"
#include "protos/perfetto/trace/track_event/log_message.gen.h"
#include "protos/perfetto/trace/track_event/log_message.pbzero.h"
#include "protos/perfetto/trace/track_event/process_descriptor.gen.h"
+#include "protos/perfetto/trace/track_event/process_descriptor.pbzero.h"
#include "protos/perfetto/trace/track_event/source_location.gen.h"
#include "protos/perfetto/trace/track_event/source_location.pbzero.h"
#include "protos/perfetto/trace/track_event/thread_descriptor.gen.h"
+#include "protos/perfetto/trace/track_event/thread_descriptor.pbzero.h"
+#include "protos/perfetto/trace/track_event/track_descriptor.gen.h"
#include "protos/perfetto/trace/track_event/track_event.gen.h"
// Trace categories used in the tests.
PERFETTO_DEFINE_CATEGORIES(PERFETTO_CATEGORY(test),
PERFETTO_CATEGORY(foo),
- PERFETTO_CATEGORY(bar));
+ PERFETTO_CATEGORY(bar),
+ PERFETTO_CATEGORY(cat));
PERFETTO_TRACK_EVENT_STATIC_STORAGE();
// For testing interning of complex objects.
@@ -228,6 +238,16 @@
WaitableTestEvent on_stop;
};
+class MyDebugAnnotation : public perfetto::DebugAnnotation {
+ public:
+ ~MyDebugAnnotation() override = default;
+
+ void Add(
+ perfetto::protos::pbzero::DebugAnnotation* annotation) const override {
+ annotation->set_legacy_json_value(R"({"key": 123})");
+ }
+};
+
// -------------------------
// Declaration of test class
// -------------------------
@@ -237,16 +257,13 @@
void SetUp() override {
instance = this;
- // Perfetto can only be initialized once in a process.
- static bool was_initialized;
- if (!was_initialized) {
- perfetto::TracingInitArgs args;
- args.backends = perfetto::kInProcessBackend;
- perfetto::Tracing::Initialize(args);
- was_initialized = true;
- RegisterDataSource<MockDataSource>("my_data_source");
- perfetto::TrackEvent::Register();
- }
+
+ perfetto::TracingInitArgs args;
+ args.backends = perfetto::kInProcessBackend;
+ perfetto::Tracing::Initialize(args);
+ RegisterDataSource<MockDataSource>("my_data_source");
+ perfetto::TrackEvent::Register();
+
// Make sure our data source always has a valid handle.
data_sources_["my_data_source"];
}
@@ -345,7 +362,8 @@
bool incremental_state_was_cleared = false;
uint32_t sequence_id = 0;
for (const auto& packet : parsed_trace.packet()) {
- if (packet.incremental_state_cleared()) {
+ if (packet.sequence_flags() & perfetto::protos::pbzero::TracePacket::
+ SEQ_INCREMENTAL_STATE_CLEARED) {
incremental_state_was_cleared = true;
categories.clear();
event_names.clear();
@@ -391,12 +409,21 @@
case perfetto::protos::gen::TrackEvent::TYPE_INSTANT:
slice += "I";
break;
- default:
- case perfetto::protos::gen::TrackEvent::TYPE_UNSPECIFIED:
+ case perfetto::protos::gen::TrackEvent::TYPE_UNSPECIFIED: {
+ EXPECT_TRUE(track_event.has_legacy_event());
EXPECT_FALSE(track_event.type());
+ auto legacy_event = track_event.legacy_event();
+ slice += "Legacy_" +
+ std::string(1, static_cast<char>(legacy_event.phase()));
+ break;
+ }
+ default:
+ ADD_FAILURE();
}
- slice += ":" + categories[track_event.category_iids()[0]] + "." +
- event_names[track_event.name_iid()];
+ if (!track_event.category_iids().empty())
+ slice += ":" + categories[track_event.category_iids()[0]];
+ if (track_event.has_name_iid())
+ slice += "." + event_names[track_event.name_iid()];
if (track_event.debug_annotations_size()) {
slice += "(";
@@ -558,25 +585,21 @@
bool begin_found = false;
bool end_found = false;
bool process_descriptor_found = false;
- bool thread_descriptor_found = false;
auto now = perfetto::test::GetTraceTimeNs();
uint32_t sequence_id = 0;
int32_t cur_pid = perfetto::test::GetCurrentProcessId();
for (const auto& packet : trace.packet()) {
- if (packet.has_process_descriptor()) {
- EXPECT_FALSE(process_descriptor_found);
- const auto& pd = packet.process_descriptor();
- EXPECT_EQ(cur_pid, pd.pid());
- process_descriptor_found = true;
+ if (packet.has_track_descriptor()) {
+ const auto& desc = packet.track_descriptor();
+ if (desc.has_process()) {
+ EXPECT_FALSE(process_descriptor_found);
+ const auto& pd = desc.process();
+ EXPECT_EQ(cur_pid, pd.pid());
+ process_descriptor_found = true;
+ }
}
- if (packet.has_thread_descriptor()) {
- EXPECT_FALSE(thread_descriptor_found);
- const auto& td = packet.thread_descriptor();
- EXPECT_EQ(cur_pid, td.pid());
- EXPECT_NE(0, td.tid());
- thread_descriptor_found = true;
- }
- if (packet.incremental_state_cleared()) {
+ if (packet.sequence_flags() &
+ perfetto::protos::pbzero::TracePacket::SEQ_INCREMENTAL_STATE_CLEARED) {
EXPECT_TRUE(packet.has_trace_packet_defaults());
incremental_state_was_cleared = true;
categories.clear();
@@ -585,6 +608,10 @@
if (!packet.has_track_event())
continue;
+ EXPECT_TRUE(
+ packet.sequence_flags() &
+ (perfetto::protos::pbzero::TracePacket::SEQ_INCREMENTAL_STATE_CLEARED |
+ perfetto::protos::pbzero::TracePacket::SEQ_NEEDS_INCREMENTAL_STATE));
const auto& track_event = packet.track_event();
// Make sure we only see track events on one sequence.
@@ -617,26 +644,24 @@
perfetto::protos::pbzero::ClockSnapshot::Clock::MONOTONIC;
EXPECT_EQ(packet.timestamp_clock_id(), kClockMonotonic);
#endif
- EXPECT_EQ(track_event.category_iids().size(), 1u);
- EXPECT_GE(track_event.category_iids()[0], 1u);
-
if (track_event.type() ==
perfetto::protos::gen::TrackEvent::TYPE_SLICE_BEGIN) {
EXPECT_FALSE(begin_found);
+ EXPECT_EQ(track_event.category_iids().size(), 1u);
+ EXPECT_GE(track_event.category_iids()[0], 1u);
EXPECT_EQ("test", categories[track_event.category_iids()[0]]);
EXPECT_EQ("TestEvent", event_names[track_event.name_iid()]);
begin_found = true;
} else if (track_event.type() ==
perfetto::protos::gen::TrackEvent::TYPE_SLICE_END) {
EXPECT_FALSE(end_found);
+ EXPECT_EQ(track_event.category_iids().size(), 0u);
EXPECT_EQ(0u, track_event.name_iid());
- EXPECT_EQ("test", categories[track_event.category_iids()[0]]);
end_found = true;
}
}
EXPECT_TRUE(incremental_state_was_cleared);
EXPECT_TRUE(process_descriptor_found);
- EXPECT_TRUE(thread_descriptor_found);
EXPECT_TRUE(begin_found);
EXPECT_TRUE(end_found);
}
@@ -828,6 +853,230 @@
EXPECT_THAT(trace2, Not(HasSubstr("Session2_Third")));
}
+TEST_F(PerfettoApiTest, TrackEventProcessAndThreadDescriptors) {
+ // Thread and process descriptors can be set before tracing is enabled.
+ perfetto::TrackEvent::SetProcessDescriptor(
+ [](perfetto::protos::pbzero::TrackDescriptor* desc) {
+ desc->set_name("hello.exe");
+ desc->set_chrome_process()->set_process_priority(1);
+ });
+
+ // Erased tracks shouldn't show up anywhere.
+ perfetto::Track erased(1234u);
+ perfetto::TrackEvent::SetTrackDescriptor(
+ erased, [](perfetto::protos::pbzero::TrackDescriptor* desc) {
+ desc->set_name("ErasedTrack");
+ });
+ perfetto::TrackEvent::EraseTrackDescriptor(erased);
+
+ // Setup the trace config.
+ perfetto::TraceConfig cfg;
+ cfg.set_duration_ms(500);
+ cfg.add_buffers()->set_size_kb(1024);
+ auto* ds_cfg = cfg.add_data_sources()->mutable_config();
+ ds_cfg->set_name("track_event");
+
+ // Create a new trace session.
+ auto* tracing_session = NewTrace(cfg);
+ tracing_session->get()->StartBlocking();
+ TRACE_EVENT_INSTANT("test", "MainThreadEvent");
+
+ std::thread thread([&] {
+ perfetto::TrackEvent::SetThreadDescriptor(
+ [](perfetto::protos::pbzero::TrackDescriptor* desc) {
+ desc->set_name("TestThread");
+ });
+ TRACE_EVENT_INSTANT("test", "ThreadEvent");
+ });
+ thread.join();
+
+ // Update the process descriptor while tracing is enabled. It should be
+ // immediately reflected in the trace.
+ perfetto::TrackEvent::SetProcessDescriptor(
+ [](perfetto::protos::pbzero::TrackDescriptor* desc) {
+ desc->set_name("goodbye.exe");
+ });
+ perfetto::TrackEvent::Flush();
+
+ tracing_session->get()->StopBlocking();
+
+ // After tracing ends, setting the descriptor has no immediate effect.
+ perfetto::TrackEvent::SetProcessDescriptor(
+ [](perfetto::protos::pbzero::TrackDescriptor* desc) {
+ desc->set_name("noop.exe");
+ });
+
+ std::vector<char> raw_trace = tracing_session->get()->ReadTraceBlocking();
+ perfetto::protos::gen::Trace trace;
+ ASSERT_TRUE(trace.ParseFromArray(raw_trace.data(), raw_trace.size()));
+
+ std::vector<perfetto::protos::gen::TrackDescriptor> descs;
+ std::vector<perfetto::protos::gen::TrackDescriptor> thread_descs;
+ constexpr uint32_t kMainThreadSequence = 2;
+ for (const auto& packet : trace.packet()) {
+ if (packet.has_track_descriptor()) {
+ if (packet.trusted_packet_sequence_id() == kMainThreadSequence) {
+ descs.push_back(packet.track_descriptor());
+ } else {
+ thread_descs.push_back(packet.track_descriptor());
+ }
+ }
+ }
+
+ // The main thread records the initial process name as well as the one that's
+ // set during tracing. Additionally it records a thread descriptor for the
+ // main thread.
+
+ EXPECT_EQ(3u, descs.size());
+
+ // Default track for the main thread.
+ EXPECT_EQ(0, descs[0].process().pid());
+ EXPECT_NE(0, descs[0].thread().pid());
+
+ // First process descriptor.
+ EXPECT_NE(0, descs[1].process().pid());
+ EXPECT_EQ("hello.exe", descs[1].name());
+
+ // Second process descriptor.
+ EXPECT_NE(0, descs[2].process().pid());
+ EXPECT_EQ("goodbye.exe", descs[2].name());
+
+ // The child thread records only its own thread descriptor (twice, since it
+ // was mutated).
+ EXPECT_EQ(2u, thread_descs.size());
+ EXPECT_EQ("TestThread", thread_descs[0].name());
+ EXPECT_NE(0, thread_descs[0].thread().pid());
+ EXPECT_NE(0, thread_descs[0].thread().tid());
+ EXPECT_EQ("TestThread", thread_descs[1].name());
+ EXPECT_NE(0, thread_descs[1].thread().pid());
+ EXPECT_NE(0, thread_descs[1].thread().tid());
+}
+
+TEST_F(PerfettoApiTest, TrackEventCustomTrack) {
+ // Setup the trace config.
+ perfetto::TraceConfig cfg;
+ cfg.set_duration_ms(500);
+ cfg.add_buffers()->set_size_kb(1024);
+ auto* ds_cfg = cfg.add_data_sources()->mutable_config();
+ ds_cfg->set_name("track_event");
+ ds_cfg->set_legacy_config("bar");
+
+ // Create a new trace session.
+ auto* tracing_session = NewTrace(cfg);
+ tracing_session->get()->StartBlocking();
+
+ // Declare a custom track and give it a name.
+ uint64_t async_id = 123;
+ perfetto::TrackEvent::SetTrackDescriptor(
+ perfetto::Track(async_id),
+ [](perfetto::protos::pbzero::TrackDescriptor* desc) {
+ desc->set_name("MyCustomTrack");
+ });
+
+ // Start events on one thread and end them on another.
+ TRACE_EVENT_BEGIN("bar", "AsyncEvent", perfetto::Track(async_id), "debug_arg",
+ 123);
+
+ TRACE_EVENT_BEGIN("bar", "SubEvent", perfetto::Track(async_id),
+ [](perfetto::EventContext) {});
+ const auto main_thread_track =
+ perfetto::Track(async_id, perfetto::ThreadTrack::Current());
+ std::thread thread([&] {
+ TRACE_EVENT_END("bar", perfetto::Track(async_id));
+ TRACE_EVENT_END("bar", perfetto::Track(async_id), "arg1", false, "arg2",
+ true);
+ const auto thread_track =
+ perfetto::Track(async_id, perfetto::ThreadTrack::Current());
+ // Thread-scoped tracks will have different uuids on different thread even
+ // if the id matches.
+ ASSERT_NE(main_thread_track.uuid, thread_track.uuid);
+ });
+ thread.join();
+
+ perfetto::TrackEvent::Flush();
+ tracing_session->get()->StopBlocking();
+
+ std::vector<char> raw_trace = tracing_session->get()->ReadTraceBlocking();
+ perfetto::protos::gen::Trace trace;
+ ASSERT_TRUE(trace.ParseFromArray(raw_trace.data(), raw_trace.size()));
+
+ // Check that the track uuids match on the begin and end events.
+ const auto track = perfetto::Track(async_id);
+ constexpr uint32_t kMainThreadSequence = 2;
+ int event_count = 0;
+ bool found_descriptor = false;
+ for (const auto& packet : trace.packet()) {
+ if (packet.has_track_descriptor() &&
+ !packet.track_descriptor().has_process() &&
+ !packet.track_descriptor().has_thread()) {
+ auto td = packet.track_descriptor();
+ EXPECT_EQ("MyCustomTrack", td.name());
+ EXPECT_EQ(track.uuid, td.uuid());
+ EXPECT_EQ(perfetto::ProcessTrack::Current().uuid, td.parent_uuid());
+ found_descriptor = true;
+ continue;
+ }
+
+ if (!packet.has_track_event())
+ continue;
+ auto track_event = packet.track_event();
+ if (track_event.type() ==
+ perfetto::protos::gen::TrackEvent::TYPE_SLICE_BEGIN) {
+ EXPECT_EQ(kMainThreadSequence, packet.trusted_packet_sequence_id());
+ EXPECT_EQ(track.uuid, track_event.track_uuid());
+ } else {
+ EXPECT_NE(kMainThreadSequence, packet.trusted_packet_sequence_id());
+ EXPECT_EQ(track.uuid, track_event.track_uuid());
+ }
+ event_count++;
+ }
+ EXPECT_TRUE(found_descriptor);
+ EXPECT_EQ(4, event_count);
+ perfetto::TrackEvent::EraseTrackDescriptor(track);
+}
+
+TEST_F(PerfettoApiTest, TrackEventAnonymousCustomTrack) {
+ // Setup the trace config.
+ perfetto::TraceConfig cfg;
+ cfg.set_duration_ms(500);
+ cfg.add_buffers()->set_size_kb(1024);
+ auto* ds_cfg = cfg.add_data_sources()->mutable_config();
+ ds_cfg->set_name("track_event");
+ ds_cfg->set_legacy_config("bar");
+
+ // Create a new trace session.
+ auto* tracing_session = NewTrace(cfg);
+ tracing_session->get()->StartBlocking();
+
+ // Emit an async event without giving it an explicit descriptor.
+ uint64_t async_id = 4004;
+ auto track = perfetto::Track(async_id, perfetto::ThreadTrack::Current());
+ TRACE_EVENT_BEGIN("bar", "AsyncEvent", track);
+ std::thread thread([&] { TRACE_EVENT_END("bar", track); });
+ thread.join();
+
+ perfetto::TrackEvent::Flush();
+ tracing_session->get()->StopBlocking();
+
+ std::vector<char> raw_trace = tracing_session->get()->ReadTraceBlocking();
+ perfetto::protos::gen::Trace trace;
+ ASSERT_TRUE(trace.ParseFromArray(raw_trace.data(), raw_trace.size()));
+
+ // Check that a descriptor for the track was emitted.
+ bool found_descriptor = false;
+ for (const auto& packet : trace.packet()) {
+ if (packet.has_track_descriptor() &&
+ !packet.track_descriptor().has_process() &&
+ !packet.track_descriptor().has_thread()) {
+ auto td = packet.track_descriptor();
+ EXPECT_EQ(track.uuid, td.uuid());
+ EXPECT_EQ(perfetto::ThreadTrack::Current().uuid, td.parent_uuid());
+ found_descriptor = true;
+ }
+ }
+ EXPECT_TRUE(found_descriptor);
+}
+
TEST_F(PerfettoApiTest, TrackEventTypedArgs) {
// Setup the trace config.
perfetto::TraceConfig cfg;
@@ -1039,22 +1288,21 @@
tracing_session->get()->StartBlocking();
size_t body_iid;
- TRACE_EVENT_BEGIN(
- "foo", "EventWithState", [&](perfetto::EventContext ctx) {
- // Test using a dynamically created interned value.
- body_iid = InternedLogMessageBodyHashed::Get(
- &ctx, std::string("Though this ") + "be madness,");
- auto log = ctx.event()->set_log_message();
- log->set_body_iid(body_iid);
+ TRACE_EVENT_BEGIN("foo", "EventWithState", [&](perfetto::EventContext ctx) {
+ // Test using a dynamically created interned value.
+ body_iid = InternedLogMessageBodyHashed::Get(
+ &ctx, std::string("Though this ") + "be madness,");
+ auto log = ctx.event()->set_log_message();
+ log->set_body_iid(body_iid);
- auto body_iid2 =
- InternedLogMessageBodyHashed::Get(&ctx, "Though this be madness,");
- EXPECT_EQ(body_iid, body_iid2);
+ auto body_iid2 =
+ InternedLogMessageBodyHashed::Get(&ctx, "Though this be madness,");
+ EXPECT_EQ(body_iid, body_iid2);
- auto body_iid3 =
- InternedLogMessageBodyHashed::Get(&ctx, "yet there is method in’t");
- EXPECT_NE(body_iid, body_iid3);
- });
+ auto body_iid3 =
+ InternedLogMessageBodyHashed::Get(&ctx, "yet there is method in’t");
+ EXPECT_NE(body_iid, body_iid3);
+ });
TRACE_EVENT_END("foo");
tracing_session->get()->StopBlocking();
@@ -1151,10 +1399,10 @@
tracing_session->get()->StopBlocking();
auto slices = ReadSlicesFromTrace(tracing_session->get());
- EXPECT_THAT(slices, ElementsAre("B:test.TestEventWithArgs", "E:test.",
- "B:test.SingleLineTestEvent", "E:test.",
- "B:test.TestEvent", "B:test.AnotherEvent",
- "E:test.", "E:test."));
+ EXPECT_THAT(
+ slices,
+ ElementsAre("B:test.TestEventWithArgs", "E", "B:test.SingleLineTestEvent",
+ "E", "B:test.TestEvent", "B:test.AnotherEvent", "E", "E"));
}
TEST_F(PerfettoApiTest, TrackEventInstant) {
@@ -1224,23 +1472,15 @@
ds_cfg->set_name("track_event");
ds_cfg->set_legacy_config("test");
- class MyDebugAnnotation : public perfetto::DebugAnnotation {
- public:
- ~MyDebugAnnotation() override = default;
-
- void Add(
- perfetto::protos::pbzero::DebugAnnotation* annotation) const override {
- annotation->set_legacy_json_value(R"({"key": 123})");
- }
- };
-
// Create a new trace session.
auto* tracing_session = NewTrace(cfg);
tracing_session->get()->StartBlocking();
+ std::unique_ptr<MyDebugAnnotation> owned_annotation(new MyDebugAnnotation());
+
TRACE_EVENT_BEGIN("test", "E", "custom_arg", MyDebugAnnotation());
TRACE_EVENT_BEGIN("test", "E", "normal_arg", "x", "custom_arg",
- MyDebugAnnotation());
+ std::move(owned_annotation));
perfetto::TrackEvent::Flush();
tracing_session->get()->StopBlocking();
@@ -1717,6 +1957,117 @@
EXPECT_EQ(packets_found, 1 | 2 | 4 | 8);
}
+TEST_F(PerfettoApiTest, LegacyTraceEvents) {
+ // TODO(skyostil): For now we just test that all variants of legacy trace
+ // points compile. Test actual functionality when implemented.
+
+ // Setup the trace config.
+ perfetto::TraceConfig cfg;
+ cfg.set_duration_ms(500);
+ cfg.add_buffers()->set_size_kb(1024);
+ auto* ds_cfg = cfg.add_data_sources()->mutable_config();
+ ds_cfg->set_name("track_event");
+
+ // Create a new trace session.
+ auto* tracing_session = NewTrace(cfg);
+ tracing_session->get()->StartBlocking();
+
+ // Basic events.
+ TRACE_EVENT_INSTANT0("cat", "LegacyEvent", TRACE_EVENT_SCOPE_GLOBAL);
+ TRACE_EVENT_BEGIN1("cat", "LegacyEvent", "arg", 123);
+ TRACE_EVENT_END2("cat", "LegacyEvent", "arg", "string", "arg2", 0.123f);
+
+ // Scoped event.
+ { TRACE_EVENT0("cat", "ScopedLegacyEvent"); }
+
+ // Event with flow (and disabled category).
+ TRACE_EVENT_WITH_FLOW0(TRACE_DISABLED_BY_DEFAULT("cat"), "LegacyFlowEvent",
+ 0xdadacafe, TRACE_EVENT_FLAG_FLOW_IN);
+
+ // Event with timestamp.
+ TRACE_EVENT_INSTANT_WITH_TIMESTAMP0("cat", "LegacyInstantEvent",
+ TRACE_EVENT_SCOPE_GLOBAL, 123456789ul);
+
+ // Event with id, thread id and timestamp (and dynamic name).
+ TRACE_EVENT_COPY_BEGIN_WITH_ID_TID_AND_TIMESTAMP0(
+ "cat", std::string("LegacyWithIdTidAndTimestamp").c_str(), 1, 2, 3);
+
+ // Event with id.
+ TRACE_COUNTER1("cat", "LegacyCounter", 1234);
+ TRACE_COUNTER_ID1("cat", "LegacyCounterWithId", 1234, 9000);
+
+ // Metadata event.
+ TRACE_EVENT_METADATA1("cat", "LegacyMetadata", "obsolete", true);
+
+ perfetto::TrackEvent::Flush();
+ tracing_session->get()->StopBlocking();
+ auto slices = ReadSlicesFromTrace(tracing_session->get());
+ EXPECT_THAT(
+ slices,
+ ElementsAre("I:cat.LegacyEvent", "B:cat.LegacyEvent(arg=(int)123)",
+ "E.LegacyEvent(arg=(string)string,arg2=(double)0.123)",
+ "B:cat.ScopedLegacyEvent", "E",
+ "Legacy_C:cat.LegacyCounter(value=(int)1234)"));
+}
+
+TEST_F(PerfettoApiTest, LegacyTraceEventsWithCustomAnnotation) {
+ // Setup the trace config.
+ perfetto::TraceConfig cfg;
+ cfg.set_duration_ms(500);
+ cfg.add_buffers()->set_size_kb(1024);
+ auto* ds_cfg = cfg.add_data_sources()->mutable_config();
+ ds_cfg->set_name("track_event");
+
+ // Create a new trace session.
+ auto* tracing_session = NewTrace(cfg);
+ tracing_session->get()->StartBlocking();
+
+ MyDebugAnnotation annotation;
+ TRACE_EVENT_BEGIN1("cat", "LegacyEvent", "arg", annotation);
+
+ std::unique_ptr<MyDebugAnnotation> owned_annotation(new MyDebugAnnotation());
+ TRACE_EVENT_BEGIN1("cat", "LegacyEvent", "arg", std::move(owned_annotation));
+
+ perfetto::TrackEvent::Flush();
+ tracing_session->get()->StopBlocking();
+ auto slices = ReadSlicesFromTrace(tracing_session->get());
+ EXPECT_THAT(slices,
+ ElementsAre("B:cat.LegacyEvent(arg=(json){\"key\": 123})",
+ "B:cat.LegacyEvent(arg=(json){\"key\": 123})"));
+}
+
+TEST_F(PerfettoApiTest, LegacyTraceEventsWithConcurrentSessions) {
+ // Make sure that a uniquely owned debug annotation can be written into
+ // multiple concurrent tracing sessions.
+
+ // Setup the trace config.
+ perfetto::TraceConfig cfg;
+ cfg.set_duration_ms(500);
+ cfg.add_buffers()->set_size_kb(1024);
+ auto* ds_cfg = cfg.add_data_sources()->mutable_config();
+ ds_cfg->set_name("track_event");
+
+ auto* tracing_session = NewTrace(cfg);
+ tracing_session->get()->StartBlocking();
+
+ auto* tracing_session2 = NewTrace(cfg);
+ tracing_session2->get()->StartBlocking();
+
+ std::unique_ptr<MyDebugAnnotation> owned_annotation(new MyDebugAnnotation());
+ TRACE_EVENT_BEGIN1("cat", "LegacyEvent", "arg", std::move(owned_annotation));
+
+ perfetto::TrackEvent::Flush();
+ tracing_session->get()->StopBlocking();
+ auto slices = ReadSlicesFromTrace(tracing_session->get());
+ EXPECT_THAT(slices,
+ ElementsAre("B:cat.LegacyEvent(arg=(json){\"key\": 123})"));
+
+ tracing_session2->get()->StopBlocking();
+ slices = ReadSlicesFromTrace(tracing_session2->get());
+ EXPECT_THAT(slices,
+ ElementsAre("B:cat.LegacyEvent(arg=(json){\"key\": 123})"));
+}
+
} // namespace
PERFETTO_DEFINE_DATA_SOURCE_STATIC_MEMBERS(MockDataSource);
diff --git a/src/tracing/test/api_test_support.cc b/src/tracing/test/api_test_support.cc
index 24d8d67..1667ffc 100644
--- a/src/tracing/test/api_test_support.cc
+++ b/src/tracing/test/api_test_support.cc
@@ -16,8 +16,8 @@
#include "src/tracing/test/api_test_support.h"
+#include "perfetto/base/proc_utils.h"
#include "perfetto/base/time.h"
-#include "perfetto/ext/base/proc_utils.h"
namespace perfetto {
namespace test {
diff --git a/src/tracing/test/fake_producer_endpoint.h b/src/tracing/test/fake_producer_endpoint.h
index fc364cf..c01ef91 100644
--- a/src/tracing/test/fake_producer_endpoint.h
+++ b/src/tracing/test/fake_producer_endpoint.h
@@ -44,7 +44,7 @@
BufferExhaustedPolicy) override {
return nullptr;
}
- SharedMemoryArbiter* GetInProcessShmemArbiter() override { return nullptr; }
+ SharedMemoryArbiter* MaybeSharedMemoryArbiter() override { return nullptr; }
CommitDataRequest last_commit_data_request;
CommitDataCallback last_commit_data_callback;
diff --git a/src/tracing/test/tracing_module.cc b/src/tracing/test/tracing_module.cc
index 09b6e5f..d4fef2e 100644
--- a/src/tracing/test/tracing_module.cc
+++ b/src/tracing/test/tracing_module.cc
@@ -82,4 +82,25 @@
puts("Hello");
}
+void FunctionWithOneTrackEventWithCustomTrack() {
+ TRACE_EVENT_BEGIN("cat1", "EventWithTrack", perfetto::Track(8086));
+ // Simulates the non-tracing work of this function, which should take priority
+ // over the above trace event in terms of instruction scheduling.
+ puts("Hello");
+}
+
+void FunctionWithOneLegacyEvent() {
+ TRACE_EVENT_BEGIN("cat1", "LegacyEventWithArgs", "arg1", 42, "arg2", .5f);
+ // Simulates the non-tracing work of this function, which should take priority
+ // over the above trace event in terms of instruction scheduling.
+ puts("Hello");
+}
+
+void FunctionWithOneScopedLegacyEvent() {
+ TRACE_EVENT("cat1", "ScopedLegacyEventWithArgs", "arg1", 42, "arg2", .5f);
+ // Simulates the non-tracing work of this function, which should take priority
+ // over the above trace event in terms of instruction scheduling.
+ puts("Hello");
+}
+
} // namespace tracing_module
diff --git a/src/tracing/test/tracing_module.h b/src/tracing/test/tracing_module.h
index e0fd1b3..7ed9364 100644
--- a/src/tracing/test/tracing_module.h
+++ b/src/tracing/test/tracing_module.h
@@ -37,6 +37,11 @@
void FunctionWithOneTrackEventWithTypedArgument();
void FunctionWithOneScopedTrackEvent();
void FunctionWithOneTrackEventWithDebugAnnotations();
+void FunctionWithOneTrackEventWithCustomTrack();
+
+// Legacy events.
+void FunctionWithOneLegacyEvent();
+void FunctionWithOneScopedLegacyEvent();
} // namespace tracing_module
diff --git a/src/tracing/test/tracing_module_categories.h b/src/tracing/test/tracing_module_categories.h
index f776894..b492db8 100644
--- a/src/tracing/test/tracing_module_categories.h
+++ b/src/tracing/test/tracing_module_categories.h
@@ -23,6 +23,7 @@
// categories can be written to the same trace writer.
#define PERFETTO_TRACK_EVENT_NAMESPACE tracing_module
+#define PERFETTO_ENABLE_LEGACY_TRACE_EVENTS 1
#include "perfetto/tracing.h"
diff --git a/src/tracing/tracing.cc b/src/tracing/tracing.cc
index fc6a696..8b20b7f 100644
--- a/src/tracing/tracing.cc
+++ b/src/tracing/tracing.cc
@@ -15,6 +15,7 @@
*/
#include "perfetto/tracing/tracing.h"
+#include "perfetto/tracing/internal/track_event_internal.h"
#include "src/tracing/internal/tracing_muxer_impl.h"
#include <condition_variable>
@@ -24,9 +25,20 @@
// static
void Tracing::Initialize(const TracingInitArgs& args) {
+ static bool was_initialized = false;
+ static TracingInitArgs init_args;
+ if (was_initialized) {
+ // Should not be reinitialized with different args.
+ PERFETTO_DCHECK(init_args == args);
+ return;
+ }
+
// Make sure the headers and implementation files agree on the build config.
PERFETTO_CHECK(args.dcheck_is_on_ == PERFETTO_DCHECK_IS_ON());
internal::TracingMuxerImpl::InitializeInstance(args);
+ internal::TrackRegistry::InitializeInstance();
+ was_initialized = true;
+ init_args = args;
}
// static
diff --git a/src/tracing/track.cc b/src/tracing/track.cc
new file mode 100644
index 0000000..b5260e4
--- /dev/null
+++ b/src/tracing/track.cc
@@ -0,0 +1,97 @@
+/*
+ * Copyright (C) 2019 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.
+ */
+
+#include "perfetto/tracing/track.h"
+
+#include "perfetto/ext/base/uuid.h"
+#include "perfetto/tracing/internal/track_event_data_source.h"
+#include "protos/perfetto/trace/track_event/process_descriptor.pbzero.h"
+#include "protos/perfetto/trace/track_event/thread_descriptor.pbzero.h"
+
+namespace perfetto {
+
+// static
+uint64_t Track::process_uuid;
+
+void Track::Serialize(protos::pbzero::TrackDescriptor* desc) const {
+ desc->set_uuid(uuid);
+ if (parent_uuid)
+ desc->set_parent_uuid(parent_uuid);
+}
+
+void ProcessTrack::Serialize(protos::pbzero::TrackDescriptor* desc) const {
+ Track::Serialize(desc);
+ auto pd = desc->set_process();
+ pd->set_pid(static_cast<int32_t>(pid));
+ // TODO(skyostil): Record command line.
+}
+
+void ThreadTrack::Serialize(protos::pbzero::TrackDescriptor* desc) const {
+ Track::Serialize(desc);
+ auto td = desc->set_thread();
+ td->set_pid(static_cast<int32_t>(pid));
+ td->set_tid(static_cast<int32_t>(tid));
+ // TODO(skyostil): Record thread name.
+}
+
+namespace internal {
+
+// static
+TrackRegistry* TrackRegistry::instance_;
+
+TrackRegistry::TrackRegistry() = default;
+TrackRegistry::~TrackRegistry() = default;
+
+// static
+void TrackRegistry::InitializeInstance() {
+ // TODO(eseckler): Chrome may call this more than once. Once Chrome doesn't
+ // call this directly anymore, bring back DCHECK(!instance_) instead.
+ if (instance_)
+ return;
+ instance_ = new TrackRegistry();
+ Track::process_uuid = static_cast<uint64_t>(base::Uuidv4().lsb());
+}
+
+void TrackRegistry::UpdateTrackImpl(
+ Track track,
+ std::function<void(protos::pbzero::TrackDescriptor*)> fill_function) {
+ constexpr size_t kInitialSliceSize = 32;
+ constexpr size_t kMaximumSliceSize = 4096;
+ protozero::HeapBuffered<protos::pbzero::TrackDescriptor> new_descriptor(
+ kInitialSliceSize, kMaximumSliceSize);
+ fill_function(new_descriptor.get());
+ auto serialized_desc = new_descriptor.SerializeAsString();
+ {
+ std::lock_guard<std::mutex> lock(mutex_);
+ tracks_[track.uuid] = std::move(serialized_desc);
+ }
+}
+
+void TrackRegistry::EraseTrack(Track track) {
+ std::lock_guard<std::mutex> lock(mutex_);
+ tracks_.erase(track.uuid);
+}
+
+// static
+void TrackRegistry::WriteTrackDescriptor(
+ const SerializedTrackDescriptor& desc,
+ protozero::MessageHandle<protos::pbzero::TracePacket> packet) {
+ packet->AppendString(
+ perfetto::protos::pbzero::TracePacket::kTrackDescriptorFieldNumber, desc);
+}
+
+} // namespace internal
+} // namespace perfetto
diff --git a/test/BUILD.gn b/test/BUILD.gn
index 3388f02..7d16a3e 100644
--- a/test/BUILD.gn
+++ b/test/BUILD.gn
@@ -19,8 +19,6 @@
source_set("end_to_end_integrationtests") {
testonly = true
deps = [
- ":task_runner_thread",
- ":task_runner_thread_delegates",
":test_helper",
"../gn:default_deps",
"../gn:gtest_and_gmock",
@@ -37,9 +35,7 @@
"../src/base:test_support",
"../src/traced/probes/ftrace",
]
- sources = [
- "end_to_end_integrationtest.cc",
- ]
+ sources = [ "end_to_end_integrationtest.cc" ]
if (start_daemons_for_testing) {
cflags = [ "-DPERFETTO_START_DAEMONS_FOR_TESTING" ]
@@ -54,9 +50,7 @@
}
executable("client_api_example") {
- sources = [
- "client_api_example.cc",
- ]
+ sources = [ "client_api_example.cc" ]
deps = [
"..:libperfetto_client_experimental",
"../gn:default_deps",
@@ -68,27 +62,22 @@
}
perfetto_fuzzer_test("end_to_end_shared_memory_fuzzer") {
- sources = [
- "end_to_end_shared_memory_fuzzer.cc",
- ]
+ sources = [ "end_to_end_shared_memory_fuzzer.cc" ]
testonly = true
deps = [
- ":task_runner_thread",
- ":task_runner_thread_delegates",
":test_helper",
"../gn:default_deps",
"../protos/perfetto/trace:zero",
"../src/base:test_support",
"../src/protozero",
- "../src/tracing",
- "../src/tracing:ipc",
+ "../src/tracing/core",
+ "../src/tracing/ipc/producer",
+ "../src/tracing/ipc/service",
]
}
perfetto_fuzzer_test("producer_socket_fuzzer") {
- sources = [
- "producer_socket_fuzzer.cc",
- ]
+ sources = [ "producer_socket_fuzzer.cc" ]
testonly = true
deps = [
":test_helper",
@@ -98,53 +87,25 @@
]
}
-source_set("task_runner_thread") {
- testonly = true
- deps = [
- "../gn:default_deps",
- "../src/base",
- "../src/base:test_support",
- ]
- sources = [
- "task_runner_thread.cc",
- "task_runner_thread.h",
- ]
-}
-
-source_set("task_runner_thread_delegates") {
- testonly = true
- deps = [
- ":task_runner_thread",
- "../gn:default_deps",
- "../include/perfetto/ext/traced",
- "../protos/perfetto/config:cpp",
- "../src/base:test_support",
- "../src/traced/probes:probes_src",
- "../src/tracing:ipc",
- ]
- sources = [
- "fake_producer.cc",
- "fake_producer.h",
- "task_runner_thread_delegates.cc",
- "task_runner_thread_delegates.h",
- ]
-}
-
source_set("test_helper") {
testonly = true
public_deps = [
"../protos/perfetto/trace:cpp",
- "../src/tracing:ipc",
+ "../src/tracing/ipc/consumer",
+ "../src/tracing/ipc/producer",
+ "../src/tracing/ipc/service",
]
deps = [
- ":task_runner_thread",
- ":task_runner_thread_delegates",
"../gn:default_deps",
"../include/perfetto/ext/traced",
+ "../protos/perfetto/config:cpp",
"../protos/perfetto/trace:zero",
"../src/base:test_support",
+ "../src/traced/probes:probes_src",
]
sources = [
+ "fake_producer.cc",
+ "fake_producer.h",
"test_helper.cc",
"test_helper.h",
]
@@ -157,8 +118,6 @@
source_set("end_to_end_benchmarks") {
testonly = true
deps = [
- ":task_runner_thread",
- ":task_runner_thread_delegates",
":test_helper",
"../gn:benchmark",
"../gn:default_deps",
@@ -169,9 +128,7 @@
"../protos/perfetto/trace:zero",
"../src/base:test_support",
]
- sources = [
- "end_to_end_benchmark.cc",
- ]
+ sources = [ "end_to_end_benchmark.cc" ]
if (start_daemons_for_testing) {
cflags = [ "-DPERFETTO_START_DAEMONS_FOR_TESTING" ]
}
@@ -183,8 +140,6 @@
"../gn:benchmark",
"../gn:default_deps",
]
- sources = [
- "benchmark_main.cc",
- ]
+ sources = [ "benchmark_main.cc" ]
}
} # if (enable_perfetto_benchmarks)
diff --git a/test/benchmark_main.cc b/test/benchmark_main.cc
index e410e52..3a3feaa 100644
--- a/test/benchmark_main.cc
+++ b/test/benchmark_main.cc
@@ -14,4 +14,4 @@
#include <benchmark/benchmark.h>
-BENCHMARK_MAIN();
+BENCHMARK_MAIN()
diff --git a/test/configs/BUILD.gn b/test/configs/BUILD.gn
index 2ce30f6..0dc0d35 100644
--- a/test/configs/BUILD.gn
+++ b/test/configs/BUILD.gn
@@ -42,9 +42,7 @@
"sys_stats.cfg",
]
- outputs = [
- "$root_out_dir/{{source_file_part}}.protobuf",
- ]
+ outputs = [ "$root_out_dir/{{source_file_part}}.protobuf" ]
# Retrieves the path where protoc is built relative to the dir where commands
# are ran (root_build_dir == out/xxx). protoc_rel_dir ends up being "." for
diff --git a/test/cts/AndroidTest.xml b/test/cts/AndroidTest.xml
index 8ec9da3..aff1988 100644
--- a/test/cts/AndroidTest.xml
+++ b/test/cts/AndroidTest.xml
@@ -33,7 +33,6 @@
<option name="append-bitness" value="true" />
</target_preparer>
<target_preparer class="com.android.tradefed.targetprep.RunCommandTargetPreparer">
- <option name="run-command" value="setprop persist.traced.enable 1" />
<option name="run-command" value="setprop persist.heapprofd.enable 1" />
<option name="run-command" value="am start -n android.perfetto.producer/.ProducerActivity" />
</target_preparer>
diff --git a/test/cts/BUILD.gn b/test/cts/BUILD.gn
index 4ecb26c..84aba0c 100644
--- a/test/cts/BUILD.gn
+++ b/test/cts/BUILD.gn
@@ -20,6 +20,7 @@
complete_static_lib = true
testonly = true
deps = [
+ "..:end_to_end_integrationtests",
"../..:libperfetto_client_experimental",
"../../gn:default_deps",
"../../gn:gtest_and_gmock",
@@ -39,3 +40,13 @@
"utils.cc",
]
}
+
+static_library("perfetto_cts_jni_deps") {
+ complete_static_lib = true
+ testonly = true
+ deps = [
+ "..:test_helper",
+ "../../gn:default_deps",
+ "../../src/base:test_support",
+ ]
+}
diff --git a/test/cts/producer/jni/fake_producer_jni.cc b/test/cts/producer/jni/fake_producer_jni.cc
index 47d4356..ab587a8 100644
--- a/test/cts/producer/jni/fake_producer_jni.cc
+++ b/test/cts/producer/jni/fake_producer_jni.cc
@@ -19,33 +19,99 @@
#include "perfetto/ext/traced/traced.h"
#include "perfetto/ext/tracing/ipc/default_socket.h"
-#include "src/base/test/test_task_runner.h"
+#include "perfetto/ext/base/unix_task_runner.h"
#include "test/fake_producer.h"
+namespace {
+
+static std::mutex g_mutex;
+
+// These variables are guarded by the above mutex.
+static perfetto::base::UnixTaskRunner* g_activity_tr = nullptr;
+static perfetto::base::UnixTaskRunner* g_service_tr = nullptr;
+static perfetto::base::UnixTaskRunner* g_isolated_service_tr = nullptr;
+
+} // namespace
+
namespace perfetto {
namespace {
-void ListenAndRespond(const std::string& name) {
- base::TestTaskRunner task_runner;
+
+void ListenAndRespond(const std::string& name, base::UnixTaskRunner** tr) {
+ // Note that this lock is unlocked by a post task in the middle of the
+ // function instead of at the end of this function.
+ std::unique_lock<std::mutex> lock(g_mutex);
+
+ // Ensure that we don't create multiple instances of the same producer.
+ // If the passed task runner is non-null, that means it's still running
+ // so we don't need to create another instance.
+ if (*tr)
+ return;
+
+ // Post a task to unlock the mutex when the runner has started executing
+ // tasks.
+ base::UnixTaskRunner task_runner;
+ task_runner.PostTask([tr, &lock, &task_runner]() {
+ *tr = &task_runner;
+ lock.unlock();
+ });
+
FakeProducer producer(name);
producer.Connect(GetProducerSocket(), &task_runner, [] {}, [] {});
task_runner.Run();
+
+ // Cleanup the task runner again to remove outside visibilty so we can
+ // create new instances of the producer.
+ {
+ std::lock_guard<std::mutex> guard(g_mutex);
+ *tr = nullptr;
+ }
}
+
} // namespace
} // namespace perfetto
extern "C" JNIEXPORT void JNICALL
+Java_android_perfetto_producer_ProducerActivity_quitTaskRunner(JNIEnv*,
+ jclass) {
+ std::lock_guard<std::mutex> guard(g_mutex);
+ if (g_activity_tr) {
+ g_activity_tr->Quit();
+ }
+}
+
+extern "C" JNIEXPORT void JNICALL
+Java_android_perfetto_producer_ProducerIsolatedService_quitTaskRunner(JNIEnv*,
+ jclass) {
+ std::lock_guard<std::mutex> guard(g_mutex);
+ if (g_isolated_service_tr) {
+ g_isolated_service_tr->Quit();
+ }
+}
+
+extern "C" JNIEXPORT void JNICALL
+Java_android_perfetto_producer_ProducerService_quitTaskRunner(JNIEnv*, jclass) {
+ std::lock_guard<std::mutex> guard(g_mutex);
+ if (g_service_tr) {
+ g_service_tr->Quit();
+ }
+}
+
+extern "C" JNIEXPORT void JNICALL
Java_android_perfetto_producer_ProducerActivity_setupProducer(JNIEnv*, jclass) {
- perfetto::ListenAndRespond("android.perfetto.cts.ProducerActivity");
+ perfetto::ListenAndRespond("android.perfetto.cts.ProducerActivity",
+ &g_activity_tr);
}
extern "C" JNIEXPORT void JNICALL
Java_android_perfetto_producer_ProducerIsolatedService_setupProducer(JNIEnv*,
jclass) {
- perfetto::ListenAndRespond("android.perfetto.cts.ProducerIsolatedService");
+ perfetto::ListenAndRespond("android.perfetto.cts.ProducerIsolatedService",
+ &g_isolated_service_tr);
}
extern "C" JNIEXPORT void JNICALL
Java_android_perfetto_producer_ProducerService_setupProducer(JNIEnv*, jclass) {
- perfetto::ListenAndRespond("android.perfetto.cts.ProducerService");
+ perfetto::ListenAndRespond("android.perfetto.cts.ProducerService",
+ &g_service_tr);
}
diff --git a/test/cts/producer/src/android/perfetto/producer/ProducerActivity.java b/test/cts/producer/src/android/perfetto/producer/ProducerActivity.java
index 1eedfe3..5a8e0c9 100644
--- a/test/cts/producer/src/android/perfetto/producer/ProducerActivity.java
+++ b/test/cts/producer/src/android/perfetto/producer/ProducerActivity.java
@@ -50,6 +50,9 @@
startForegroundService(new Intent(ProducerActivity.this, ProducerIsolatedService.class));
System.loadLibrary("perfettocts_jni");
+
+ // We make sure at the C++ level that we don't setup multiple producers in the same
+ // process.
new Thread(new Runnable() {
public void run() {
try {
@@ -58,9 +61,17 @@
ex.printStackTrace();
}
}
- })
- .start();
+ }).start();
+ }
+
+ @Override
+ public void onDestroy() {
+ super.onDestroy();
+
+ quitTaskRunner();
}
private static native void setupProducer();
+
+ private static native void quitTaskRunner();
}
diff --git a/test/cts/producer/src/android/perfetto/producer/ProducerIsolatedService.java b/test/cts/producer/src/android/perfetto/producer/ProducerIsolatedService.java
index 9f26f54..943cab9 100644
--- a/test/cts/producer/src/android/perfetto/producer/ProducerIsolatedService.java
+++ b/test/cts/producer/src/android/perfetto/producer/ProducerIsolatedService.java
@@ -58,7 +58,11 @@
}
@Override
- public void onDestroy() {}
+ public void onDestroy() {
+ quitTaskRunner();
+ }
private static native void setupProducer();
+
+ private static native void quitTaskRunner();
}
diff --git a/test/cts/producer/src/android/perfetto/producer/ProducerService.java b/test/cts/producer/src/android/perfetto/producer/ProducerService.java
index a86267a..3b1c3cf 100644
--- a/test/cts/producer/src/android/perfetto/producer/ProducerService.java
+++ b/test/cts/producer/src/android/perfetto/producer/ProducerService.java
@@ -57,7 +57,11 @@
}
@Override
- public void onDestroy() {}
+ public void onDestroy() {
+ quitTaskRunner();
+ }
private static native void setupProducer();
+
+ private static native void quitTaskRunner();
}
diff --git a/test/end_to_end_benchmark.cc b/test/end_to_end_benchmark.cc
index 0668487..ff1fe74 100644
--- a/test/end_to_end_benchmark.cc
+++ b/test/end_to_end_benchmark.cc
@@ -22,8 +22,6 @@
#include "perfetto/tracing/core/trace_config.h"
#include "src/base/test/test_task_runner.h"
#include "test/gtest_and_gmock.h"
-#include "test/task_runner_thread.h"
-#include "test/task_runner_thread_delegates.h"
#include "test/test_helper.h"
#include "protos/perfetto/config/test_config.gen.h"
@@ -73,8 +71,10 @@
helper.WaitForProducerEnabled();
uint64_t wall_start_ns = static_cast<uint64_t>(base::GetWallTimeNs().count());
- uint64_t service_start_ns = helper.service_thread()->GetThreadCPUTimeNs();
- uint64_t producer_start_ns = helper.producer_thread()->GetThreadCPUTimeNs();
+ uint64_t service_start_ns =
+ helper.service_thread()->GetThreadCPUTimeNsForTesting();
+ uint64_t producer_start_ns =
+ helper.producer_thread()->GetThreadCPUTimeNsForTesting();
uint32_t iterations = 0;
for (auto _ : state) {
auto cname = "produced.and.committed." + std::to_string(iterations++);
@@ -83,9 +83,11 @@
task_runner.RunUntilCheckpoint(cname, time_for_messages_ms);
}
uint64_t service_ns =
- helper.service_thread()->GetThreadCPUTimeNs() - service_start_ns;
+ helper.service_thread()->GetThreadCPUTimeNsForTesting() -
+ service_start_ns;
uint64_t producer_ns =
- helper.producer_thread()->GetThreadCPUTimeNs() - producer_start_ns;
+ helper.producer_thread()->GetThreadCPUTimeNsForTesting() -
+ producer_start_ns;
uint64_t wall_ns =
static_cast<uint64_t>(base::GetWallTimeNs().count()) - wall_start_ns;
@@ -150,8 +152,8 @@
helper.WaitForProducerEnabled();
uint64_t wall_start_ns = static_cast<uint64_t>(base::GetWallTimeNs().count());
- uint64_t service_start_ns =
- static_cast<uint64_t>(helper.service_thread()->GetThreadCPUTimeNs());
+ uint64_t service_start_ns = static_cast<uint64_t>(
+ helper.service_thread()->GetThreadCPUTimeNsForTesting());
uint64_t consumer_start_ns =
static_cast<uint64_t>(base::GetThreadCPUTimeNs().count());
uint64_t read_time_taken_ns = 0;
@@ -193,7 +195,8 @@
}
}
uint64_t service_ns =
- helper.service_thread()->GetThreadCPUTimeNs() - service_start_ns;
+ helper.service_thread()->GetThreadCPUTimeNsForTesting() -
+ service_start_ns;
uint64_t consumer_ns =
static_cast<uint64_t>(base::GetThreadCPUTimeNs().count()) -
consumer_start_ns;
diff --git a/test/end_to_end_integrationtest.cc b/test/end_to_end_integrationtest.cc
index 209693d..52947df 100644
--- a/test/end_to_end_integrationtest.cc
+++ b/test/end_to_end_integrationtest.cc
@@ -35,8 +35,6 @@
#include "src/traced/probes/ftrace/ftrace_controller.h"
#include "src/traced/probes/ftrace/ftrace_procfs.h"
#include "test/gtest_and_gmock.h"
-#include "test/task_runner_thread.h"
-#include "test/task_runner_thread_delegates.h"
#include "test/test_helper.h"
#include "protos/perfetto/config/power/android_power_config.pbzero.h"
@@ -362,9 +360,8 @@
helper.StartServiceIfRequired();
#if PERFETTO_BUILDFLAG(PERFETTO_START_DAEMONS)
- TaskRunnerThread producer_thread("perfetto.prd");
- producer_thread.Start(std::unique_ptr<ProbesProducerDelegate>(
- new ProbesProducerDelegate(TEST_PRODUCER_SOCK_NAME)));
+ ProbesProducerThread probes(TEST_PRODUCER_SOCK_NAME);
+ probes.Connect();
#endif
helper.ConnectConsumer();
@@ -408,9 +405,8 @@
helper.StartServiceIfRequired();
#if PERFETTO_BUILDFLAG(PERFETTO_START_DAEMONS)
- TaskRunnerThread producer_thread("perfetto.prd");
- producer_thread.Start(std::unique_ptr<ProbesProducerDelegate>(
- new ProbesProducerDelegate(TEST_PRODUCER_SOCK_NAME)));
+ ProbesProducerThread probes(TEST_PRODUCER_SOCK_NAME);
+ probes.Connect();
#endif
helper.ConnectConsumer();
@@ -467,9 +463,8 @@
helper.StartServiceIfRequired();
#if PERFETTO_BUILDFLAG(PERFETTO_START_DAEMONS)
- TaskRunnerThread producer_thread("perfetto.prd");
- producer_thread.Start(std::unique_ptr<ProbesProducerDelegate>(
- new ProbesProducerDelegate(TEST_PRODUCER_SOCK_NAME)));
+ ProbesProducerThread probes(TEST_PRODUCER_SOCK_NAME);
+ probes.Connect();
#else
base::ignore_result(TEST_PRODUCER_SOCK_NAME);
#endif
diff --git a/test/end_to_end_shared_memory_fuzzer.cc b/test/end_to_end_shared_memory_fuzzer.cc
index 052f888..ce53acf 100644
--- a/test/end_to_end_shared_memory_fuzzer.cc
+++ b/test/end_to_end_shared_memory_fuzzer.cc
@@ -30,8 +30,6 @@
#include "perfetto/tracing/core/data_source_descriptor.h"
#include "protos/perfetto/trace/test_event.pbzero.h"
#include "src/base/test/test_task_runner.h"
-#include "test/task_runner_thread.h"
-#include "test/task_runner_thread_delegates.h"
#include "test/test_helper.h"
#include "protos/perfetto/trace/trace_packet.pbzero.h"
@@ -109,23 +107,33 @@
std::function<void()> on_produced_and_committed_;
};
-class FakeProducerDelegate : public ThreadDelegate {
+class FuzzerFakeProducerThread {
public:
- FakeProducerDelegate(const uint8_t* data,
- size_t size,
- std::function<void()> on_produced_and_committed)
+ FuzzerFakeProducerThread(const uint8_t* data,
+ size_t size,
+ std::function<void()> on_produced_and_committed)
: data_(data),
size_(size),
on_produced_and_committed_(on_produced_and_committed) {}
- ~FakeProducerDelegate() override = default;
- void Initialize(base::TaskRunner* task_runner) override {
- producer_.reset(new FakeProducer("android.perfetto.FakeProducer", data_,
- size_, on_produced_and_committed_));
- producer_->Connect(TEST_PRODUCER_SOCK_NAME, task_runner);
+ ~FuzzerFakeProducerThread() {
+ if (!runner_)
+ return;
+ runner_->PostTaskAndWaitForTesting([this]() { producer_.reset(); });
+ }
+
+ void Connect() {
+ runner_ = base::ThreadTaskRunner::CreateAndStart("perfetto.prd.fake");
+ runner_->PostTaskAndWaitForTesting([this]() {
+ producer_.reset(new FakeProducer("android.perfetto.FakeProducer", data_,
+ size_, on_produced_and_committed_));
+ producer_->Connect(TEST_PRODUCER_SOCK_NAME, runner_->get());
+ });
}
private:
+ base::Optional<base::ThreadTaskRunner> runner_; // Keep first.
+
std::unique_ptr<FakeProducer> producer_;
const uint8_t* data_;
const size_t size_;
@@ -140,11 +148,10 @@
TestHelper helper(&task_runner);
helper.StartServiceIfRequired();
- TaskRunnerThread producer_thread("perfetto.prd");
- producer_thread.Start(std::unique_ptr<FakeProducerDelegate>(
- new FakeProducerDelegate(data, size,
- helper.WrapTask(task_runner.CreateCheckpoint(
- "produced.and.committed")))));
+ auto cp =
+ helper.WrapTask(task_runner.CreateCheckpoint("produced.and.committed"));
+ FuzzerFakeProducerThread producer_thread(data, size, cp);
+ producer_thread.Connect();
helper.ConnectConsumer();
helper.WaitForConsumerConnect();
diff --git a/test/fake_producer.cc b/test/fake_producer.cc
index 17f80f0..730ec00 100644
--- a/test/fake_producer.cc
+++ b/test/fake_producer.cc
@@ -16,7 +16,6 @@
#include "test/fake_producer.h"
-#include <condition_variable>
#include <mutex>
#include "perfetto/base/logging.h"
diff --git a/test/metrics/java_heap_stats.out b/test/metrics/java_heap_stats.out
index 8ba3b96..53b9fb6 100644
--- a/test/metrics/java_heap_stats.out
+++ b/test/metrics/java_heap_stats.out
@@ -7,7 +7,7 @@
}
samples {
ts: 10
- heap_size: 480
+ heap_size: 736
reachable_heap_size: 96
}
}
diff --git a/test/metrics/trace_metadata.json.out b/test/metrics/trace_metadata.json.out
index c961b9e..031db4c 100644
--- a/test/metrics/trace_metadata.json.out
+++ b/test/metrics/trace_metadata.json.out
@@ -6,6 +6,7 @@
"value": 5
}
],
- "trace_duration_ns": 9519159074
+ "trace_duration_ns": 9519159074,
+ "trace_size_bytes": 6365447
}
}
diff --git a/test/metrics/trace_metadata.out b/test/metrics/trace_metadata.out
index c5ca0d8..80d5bad 100644
--- a/test/metrics/trace_metadata.out
+++ b/test/metrics/trace_metadata.out
@@ -3,5 +3,6 @@
name: "mismatched_sched_switch_tids"
value: 5
}
- trace_duration_ns: 9519159074
+ trace_duration_ns: 9519159074,
+ trace_size_bytes: 6365447
}
diff --git a/test/synth_common.py b/test/synth_common.py
index f950294..036f9b7 100644
--- a/test/synth_common.py
+++ b/test/synth_common.py
@@ -19,6 +19,8 @@
from google.protobuf.pyext import _message
CLONE_THREAD = 0x00010000
+CLONE_VFORK = 0x00004000
+CLONE_VM = 0x00000100
class Trace(object):
@@ -342,6 +344,18 @@
debug_marker.object = obj
debug_marker.object_name = obj_name
+ def add_vk_queue_submit(self, ts, dur, pid, tid, vk_queue, vk_command_buffers,
+ submission_id):
+ packet = self.add_packet()
+ packet.timestamp = ts
+ submit = (self.packet.vulkan_api_event.vk_queue_submit)
+ submit.duration_ns = dur
+ submit.pid = pid
+ submit.tid = tid
+ for cmd in vk_command_buffers:
+ submit.vk_command_buffers.append(cmd)
+ submit.submission_id = submission_id
+
def add_gpu_log(self, ts, severity, tag, message):
packet = self.add_packet()
packet.timestamp = ts
diff --git a/test/task_runner_thread.cc b/test/task_runner_thread.cc
deleted file mode 100644
index c625078..0000000
--- a/test/task_runner_thread.cc
+++ /dev/null
@@ -1,116 +0,0 @@
-/*
- * Copyright (C) 2018 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.
- */
-
-#include <pthread.h>
-#include <stdlib.h>
-#include <sys/syscall.h>
-#include <sys/types.h>
-#include <unistd.h>
-
-#include <condition_variable>
-#include <thread>
-
-#include "perfetto/base/time.h"
-#include "perfetto/ext/base/file_utils.h"
-#include "perfetto/ext/base/string_splitter.h"
-#include "test/task_runner_thread.h"
-
-namespace perfetto {
-
-TaskRunnerThread::TaskRunnerThread(const char* name) : name_(name) {}
-TaskRunnerThread::~TaskRunnerThread() {
- Stop();
-}
-
-void TaskRunnerThread::Start(std::unique_ptr<ThreadDelegate> delegate) {
- // Begin holding the lock for the condition variable.
- std::unique_lock<std::mutex> lock(mutex_);
-
- // Start the thread.
- PERFETTO_DCHECK(!runner_);
- thread_ = std::thread(&TaskRunnerThread::Run, this, std::move(delegate));
-
- // Wait for runner to be ready.
- ready_.wait_for(lock, std::chrono::seconds(10),
- [this]() { return runner_ != nullptr; });
-}
-
-void TaskRunnerThread::Stop() {
- {
- std::unique_lock<std::mutex> lock(mutex_);
- if (runner_)
- runner_->Quit();
- }
-
- if (thread_.joinable())
- thread_.join();
-}
-
-uint64_t TaskRunnerThread::GetThreadCPUTimeNs() {
- std::condition_variable cv;
- std::unique_lock<std::mutex> lock(mutex_);
- uint64_t thread_time_ns = 0;
-
- if (!runner_)
- return 0;
-
- runner_->PostTask([this, &thread_time_ns, &cv] {
- std::unique_lock<std::mutex> inner_lock(mutex_);
- thread_time_ns = static_cast<uint64_t>(base::GetThreadCPUTimeNs().count());
- cv.notify_one();
- });
-
- cv.wait(lock, [&thread_time_ns] { return thread_time_ns != 0; });
- return thread_time_ns;
-}
-
-void TaskRunnerThread::Run(std::unique_ptr<ThreadDelegate> delegate) {
-#if PERFETTO_BUILDFLAG(PERFETTO_OS_MACOSX)
- pthread_setname_np(name_);
-#else
- pthread_setname_np(pthread_self(), name_);
-#endif
-
- // Create the task runner and execute the specicalised code.
- base::UnixTaskRunner task_runner;
- delegate->Initialize(&task_runner);
-
- // Pass the runner back to the main thread.
- {
- std::unique_lock<std::mutex> lock(mutex_);
- runner_ = &task_runner;
- }
-
- // Notify the main thread that the runner is ready.
- ready_.notify_one();
-
- // Spin the loop.
- task_runner.Run();
-
- // Ensure we clear out the delegate before runner goes out
- // of scope.
- delegate.reset();
-
- // Cleanup the runner.
- {
- std::unique_lock<std::mutex> lock(mutex_);
- runner_ = nullptr;
- }
-}
-
-ThreadDelegate::~ThreadDelegate() = default;
-
-} // namespace perfetto
diff --git a/test/task_runner_thread.h b/test/task_runner_thread.h
deleted file mode 100644
index 354c308..0000000
--- a/test/task_runner_thread.h
+++ /dev/null
@@ -1,69 +0,0 @@
-/*
- * Copyright (C) 2018 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.
- */
-
-#ifndef TEST_TASK_RUNNER_THREAD_H_
-#define TEST_TASK_RUNNER_THREAD_H_
-
-#include <condition_variable>
-#include <mutex>
-#include <thread>
-
-#include "perfetto/base/task_runner.h"
-#include "src/base/test/test_task_runner.h"
-
-namespace perfetto {
-
-// Used to perform initialization work on a background TaskRunnerThread.
-class ThreadDelegate {
- public:
- virtual ~ThreadDelegate();
-
- // Invoked on the target thread before the message loop is started.
- virtual void Initialize(base::TaskRunner* task_runner) = 0;
-};
-
-// Background thread which spins a task runner until completed or the thread is
-// destroyed. If the thread is destroyed before the task runner completes, the
-// task runner is quit and the thread is joined.
-class TaskRunnerThread {
- public:
- explicit TaskRunnerThread(const char* name);
- ~TaskRunnerThread();
-
- // Blocks until the thread has been created and Initialize() has been
- // called.
- void Start(std::unique_ptr<ThreadDelegate> delegate);
-
- // Blocks until the thread has been stopped and joined.
- void Stop();
-
- uint64_t GetThreadCPUTimeNs();
-
- private:
- void Run(std::unique_ptr<ThreadDelegate> delegate);
-
- const char* const name_;
- std::thread thread_;
- std::condition_variable ready_;
-
- // All variables below this point are protected by |mutex_|.
- std::mutex mutex_;
- base::UnixTaskRunner* runner_ = nullptr;
-};
-
-} // namespace perfetto
-
-#endif // TEST_TASK_RUNNER_THREAD_H_
diff --git a/test/task_runner_thread_delegates.h b/test/task_runner_thread_delegates.h
deleted file mode 100644
index bea384a9..0000000
--- a/test/task_runner_thread_delegates.h
+++ /dev/null
@@ -1,91 +0,0 @@
-/*
- * Copyright (C) 2018 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.
- */
-
-#ifndef TEST_TASK_RUNNER_THREAD_DELEGATES_H_
-#define TEST_TASK_RUNNER_THREAD_DELEGATES_H_
-
-#include "perfetto/ext/tracing/ipc/service_ipc_host.h"
-#include "src/traced/probes/probes_producer.h"
-#include "test/fake_producer.h"
-#include "test/task_runner_thread.h"
-
-namespace perfetto {
-// This is used only in daemon starting integrations tests.
-class ServiceDelegate : public ThreadDelegate {
- public:
- ServiceDelegate(const std::string& producer_socket,
- const std::string& consumer_socket)
- : producer_socket_(producer_socket), consumer_socket_(consumer_socket) {}
- ~ServiceDelegate() override;
-
- void Initialize(base::TaskRunner* task_runner) override {
- svc_ = ServiceIPCHost::CreateInstance(task_runner);
- unlink(producer_socket_.c_str());
- unlink(consumer_socket_.c_str());
- svc_->Start(producer_socket_.c_str(), consumer_socket_.c_str());
- }
-
- private:
- std::string producer_socket_;
- std::string consumer_socket_;
- std::unique_ptr<ServiceIPCHost> svc_;
-};
-
-// This is used only in daemon starting integrations tests.
-class ProbesProducerDelegate : public ThreadDelegate {
- public:
- ProbesProducerDelegate(const std::string& producer_socket)
- : producer_socket_(producer_socket) {}
- ~ProbesProducerDelegate() override;
-
- void Initialize(base::TaskRunner* task_runner) override {
- producer_.reset(new ProbesProducer);
- producer_->ConnectWithRetries(producer_socket_.c_str(), task_runner);
- }
-
- private:
- std::string producer_socket_;
- std::unique_ptr<ProbesProducer> producer_;
-};
-
-class FakeProducerDelegate : public ThreadDelegate {
- public:
- FakeProducerDelegate(const std::string& producer_socket,
- std::function<void()> setup_callback,
- std::function<void()> connect_callback)
- : producer_socket_(producer_socket),
- setup_callback_(std::move(setup_callback)),
- connect_callback_(std::move(connect_callback)) {}
- ~FakeProducerDelegate() override;
-
- void Initialize(base::TaskRunner* task_runner) override {
- producer_.reset(new FakeProducer("android.perfetto.FakeProducer"));
- producer_->Connect(producer_socket_.c_str(), task_runner,
- std::move(setup_callback_),
- std::move(connect_callback_));
- }
-
- FakeProducer* producer() { return producer_.get(); }
-
- private:
- std::string producer_socket_;
- std::unique_ptr<FakeProducer> producer_;
- std::function<void()> setup_callback_;
- std::function<void()> connect_callback_;
-};
-} // namespace perfetto
-
-#endif // TEST_TASK_RUNNER_THREAD_DELEGATES_H_
diff --git a/test/test_helper.cc b/test/test_helper.cc
index e716c07..51d9cb7 100644
--- a/test/test_helper.cc
+++ b/test/test_helper.cc
@@ -18,7 +18,6 @@
#include "perfetto/ext/traced/traced.h"
#include "perfetto/ext/tracing/core/trace_packet.h"
-#include "test/task_runner_thread_delegates.h"
#include "perfetto/ext/tracing/ipc/default_socket.h"
#include "protos/perfetto/trace/trace_packet.pbzero.h"
@@ -41,8 +40,10 @@
TestHelper::TestHelper(base::TestTaskRunner* task_runner)
: instance_num_(next_instance_num_++),
task_runner_(task_runner),
- service_thread_("perfetto.svc"),
- producer_thread_("perfetto.prd") {}
+ service_thread_(TEST_PRODUCER_SOCK_NAME, TEST_CONSUMER_SOCK_NAME),
+ fake_producer_thread_(TEST_PRODUCER_SOCK_NAME,
+ WrapTask(CreateCheckpoint("producer.setup")),
+ WrapTask(CreateCheckpoint("producer.enabled"))) {}
void TestHelper::OnConnect() {
std::move(on_connect_callback_)();
@@ -77,19 +78,13 @@
void TestHelper::StartServiceIfRequired() {
#if PERFETTO_BUILDFLAG(PERFETTO_START_DAEMONS)
- service_thread_.Start(std::unique_ptr<ServiceDelegate>(
- new ServiceDelegate(TEST_PRODUCER_SOCK_NAME, TEST_CONSUMER_SOCK_NAME)));
+ service_thread_.Start();
#endif
}
FakeProducer* TestHelper::ConnectFakeProducer() {
- std::unique_ptr<FakeProducerDelegate> producer_delegate(
- new FakeProducerDelegate(TEST_PRODUCER_SOCK_NAME,
- WrapTask(CreateCheckpoint("producer.setup")),
- WrapTask(CreateCheckpoint("producer.enabled"))));
- FakeProducerDelegate* producer_delegate_cached = producer_delegate.get();
- producer_thread_.Start(std::move(producer_delegate));
- return producer_delegate_cached->producer();
+ fake_producer_thread_.Connect();
+ return fake_producer_thread_.producer();
}
void TestHelper::ConnectConsumer() {
diff --git a/test/test_helper.h b/test/test_helper.h
index 11897e5..e18531e 100644
--- a/test/test_helper.h
+++ b/test/test_helper.h
@@ -18,18 +18,121 @@
#define TEST_TEST_HELPER_H_
#include "perfetto/ext/base/scoped_file.h"
+#include "perfetto/ext/base/thread_task_runner.h"
#include "perfetto/ext/tracing/core/consumer.h"
#include "perfetto/ext/tracing/core/trace_packet.h"
#include "perfetto/ext/tracing/ipc/consumer_ipc_client.h"
+#include "perfetto/ext/tracing/ipc/service_ipc_host.h"
#include "perfetto/tracing/core/trace_config.h"
#include "src/base/test/test_task_runner.h"
+#include "src/traced/probes/probes_producer.h"
#include "test/fake_producer.h"
-#include "test/task_runner_thread.h"
#include "protos/perfetto/trace/trace_packet.gen.h"
namespace perfetto {
+// This is used only in daemon starting integrations tests.
+class ServiceThread {
+ public:
+ ServiceThread(const std::string& producer_socket,
+ const std::string& consumer_socket)
+ : producer_socket_(producer_socket), consumer_socket_(consumer_socket) {}
+
+ ~ServiceThread() {
+ if (!runner_)
+ return;
+ runner_->PostTaskAndWaitForTesting([this]() { svc_.reset(); });
+ }
+
+ void Start() {
+ runner_ = base::ThreadTaskRunner::CreateAndStart("perfetto.svc");
+ runner_->PostTaskAndWaitForTesting([this]() {
+ svc_ = ServiceIPCHost::CreateInstance(runner_->get());
+ unlink(producer_socket_.c_str());
+ unlink(consumer_socket_.c_str());
+
+ bool res =
+ svc_->Start(producer_socket_.c_str(), consumer_socket_.c_str());
+ PERFETTO_CHECK(res);
+ });
+ }
+
+ base::ThreadTaskRunner* runner() { return runner_ ? &*runner_ : nullptr; }
+
+ private:
+ base::Optional<base::ThreadTaskRunner> runner_; // Keep first.
+
+ std::string producer_socket_;
+ std::string consumer_socket_;
+ std::unique_ptr<ServiceIPCHost> svc_;
+};
+
+// This is used only in daemon starting integrations tests.
+class ProbesProducerThread {
+ public:
+ ProbesProducerThread(const std::string& producer_socket)
+ : producer_socket_(producer_socket) {}
+
+ ~ProbesProducerThread() {
+ if (!runner_)
+ return;
+ runner_->PostTaskAndWaitForTesting([this]() { producer_.reset(); });
+ }
+
+ void Connect() {
+ runner_ = base::ThreadTaskRunner::CreateAndStart("perfetto.prd.probes");
+ runner_->PostTaskAndWaitForTesting([this]() {
+ producer_.reset(new ProbesProducer());
+ producer_->ConnectWithRetries(producer_socket_.c_str(), runner_->get());
+ });
+ }
+
+ private:
+ base::Optional<base::ThreadTaskRunner> runner_; // Keep first.
+
+ std::string producer_socket_;
+ std::unique_ptr<ProbesProducer> producer_;
+};
+
+class FakeProducerThread {
+ public:
+ FakeProducerThread(const std::string& producer_socket,
+ std::function<void()> setup_callback,
+ std::function<void()> connect_callback)
+ : producer_socket_(producer_socket),
+ setup_callback_(std::move(setup_callback)),
+ connect_callback_(std::move(connect_callback)) {}
+
+ ~FakeProducerThread() {
+ if (!runner_)
+ return;
+ runner_->PostTaskAndWaitForTesting([this]() { producer_.reset(); });
+ }
+
+ void Connect() {
+ runner_ = base::ThreadTaskRunner::CreateAndStart("perfetto.prd.fake");
+ runner_->PostTaskAndWaitForTesting([this]() {
+ producer_.reset(new FakeProducer("android.perfetto.FakeProducer"));
+ producer_->Connect(producer_socket_.c_str(), runner_->get(),
+ std::move(setup_callback_),
+ std::move(connect_callback_));
+ });
+ }
+
+ base::ThreadTaskRunner* runner() { return runner_ ? &*runner_ : nullptr; }
+
+ FakeProducer* producer() { return producer_.get(); }
+
+ private:
+ base::Optional<base::ThreadTaskRunner> runner_; // Keep first.
+
+ std::string producer_socket_;
+ std::unique_ptr<FakeProducer> producer_;
+ std::function<void()> setup_callback_;
+ std::function<void()> connect_callback_;
+};
+
class TestHelper : public Consumer {
public:
static const char* GetConsumerSocketName();
@@ -79,8 +182,10 @@
std::function<void()> WrapTask(const std::function<void()>& function);
- TaskRunnerThread* service_thread() { return &service_thread_; }
- TaskRunnerThread* producer_thread() { return &producer_thread_; }
+ base::ThreadTaskRunner* service_thread() { return service_thread_.runner(); }
+ base::ThreadTaskRunner* producer_thread() {
+ return fake_producer_thread_.runner();
+ }
const std::vector<protos::gen::TracePacket>& trace() { return trace_; }
private:
@@ -97,8 +202,9 @@
std::vector<protos::gen::TracePacket> trace_;
- TaskRunnerThread service_thread_;
- TaskRunnerThread producer_thread_;
+ ServiceThread service_thread_;
+ FakeProducerThread fake_producer_thread_;
+
std::unique_ptr<TracingService::ConsumerEndpoint> endpoint_; // Keep last.
};
diff --git a/test/trace_processor/android_sched_and_ps_trace_size.out b/test/trace_processor/android_sched_and_ps_trace_size.out
new file mode 100644
index 0000000..b2bd2ea
--- /dev/null
+++ b/test/trace_processor/android_sched_and_ps_trace_size.out
@@ -0,0 +1,2 @@
+"int_value"
+18761615
diff --git a/test/trace_processor/fuchsia_workstation_smoke_slices.out b/test/trace_processor/fuchsia_workstation_smoke_slices.out
index 496d5ec..2d133e8 100644
--- a/test/trace_processor/fuchsia_workstation_smoke_slices.out
+++ b/test/trace_processor/fuchsia_workstation_smoke_slices.out
@@ -19,6 +19,6 @@
"thread_track",17,38
"thread_track",18,12
"thread_track",19,1
-"track",0,84
+"track",0,85
"track",1,14
-"track",2,2
+"track",2,1
diff --git a/test/trace_processor/gpu_render_stages.out b/test/trace_processor/gpu_render_stages.out
index ace66ec..0cfaaf6 100644
--- a/test/trace_processor/gpu_render_stages.out
+++ b/test/trace_processor/gpu_render_stages.out
@@ -1,17 +1,18 @@
-"track_name","track_desc","ts","dur","slice_name","depth","flat_key","string_value","context_id","render_target","submission_id","hw_queue_id"
-"queue 1","queue desc 1",0,5,"render stage(1)",0,"[NULL]","[NULL]",0,0,0,1
-"queue 0","queue desc 0",0,5,"stage 0",0,"[NULL]","[NULL]",42,0,0,0
-"queue 1","queue desc 1",10,5,"stage 1",0,"description","stage desc 1",42,0,0,1
-"queue 2","[NULL]",20,5,"stage 2",0,"[NULL]","[NULL]",42,0,0,2
-"queue 0","queue desc 0",30,5,"stage 3",0,"[NULL]","[NULL]",42,0,0,0
-"Unknown GPU Queue 3","[NULL]",40,5,"render stage(4)",0,"[NULL]","[NULL]",42,0,0,3
-"queue 0","queue desc 0",50,5,"stage 0",0,"key1","value1",42,0,0,0
-"queue 0","queue desc 0",60,5,"stage 0",0,"key2","value2",42,0,0,0
-"queue 0","queue desc 0",60,5,"stage 0",0,"key1","value1",42,0,0,0
-"queue 0","queue desc 0",70,5,"stage 0",0,"key1","[NULL]",42,0,0,0
-"queue 0","queue desc 0",80,5,"stage 2",0,"[NULL]","[NULL]",42,0,0,0
-"queue 0","queue desc 0",90,5,"stage 0[0x10]",0,"[NULL]","[NULL]",42,16,0,0
-"queue 0","queue desc 0",100,5,"stage 0[0x10]",0,"[NULL]","[NULL]",42,16,0,0
-"queue 0","queue desc 0",110,5,"stage 0[framebuffer]",0,"[NULL]","[NULL]",42,16,0,0
-"queue 0","queue desc 0",120,5,"stage 0[renamed_buffer]",0,"[NULL]","[NULL]",42,16,0,0
-"Unknown GPU Queue ","[NULL]",120,5,"render stage(18446744073709551615)",0,"[NULL]","[NULL]",42,0,0,1024
+"track_name","track_desc","ts","dur","slice_name","depth","flat_key","string_value","context_id","render_target","render_target_name","render_pass","render_pass_name","command_buffer","command_buffer_name","submission_id","hw_queue_id"
+"queue 1","queue desc 1",0,5,"render stage(1)",0,"[NULL]","[NULL]",0,0,"[NULL]",0,"[NULL]",0,"[NULL]",0,1
+"queue 0","queue desc 0",0,5,"stage 0",0,"[NULL]","[NULL]",42,0,"[NULL]",0,"[NULL]",0,"[NULL]",0,0
+"queue 1","queue desc 1",10,5,"stage 1",0,"description","stage desc 1",42,0,"[NULL]",0,"[NULL]",0,"[NULL]",0,1
+"queue 2","[NULL]",20,5,"stage 2",0,"[NULL]","[NULL]",42,0,"[NULL]",0,"[NULL]",0,"[NULL]",0,2
+"queue 0","queue desc 0",30,5,"stage 3",0,"[NULL]","[NULL]",42,0,"[NULL]",0,"[NULL]",0,"[NULL]",0,0
+"Unknown GPU Queue 3","[NULL]",40,5,"render stage(4)",0,"[NULL]","[NULL]",42,0,"[NULL]",0,"[NULL]",0,"[NULL]",0,3
+"queue 0","queue desc 0",50,5,"stage 0",0,"key1","value1",42,0,"[NULL]",0,"[NULL]",0,"[NULL]",0,0
+"queue 0","queue desc 0",60,5,"stage 0",0,"key2","value2",42,0,"[NULL]",0,"[NULL]",0,"[NULL]",0,0
+"queue 0","queue desc 0",60,5,"stage 0",0,"key1","value1",42,0,"[NULL]",0,"[NULL]",0,"[NULL]",0,0
+"queue 0","queue desc 0",70,5,"stage 0",0,"key1","[NULL]",42,0,"[NULL]",0,"[NULL]",0,"[NULL]",0,0
+"queue 0","queue desc 0",80,5,"stage 2",0,"[NULL]","[NULL]",42,0,"[NULL]",0,"[NULL]",0,"[NULL]",0,0
+"queue 0","queue desc 0",90,5,"stage 0",0,"[NULL]","[NULL]",42,16,"[NULL]",32,"[NULL]",48,"[NULL]",0,0
+"queue 0","queue desc 0",100,5,"stage 0",0,"[NULL]","[NULL]",42,16,"[NULL]",16,"[NULL]",16,"command_buffer",0,0
+"queue 0","queue desc 0",110,5,"stage 0",0,"[NULL]","[NULL]",42,16,"[NULL]",16,"render_pass",16,"command_buffer",0,0
+"queue 0","queue desc 0",120,5,"stage 0",0,"[NULL]","[NULL]",42,16,"framebuffer",16,"render_pass",16,"command_buffer",0,0
+"queue 0","queue desc 0",130,5,"stage 0",0,"[NULL]","[NULL]",42,16,"renamed_buffer",0,"[NULL]",0,"[NULL]",0,0
+"Unknown GPU Queue ","[NULL]",140,5,"render stage(18446744073709551615)",0,"[NULL]","[NULL]",42,0,"[NULL]",0,"[NULL]",0,"[NULL]",0,1024
diff --git a/test/trace_processor/gpu_render_stages.py b/test/trace_processor/gpu_render_stages.py
index 48c6866..a88fc78 100644
--- a/test/trace_processor/gpu_render_stages.py
+++ b/test/trace_processor/gpu_render_stages.py
@@ -93,6 +93,7 @@
# Test stage naming with render target handle.
VK_OBJECT_TYPE_COMMAND_BUFFER = 6
+VK_OBJECT_TYPE_RENDER_PASS = 18
VK_OBJECT_TYPE_FRAMEBUFFER = 24
trace.add_gpu_render_stages(
@@ -106,9 +107,12 @@
hw_queue_id=0,
stage_id=0,
context=42,
- render_target_handle=0x10)
+ render_target_handle=0x10,
+ render_pass_handle=0x20,
+ command_buffer_handle=0x30)
-# adding a marker with non-FRAMEBUFFER should not affect the name.
+# adding a marker with COMMAND_BUFFER and RENDER_PASS should affect only the
+# relevant handles.
trace.add_vk_debug_marker(
ts=91,
pid=100,
@@ -123,16 +127,17 @@
hw_queue_id=0,
stage_id=0,
context=42,
- render_target_handle=0x10)
+ render_target_handle=0x10,
+ render_pass_handle=0x10,
+ command_buffer_handle=0x10)
-# adding a marker with FRAMEBUFFER changes the name.
trace.add_vk_debug_marker(
ts=101,
pid=100,
vk_device=1,
- obj_type=VK_OBJECT_TYPE_FRAMEBUFFER,
+ obj_type=VK_OBJECT_TYPE_RENDER_PASS,
obj=0x10,
- obj_name="framebuffer")
+ obj_name="render_pass")
trace.add_gpu_render_stages(
ts=110,
event_id=10,
@@ -140,18 +145,39 @@
hw_queue_id=0,
stage_id=0,
context=42,
- render_target_handle=0x10)
+ render_target_handle=0x10,
+ render_pass_handle=0x10,
+ command_buffer_handle=0x10)
-# setting the name again replace the name
+# adding a marker with FRAMEBUFFER changes the name of the stage as well.
trace.add_vk_debug_marker(
ts=111,
pid=100,
vk_device=1,
obj_type=VK_OBJECT_TYPE_FRAMEBUFFER,
obj=0x10,
- obj_name="renamed_buffer")
+ obj_name="framebuffer")
trace.add_gpu_render_stages(
ts=120,
+ event_id=10,
+ duration=5,
+ hw_queue_id=0,
+ stage_id=0,
+ context=42,
+ render_target_handle=0x10,
+ render_pass_handle=0x10,
+ command_buffer_handle=0x10)
+
+# setting the name again replace the name
+trace.add_vk_debug_marker(
+ ts=121,
+ pid=100,
+ vk_device=1,
+ obj_type=VK_OBJECT_TYPE_FRAMEBUFFER,
+ obj=0x10,
+ obj_name="renamed_buffer")
+trace.add_gpu_render_stages(
+ ts=130,
event_id=11,
duration=5,
hw_queue_id=0,
@@ -161,6 +187,6 @@
# Check that a hw_queue_id=-1 doesn't blow up.
trace.add_gpu_render_stages(
- ts=120, event_id=12, duration=5, hw_queue_id=-1, stage_id=-1, context=42)
+ ts=140, event_id=12, duration=5, hw_queue_id=-1, stage_id=-1, context=42)
print(trace.trace.SerializeToString())
diff --git a/test/trace_processor/gpu_render_stages.sql b/test/trace_processor/gpu_render_stages.sql
index dbfe545..c85d162 100644
--- a/test/trace_processor/gpu_render_stages.sql
+++ b/test/trace_processor/gpu_render_stages.sql
@@ -15,9 +15,10 @@
--
SELECT track.name AS track_name, gpu_track.description AS track_desc, ts, dur,
gpu_slice.name AS slice_name, depth, flat_key, string_value,
- gpu_slice.context_id, render_target, submission_id, hw_queue_id
+ gpu_slice.context_id, render_target, render_target_name, render_pass, render_pass_name,
+ command_buffer, command_buffer_name, submission_id, hw_queue_id
FROM gpu_track
LEFT JOIN track USING (id)
-INNER JOIN gpu_slice on gpu_track.id=gpu_slice.track_id
+INNER JOIN gpu_slice ON gpu_track.id=gpu_slice.track_id
LEFT JOIN args ON gpu_slice.arg_set_id = args.arg_set_id
ORDER BY ts;
diff --git a/test/trace_processor/graphics_frame_events.out b/test/trace_processor/graphics_frame_events.out
index 76e4e13..fd7c42a 100644
--- a/test/trace_processor/graphics_frame_events.out
+++ b/test/trace_processor/graphics_frame_events.out
@@ -16,5 +16,5 @@
8,"layer3[buffer:2]",13,"Post",12,"layer_name","layer3"
9,"layer3[buffer:3]",5,"Attach",15,"layer_name","layer3"
10,"layer3[buffer:3]",10,"Cancel",16,"layer_name","layer3"
-16,"Displayed Frame",-1,6,17,"[NULL]","[NULL]"
+16,"Displayed Frame",-1,"6",17,"[NULL]","[NULL]"
16,"layer5[buffer:6]",0,"PresentFenceSignaled",17,"layer_name","layer5"
diff --git a/test/trace_processor/heap_graph.textproto b/test/trace_processor/heap_graph.textproto
index 295e284..b8407aa 100644
--- a/test/trace_processor/heap_graph.textproto
+++ b/test/trace_processor/heap_graph.textproto
@@ -47,6 +47,11 @@
reference_field_id: 2
reference_object_id: 0x01
}
+ objects {
+ id: 0x05
+ type_id: 4
+ self_size: 256
+ }
continued: true
index: 1
}
@@ -67,6 +72,10 @@
iid: 3
str: "a"
}
+ type_names {
+ iid: 4
+ str: "a[]"
+ }
field_names {
iid: 1
str: "FactoryProducerDelegateImplActor.foo"
diff --git a/test/trace_processor/heap_graph_flamegraph.sql b/test/trace_processor/heap_graph_flamegraph.sql
new file mode 100644
index 0000000..157095f
--- /dev/null
+++ b/test/trace_processor/heap_graph_flamegraph.sql
@@ -0,0 +1,12 @@
+SELECT
+ id,
+ depth,
+ name,
+ map_name,
+ count,
+ cumulative_count,
+ size,
+ cumulative_size,
+ parent_id
+FROM experimental_flamegraph(601908408518618, 1, 'graph')
+LIMIT 10
diff --git a/test/trace_processor/heap_graph_flamegraph_system-server-heap-graph.out b/test/trace_processor/heap_graph_flamegraph_system-server-heap-graph.out
new file mode 100644
index 0000000..8f822d1
--- /dev/null
+++ b/test/trace_processor/heap_graph_flamegraph_system-server-heap-graph.out
@@ -0,0 +1,11 @@
+"id","depth","name","map_name","count","cumulative_count","size","cumulative_size","parent_id"
+0,0,"java.lang.Class<boolean>","JAVA",2,4,240,276,"[NULL]"
+1,1,"java.lang.Object[]","JAVA",1,1,12,12,0
+2,1,"java.lang.String","JAVA",1,1,24,24,0
+3,0,"java.lang.Class<byte>","JAVA",3,4,360,384,"[NULL]"
+4,1,"java.lang.String","JAVA",1,1,24,24,3
+5,0,"java.lang.Class<short>","JAVA",2,3,240,264,"[NULL]"
+6,1,"java.lang.String","JAVA",1,1,24,24,5
+7,0,"java.lang.Class<char>","JAVA",2,3,240,264,"[NULL]"
+8,1,"java.lang.String","JAVA",1,1,24,24,7
+9,0,"java.lang.Class<int>","JAVA",2,3,240,264,"[NULL]"
diff --git a/test/trace_processor/heap_graph_object.out b/test/trace_processor/heap_graph_object.out
index a25b67b..1d3b6eb 100644
--- a/test/trace_processor/heap_graph_object.out
+++ b/test/trace_processor/heap_graph_object.out
@@ -3,3 +3,4 @@
1,"heap_graph_object",2,10,2,32,-1,-1,1,1,"Foo","[NULL]","[NULL]"
2,"heap_graph_object",2,10,3,128,-1,-1,1,0,"Foo","[NULL]","[NULL]"
3,"heap_graph_object",2,10,4,256,-1,-1,1,0,"a","DeobfuscatedA","[NULL]"
+4,"heap_graph_object",2,10,5,256,-1,-1,2,0,"a[]","DeobfuscatedA[]","[NULL]"
diff --git a/test/trace_processor/heap_profile_flamegraph.sql b/test/trace_processor/heap_profile_flamegraph.sql
new file mode 100644
index 0000000..fa90b15
--- /dev/null
+++ b/test/trace_processor/heap_profile_flamegraph.sql
@@ -0,0 +1 @@
+select * from experimental_flamegraph(605908369259172, 1, 'native') limit 10;
diff --git a/test/trace_processor/heap_profile_flamegraph_system-server-native-profile.out b/test/trace_processor/heap_profile_flamegraph_system-server-native-profile.out
new file mode 100644
index 0000000..42ab65d
--- /dev/null
+++ b/test/trace_processor/heap_profile_flamegraph_system-server-native-profile.out
@@ -0,0 +1,11 @@
+"id","type","depth","name","map_name","count","cumulative_count","size","cumulative_size","alloc_count","cumulative_alloc_count","alloc_size","cumulative_alloc_size","parent_id"
+0,"experimental_flamegraph_nodes",0,"__start_thread","/apex/com.android.runtime/lib64/bionic/libc.so",0,8,0,84848,0,210,0,1084996,"[NULL]"
+1,"experimental_flamegraph_nodes",1,"_ZL15__pthread_startPv","/apex/com.android.runtime/lib64/bionic/libc.so",0,8,0,84848,0,210,0,1084996,0
+2,"experimental_flamegraph_nodes",2,"_ZN7android14AndroidRuntime15javaThreadShellEPv","/system/lib64/libandroid_runtime.so",0,5,0,27704,0,77,0,348050,1
+3,"experimental_flamegraph_nodes",3,"_ZN7android6Thread11_threadLoopEPv","/system/lib64/libutils.so",0,5,0,27704,0,77,0,348050,2
+4,"experimental_flamegraph_nodes",4,"_ZN7android10PoolThread10threadLoopEv","/system/lib64/libbinder.so",0,1,0,4096,0,64,0,279182,3
+5,"experimental_flamegraph_nodes",5,"_ZN7android14IPCThreadState14joinThreadPoolEb","/system/lib64/libbinder.so",0,1,0,4096,0,64,0,279182,4
+6,"experimental_flamegraph_nodes",6,"_ZN7android14IPCThreadState20getAndExecuteCommandEv","/system/lib64/libbinder.so",0,1,0,4096,0,64,0,279182,5
+7,"experimental_flamegraph_nodes",7,"_ZN7android14IPCThreadState14executeCommandEi","/system/lib64/libbinder.so",0,1,0,4096,0,64,0,279182,6
+8,"experimental_flamegraph_nodes",8,"_ZN7android7BBinder8transactEjRKNS_6ParcelEPS1_j","/system/lib64/libbinder.so",0,1,0,4096,0,64,0,279182,7
+9,"experimental_flamegraph_nodes",9,"_ZN11JavaBBinder10onTransactEjRKN7android6ParcelEPS1_j","/system/lib64/libandroid_runtime.so",0,0,0,0,0,60,0,262730,8
diff --git a/test/trace_processor/heap_profile_tracker_new_stack.out b/test/trace_processor/heap_profile_tracker_new_stack.out
new file mode 100644
index 0000000..205768d
--- /dev/null
+++ b/test/trace_processor/heap_profile_tracker_new_stack.out
@@ -0,0 +1,5 @@
+"id","type","ts","upid","callsite_id","count","size"
+0,"heap_profile_allocation",0,0,0,1,1
+1,"heap_profile_allocation",0,0,0,-1,-1
+2,"heap_profile_allocation",1,0,0,1,1
+3,"heap_profile_allocation",1,0,0,-1,-1
diff --git a/test/trace_processor/heap_profile_tracker_new_stack.sql b/test/trace_processor/heap_profile_tracker_new_stack.sql
new file mode 100644
index 0000000..efed7da
--- /dev/null
+++ b/test/trace_processor/heap_profile_tracker_new_stack.sql
@@ -0,0 +1 @@
+select * from heap_profile_allocation;
diff --git a/test/trace_processor/heap_profile_tracker_new_stack.textproto b/test/trace_processor/heap_profile_tracker_new_stack.textproto
new file mode 100644
index 0000000..f84c30a
--- /dev/null
+++ b/test/trace_processor/heap_profile_tracker_new_stack.textproto
@@ -0,0 +1,76 @@
+packet {
+ clock_snapshot {
+ clocks: {
+ clock_id: 6 # BOOTTIME
+ timestamp: 0
+ }
+ clocks: {
+ clock_id: 4 # MONOTONIC_COARSE
+ timestamp: 0
+ }
+ }
+}
+
+packet {
+ previous_packet_dropped: true
+ incremental_state_cleared: true
+ trusted_packet_sequence_id: 1
+ timestamp: 0
+ interned_data {
+ mappings {
+ iid: 1
+ }
+ frames {
+ iid: 1
+ mapping_id: 1
+ rel_pc: 0x123
+ }
+ callstacks {
+ iid: 1
+ frame_ids: 1
+ }
+ }
+}
+
+packet {
+ trusted_packet_sequence_id: 1
+ timestamp: 0
+ profile_packet {
+ index: 0
+ continued: false
+ process_dumps {
+ samples {
+ callstack_id: 1
+ self_allocated: 1
+ alloc_count: 1
+ self_freed: 1
+ free_count: 1
+ }
+ }
+ }
+}
+
+packet {
+ trusted_packet_sequence_id: 1
+ timestamp: 1
+ interned_data {
+ callstacks {
+ iid: 2
+ frame_ids: 1
+ }
+ }
+ profile_packet {
+ index: 1
+ continued: false
+ process_dumps {
+ timestamp: 1
+ samples {
+ callstack_id: 2
+ self_allocated: 1
+ alloc_count: 1
+ self_freed: 1
+ free_count: 1
+ }
+ }
+ }
+}
diff --git a/test/trace_processor/index b/test/trace_processor/index
index e6d6286..f929928 100644
--- a/test/trace_processor/index
+++ b/test/trace_processor/index
@@ -57,6 +57,8 @@
# Rss stats
rss_stat_mm_id.py rss_stat.sql rss_stat_mm_id.out
+rss_stat_mm_id_clone.py rss_stat.sql rss_stat_mm_id_clone.out
+rss_stat_mm_id_reuse.py rss_stat.sql rss_stat_mm_id_reuse.out
rss_stat_legacy.py rss_stat.sql rss_stat_legacy.out
# Memory counters
@@ -129,6 +131,7 @@
# GPU trace tests.
gpu_counters.py gpu_counters.sql gpu_counters.out
gpu_render_stages.py gpu_render_stages.sql gpu_render_stages.out
+vulkan_api_events.py vulkan_api_events.sql vulkan_api_events.out
gpu_log.py gpu_log.sql gpu_log.out
# Clock sync
@@ -151,6 +154,11 @@
heap_graph.textproto heap_graph_reference.sql heap_graph_reference.out
heap_graph_interleaved.textproto heap_graph_object.sql heap_graph_interleaved_object.out
heap_graph_interleaved.textproto heap_graph_reference.sql heap_graph_interleaved_reference.out
+../data/system-server-heap-graph.pftrace heap_graph_flamegraph.sql heap_graph_flamegraph_system-server-heap-graph.out
+../data/system-server-native-profile heap_profile_flamegraph.sql heap_profile_flamegraph_system-server-native-profile.out
+heap_profile_tracker_new_stack.textproto heap_profile_tracker_new_stack.sql heap_profile_tracker_new_stack.out
+
+stack_profile_tracker_empty_callstack.textproto stack_profile_tracker_empty_callstack.sql stack_profile_tracker_empty_callstack.out
# TrackEvent tests.
track_event_same_tids.textproto process_tracking.sql track_event_same_tids_threads.out
@@ -172,3 +180,6 @@
# Ensures process -> package matching works as expected.
process_metadata_matching.textproto process_metadata_matching.sql process_metadata_matching.out
+
+# Trace size
+../data/android_sched_and_ps.pb trace_size.sql android_sched_and_ps_trace_size.out
diff --git a/test/trace_processor/metadata.sql b/test/trace_processor/metadata.sql
index 46f9e6b..3943251 100644
--- a/test/trace_processor/metadata.sql
+++ b/test/trace_processor/metadata.sql
@@ -13,4 +13,4 @@
-- See the License for the specific language governing permissions and
-- limitations under the License.
--
-select name, str_value from metadata order by name;
+select name, str_value from metadata where str_value is not null order by name;
diff --git a/test/trace_processor/rss_stat_mm_id copy.py b/test/trace_processor/rss_stat_mm_id copy.py
new file mode 100644
index 0000000..d2b5e5a
--- /dev/null
+++ b/test/trace_processor/rss_stat_mm_id copy.py
@@ -0,0 +1,52 @@
+#!/usr/bin/python
+# Copyright (C) 2019 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.
+
+# This synthetic trace tests handling of the mm_id field in the rss_stat
+# event.
+
+from os import sys, path
+
+sys.path.append(path.dirname(path.dirname(path.abspath(__file__))))
+import synth_common
+
+trace = synth_common.create_trace()
+
+trace.add_process_tree_packet(ts=1)
+trace.add_process(10, 0, "process")
+
+trace.add_ftrace_packet(0)
+
+# Create a new child process (treated internally as a thread) of kthreadd.
+trace.add_newtask(ts=50, tid=2, new_tid=3, new_comm="kthread_child", flags=0)
+
+# Add an event on tid 3 which affects its own rss.
+trace.add_rss_stat(ts=90, tid=3, member=0, size=9, mm_id=4321, curr=True)
+
+# Try to add an event for tid 10. However, as we've not seen an event
+# with curr == True for tid == 10, this event will be dropped.
+trace.add_rss_stat(ts=91, tid=3, member=0, size=900, mm_id=1234, curr=False)
+
+# Add an event for tid 3 from tid 10. This emulates e.g. direct reclaim
+# where a process reaches into another process' mm struct.
+trace.add_rss_stat(ts=99, tid=10, member=0, size=10, mm_id=4321, curr=False)
+
+# Add an event on tid 10 which affects its own rss.
+trace.add_rss_stat(ts=100, tid=10, member=0, size=1000, mm_id=1234, curr=True)
+
+# Add an event on tid 10 from tid 3. This emlates e.g. background reclaim
+# where kthreadd is cleaning up the mm struct of another process.
+trace.add_rss_stat(ts=101, tid=3, member=0, size=900, mm_id=1234, curr=False)
+
+print(trace.trace.SerializeToString())
diff --git a/test/trace_processor/rss_stat_mm_id_clone.out b/test/trace_processor/rss_stat_mm_id_clone.out
new file mode 100644
index 0000000..0969481
--- /dev/null
+++ b/test/trace_processor/rss_stat_mm_id_clone.out
@@ -0,0 +1,9 @@
+"ts","name","pid","name","value"
+100,"mem.rss.file",10,"parent_process",100.000000
+100,"mem.rss.file",2,"kthreadd",10.000000
+102,"mem.rss.file",2,"kthreadd",20.000000
+102,"mem.rss.file",11,"child_process",90.000000
+104,"mem.rss.file",11,"child_process",10.000000
+105,"mem.rss.file",10,"parent_process",95.000000
+107,"mem.rss.file",10,"parent_process",105.000000
+108,"mem.rss.file",10,"parent_process",110.000000
diff --git a/test/trace_processor/rss_stat_mm_id_clone.py b/test/trace_processor/rss_stat_mm_id_clone.py
new file mode 100644
index 0000000..308b6b4
--- /dev/null
+++ b/test/trace_processor/rss_stat_mm_id_clone.py
@@ -0,0 +1,98 @@
+#!/usr/bin/python
+# Copyright (C) 2019 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.
+
+# This synthetic trace tests handling of the mm_id field in the rss_stat
+# event during clone events which have various flag combinations set.
+
+from os import sys, path
+
+sys.path.append(path.dirname(path.dirname(path.abspath(__file__))))
+import synth_common
+
+trace = synth_common.create_trace()
+
+trace.add_process_tree_packet(ts=1)
+trace.add_process(10, 1, "parent_process")
+trace.add_process(3, 2, "kernel_thread")
+
+# In this packet, check what happens to userspace processes with different
+# clone flags.
+trace.add_ftrace_packet(1)
+
+# Emit an rss stat event for the main thread of the process to associate it
+# with an mm_id.
+trace.add_rss_stat(100, tid=10, member=0, size=100, mm_id=0x1234, curr=1)
+
+# Create a newtask event emulating vfork/posix_spawn (i.e. CLONE_VM and
+# CLONE_VFORK set).
+trace.add_newtask(
+ 101,
+ tid=10,
+ new_tid=11,
+ new_comm="child_process",
+ flags=synth_common.CLONE_VFORK | synth_common.CLONE_VM)
+
+# The child process will now change its own (and parent's) VM space with
+# |curr| set to 1 (emulating cleaning up some memory in parent).
+trace.add_rss_stat(102, tid=11, member=0, size=90, mm_id=0x1234, curr=1)
+
+# At this point, the child process will obtain a new mm struct. From this
+# point on, all mm_ids from the child should be different from the parent.
+
+# The child process will now change its parents VM space with curr set to
+# 0 (emulating e.g. cleaning up its stack).
+trace.add_rss_stat(103, tid=11, member=0, size=85, mm_id=0x1234, curr=0)
+
+# Now the child process should exec another process.
+
+# The child can now change its own memory.
+trace.add_rss_stat(104, tid=11, member=0, size=10, mm_id=0x5678, curr=1)
+
+# The parent can now resume execution and may emit another rss event.
+trace.add_rss_stat(105, tid=10, member=0, size=95, mm_id=0x1234, curr=1)
+
+# The parent can now go ahead and start a new thread.
+trace.add_newtask(
+ 106,
+ tid=10,
+ new_tid=12,
+ new_comm="parent_thread",
+ flags=synth_common.CLONE_VM | synth_common.CLONE_THREAD)
+
+# Since this thread shares mm space with the parent, it should have the
+# same mm id and have curr set to 1.
+trace.add_rss_stat(107, tid=12, member=0, size=105, mm_id=0x1234, curr=1)
+
+# The parent can also emit events with the same mm struct at the same time.
+trace.add_rss_stat(108, tid=10, member=0, size=110, mm_id=0x1234, curr=1)
+
+# In this packet, we check what happens to kernel threads in RSS stat.
+trace.add_ftrace_packet(1)
+
+# Emit an rss stat event for the the existing kernel thread.
+trace.add_rss_stat(100, tid=3, member=0, size=10, mm_id=0x2345, curr=1)
+
+# Start a new kernel thread.
+trace.add_newtask(
+ 101,
+ tid=2,
+ new_tid=4,
+ new_comm="kernel_thread2",
+ flags=synth_common.CLONE_VM)
+
+# Emit a rss stat for the new kernel thread.
+trace.add_rss_stat(102, tid=4, member=0, size=20, mm_id=0x2345, curr=1)
+
+print(trace.trace.SerializeToString())
diff --git a/test/trace_processor/rss_stat_mm_id_reuse.out b/test/trace_processor/rss_stat_mm_id_reuse.out
new file mode 100644
index 0000000..396f5f7
--- /dev/null
+++ b/test/trace_processor/rss_stat_mm_id_reuse.out
@@ -0,0 +1,3 @@
+"ts","name","pid","name","value"
+100,"mem.rss.file",10,"parent_process",100.000000
+103,"mem.rss.file",10,"new_process",10.000000
diff --git a/test/trace_processor/rss_stat_mm_id_reuse.py b/test/trace_processor/rss_stat_mm_id_reuse.py
new file mode 100644
index 0000000..58d7b4d
--- /dev/null
+++ b/test/trace_processor/rss_stat_mm_id_reuse.py
@@ -0,0 +1,43 @@
+#!/usr/bin/python
+# Copyright (C) 2019 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.
+
+# This synthetic trace tests handling of the mm_id field in the rss_stat
+# event when mm_structs are reused on process death.
+
+from os import sys, path
+
+sys.path.append(path.dirname(path.dirname(path.abspath(__file__))))
+import synth_common
+
+trace = synth_common.create_trace()
+
+trace.add_process_tree_packet(ts=1)
+trace.add_process(10, 1, "parent_process")
+
+trace.add_ftrace_packet(1)
+
+# Emit an event for the process.
+trace.add_rss_stat(100, tid=10, member=0, size=100, mm_id=0x1234, curr=1)
+
+# Now kill the process.
+trace.add_process_free(ts=101, tid=10, comm="parent_process", prio=0)
+
+# Create a new thread which reuses the pid and mm struct.
+trace.add_newtask(102, tid=1, new_tid=10, new_comm="new_process", flags=0)
+
+# Emit an event for the new thread.
+trace.add_rss_stat(103, tid=10, member=0, size=10, mm_id=0x1234, curr=1)
+
+print(trace.trace.SerializeToString())
diff --git a/test/trace_processor/stack_profile_tracker_empty_callstack.out b/test/trace_processor/stack_profile_tracker_empty_callstack.out
new file mode 100644
index 0000000..eb69505
--- /dev/null
+++ b/test/trace_processor/stack_profile_tracker_empty_callstack.out
@@ -0,0 +1,2 @@
+"count"
+0
diff --git a/test/trace_processor/stack_profile_tracker_empty_callstack.sql b/test/trace_processor/stack_profile_tracker_empty_callstack.sql
new file mode 100644
index 0000000..c61df0d
--- /dev/null
+++ b/test/trace_processor/stack_profile_tracker_empty_callstack.sql
@@ -0,0 +1 @@
+select count(1) as count from heap_profile_allocation;
diff --git a/test/trace_processor/stack_profile_tracker_empty_callstack.textproto b/test/trace_processor/stack_profile_tracker_empty_callstack.textproto
new file mode 100644
index 0000000..c0b6dfe
--- /dev/null
+++ b/test/trace_processor/stack_profile_tracker_empty_callstack.textproto
@@ -0,0 +1,45 @@
+packet {
+ clock_snapshot {
+ clocks: {
+ clock_id: 6 # BOOTTIME
+ timestamp: 0
+ }
+ clocks: {
+ clock_id: 4 # MONOTONIC_COARSE
+ timestamp: 0
+ }
+ }
+}
+
+packet {
+ previous_packet_dropped: true
+ incremental_state_cleared: true
+ trusted_packet_sequence_id: 1
+ timestamp: 0
+ interned_data {
+ callstacks {
+ iid: 1
+ }
+ }
+}
+
+packet {
+ trusted_packet_sequence_id: 1
+ timestamp: 0
+ profile_packet {
+ index: 0
+ continued: false
+ process_dumps {
+ samples {
+ callstack_id: 1
+ self_allocated: 1
+ alloc_count: 1
+ }
+ samples {
+ callstack_id: 1
+ self_allocated: 1
+ alloc_count: 1
+ }
+ }
+ }
+}
diff --git a/test/trace_processor/trace_size.sql b/test/trace_processor/trace_size.sql
new file mode 100644
index 0000000..01704a2
--- /dev/null
+++ b/test/trace_processor/trace_size.sql
@@ -0,0 +1,16 @@
+--
+-- Copyright 2020 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
+--
+-- https://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.
+--
+select int_value from metadata where name = 'trace_size_bytes';
diff --git a/test/trace_processor/track_event_args.sql b/test/trace_processor/track_event_args.sql
index 7b7b978..10187a2 100644
--- a/test/trace_processor/track_event_args.sql
+++ b/test/trace_processor/track_event_args.sql
@@ -13,4 +13,4 @@
-- See the License for the specific language governing permissions and
-- limitations under the License.
--
-select arg_set_id, flat_key, key, int_value, string_value from args where arg_set_id >= 2 order by arg_set_id, key asc;
\ No newline at end of file
+select arg_set_id, flat_key, key, int_value, string_value from args order by arg_set_id, key asc;
\ No newline at end of file
diff --git a/test/trace_processor/track_event_same_tids_slices.out b/test/trace_processor/track_event_same_tids_slices.out
index 48fa77b..d882f13 100644
--- a/test/trace_processor/track_event_same_tids_slices.out
+++ b/test/trace_processor/track_event_same_tids_slices.out
@@ -1,3 +1,3 @@
-"thread","ts","dur","category","name","arg_set_id"
-"t1",1000,0,"cat","name1",0
-"t2",2000,0,"cat","name2",0
+"track","process","thread","thread_process","ts","dur","category","name","arg_set_id"
+"[NULL]","[NULL]","t1","[NULL]",1000,0,"cat","name1",0
+"[NULL]","[NULL]","t2","[NULL]",2000,0,"cat","name2",0
diff --git a/test/trace_processor/track_event_slices.sql b/test/trace_processor/track_event_slices.sql
index 42f7b69..5146810 100644
--- a/test/trace_processor/track_event_slices.sql
+++ b/test/trace_processor/track_event_slices.sql
@@ -14,13 +14,20 @@
-- limitations under the License.
--
select
+ track.name as track,
+ process.name as process,
thread.name as thread,
+ thread_process.name as thread_process,
slice.ts,
slice.dur,
slice.category,
slice.name,
slice.arg_set_id
from slice
+left join track on slice.track_id = track.id
+left join process_track on slice.track_id = process_track.id
+left join process on process_track.upid = process.upid
left join thread_track on slice.track_id = thread_track.id
left join thread on thread_track.utid = thread.utid
+left join process thread_process on thread.upid = thread_process.upid
order by ts asc;
diff --git a/test/trace_processor/track_event_tracks.textproto b/test/trace_processor/track_event_tracks.textproto
index fd8cdc8..b76fa36 100644
--- a/test/trace_processor/track_event_tracks.textproto
+++ b/test/trace_processor/track_event_tracks.textproto
@@ -5,6 +5,7 @@
incremental_state_cleared: true
track_descriptor {
uuid: 1
+ parent_uuid: 10
thread {
pid: 5
tid: 1
@@ -24,6 +25,7 @@
incremental_state_cleared: true
track_descriptor {
uuid: 2
+ parent_uuid: 10
thread {
pid: 5
tid: 2
@@ -36,13 +38,54 @@
}
}
}
+# Both thread tracks are nested underneath this process track.
+packet {
+ trusted_packet_sequence_id: 1
+ timestamp: 0
+ track_descriptor {
+ uuid: 10
+ process {
+ pid: 5
+ process_name: "p1"
+ }
+ }
+}
+# And we have an async track underneath the process too.
+packet {
+ trusted_packet_sequence_id: 1
+ timestamp: 0
+ track_descriptor {
+ uuid: 11
+ parent_uuid: 10
+ name: "async"
+ }
+}
+packet {
+ trusted_packet_sequence_id: 1
+ timestamp: 100
+ track_descriptor {
+ uuid: 12
+ parent_uuid: 10
+ name: "async2"
+ }
+}
+packet {
+ trusted_packet_sequence_id: 2
+ timestamp: 200
+ track_descriptor {
+ uuid: 12
+ parent_uuid: 10
+ name: "async2"
+ }
+}
+
# Should appear on default track "t1".
packet {
trusted_packet_sequence_id: 1
timestamp: 1000
track_event {
categories: "cat"
- name: "name1"
+ name: "event1_on_t1"
type: 3
}
}
@@ -52,7 +95,7 @@
timestamp: 2000
track_event {
categories: "cat"
- name: "name2"
+ name: "event1_on_t2"
type: 3
}
}
@@ -63,7 +106,173 @@
track_event {
track_uuid: 2
categories: "cat"
- name: "name3"
+ name: "event2_on_t2"
type: 3
}
}
+# Should appear on process track.
+packet {
+ trusted_packet_sequence_id: 1
+ timestamp: 4000
+ track_event {
+ track_uuid: 10
+ categories: "cat"
+ name: "event1_on_p1"
+ type: 3
+ }
+}
+# Should appear on async track.
+packet {
+ trusted_packet_sequence_id: 1
+ timestamp: 5000
+ track_event {
+ track_uuid: 11
+ categories: "cat"
+ name: "event1_on_async"
+ type: 3
+ }
+}
+# Event for the "async2" track starting on one thread and ending on another.
+packet {
+ trusted_packet_sequence_id: 1
+ timestamp: 5100
+ track_event {
+ track_uuid: 12
+ categories: "cat"
+ name: "event1_on_async2"
+ type: 1
+ }
+}
+packet {
+ trusted_packet_sequence_id: 2
+ timestamp: 5200
+ track_event {
+ track_uuid: 12
+ categories: "cat"
+ name: "event1_on_async2"
+ type: 2
+ }
+}
+
+# If we later see another track descriptor for tid 1, but with a different uuid,
+# we should detect tid reuse and start a new thread.
+packet {
+ trusted_packet_sequence_id: 3
+ timestamp: 10000
+ incremental_state_cleared: true
+ track_descriptor {
+ uuid: 3
+ parent_uuid: 10
+ thread {
+ pid: 5
+ tid: 1
+ thread_name: "t3"
+ }
+ }
+}
+# Should appear on t3.
+packet {
+ trusted_packet_sequence_id: 3
+ timestamp: 11000
+ track_event {
+ track_uuid: 3
+ categories: "cat"
+ name: "event1_on_t3"
+ type: 3
+ }
+}
+
+# If we later see another track descriptor for pid 5, but with a different uuid,
+# we should detect pid reuse and start a new process.
+packet {
+ trusted_packet_sequence_id: 4
+ timestamp: 20000
+ incremental_state_cleared: true
+ track_descriptor {
+ uuid: 20
+ process {
+ pid: 5
+ process_name: "p2"
+ }
+ }
+}
+# Should appear on p2.
+packet {
+ trusted_packet_sequence_id: 4
+ timestamp: 21000
+ track_event {
+ track_uuid: 20
+ categories: "cat"
+ name: "event1_on_p2"
+ type: 3
+ }
+}
+# Another thread t4 in the new process.
+packet {
+ trusted_packet_sequence_id: 4
+ timestamp: 22000
+ incremental_state_cleared: true
+ track_descriptor {
+ uuid: 21
+ parent_uuid: 20
+ thread {
+ pid: 5
+ tid: 4
+ thread_name: "t4"
+ }
+ }
+}
+# Should appear on t4.
+packet {
+ trusted_packet_sequence_id: 4
+ timestamp: 22000
+ track_event {
+ track_uuid: 21
+ categories: "cat"
+ name: "event1_on_t4"
+ type: 3
+ }
+}
+
+# Another packet for a thread track in the old process, badly sorted.
+packet {
+ trusted_packet_sequence_id: 2
+ timestamp: 6000
+ track_event {
+ track_uuid: 1
+ categories: "cat"
+ name: "event3_on_t1"
+ type: 3
+ }
+}
+
+# Override the track to the default descriptor track for an event with a
+# TrackEvent type. Should appear on the default descriptor track instead of
+# "t1".
+packet {
+ trusted_packet_sequence_id: 1
+ timestamp: 30000
+ track_event {
+ track_uuid: 0
+ categories: "cat"
+ name: "event1_on_t1"
+ type: 3
+ }
+}
+
+# But a legacy event without TrackEvent type falls back to legacy tracks (based
+# on ThreadDescriptor / async IDs / legacy instant scopes). This instant event
+# should appear on the process track "p2".
+packet {
+ trusted_packet_sequence_id: 1
+ timestamp: 31000
+ track_event {
+ track_uuid: 0
+ categories: "cat"
+ name: "event1_on_t1"
+ legacy_event {
+ phase: 73 # 'I'
+ instant_event_scope: 2 # Process scope
+ }
+ }
+}
diff --git a/test/trace_processor/track_event_tracks_slices.out b/test/trace_processor/track_event_tracks_slices.out
index 93c7186..d7119df 100644
--- a/test/trace_processor/track_event_tracks_slices.out
+++ b/test/trace_processor/track_event_tracks_slices.out
@@ -1,4 +1,13 @@
-"thread","ts","dur","category","name","arg_set_id"
-"t1",1000,0,"cat","name1",0
-"t2",2000,0,"cat","name2",0
-"t2",3000,0,"cat","name3",0
+"track","process","thread","thread_process","ts","dur","category","name","arg_set_id"
+"[NULL]","[NULL]","t1","p1",1000,0,"cat","event1_on_t1",0
+"[NULL]","[NULL]","t2","p1",2000,0,"cat","event1_on_t2",0
+"[NULL]","[NULL]","t2","p1",3000,0,"cat","event2_on_t2",0
+"[NULL]","p1","[NULL]","[NULL]",4000,0,"cat","event1_on_p1",8
+"async","p1","[NULL]","[NULL]",5000,0,"cat","event1_on_async",8
+"async2","p1","[NULL]","[NULL]",5100,100,"cat","event1_on_async2",3
+"[NULL]","[NULL]","t1","p1",6000,0,"cat","event3_on_t1",0
+"[NULL]","[NULL]","t3","p1",11000,0,"cat","event1_on_t3",0
+"[NULL]","p2","[NULL]","[NULL]",21000,0,"cat","event1_on_p2",7
+"[NULL]","[NULL]","t4","p2",22000,0,"cat","event1_on_t4",0
+"Default Track","[NULL]","[NULL]","[NULL]",30000,0,"cat","event1_on_t1",0
+"[NULL]","p2","[NULL]","[NULL]",31000,0,"cat","event1_on_t1",6
diff --git a/test/trace_processor/track_event_typed_args_args.out b/test/trace_processor/track_event_typed_args_args.out
index f08c63e..c66424f 100644
--- a/test/trace_processor/track_event_typed_args_args.out
+++ b/test/trace_processor/track_event_typed_args_args.out
@@ -1,5 +1,5 @@
"arg_set_id","flat_key","key","int_value","string_value"
-2,"user_event.action","user_event.action","[NULL]","NewTab"
-3,"legacy_ipc.class","legacy_ipc.class","[NULL]","AUTOMATION"
-3,"legacy_ipc.line","legacy_ipc.line",10,"[NULL]"
-4,"keyed_service.name","keyed_service.name","[NULL]","MediaRouter"
+1,"user_event.action","user_event.action","[NULL]","NewTab"
+2,"legacy_ipc.class","legacy_ipc.class","[NULL]","AUTOMATION"
+2,"legacy_ipc.line","legacy_ipc.line",10,"[NULL]"
+3,"keyed_service.name","keyed_service.name","[NULL]","MediaRouter"
diff --git a/test/trace_processor/track_event_typed_args_slices.out b/test/trace_processor/track_event_typed_args_slices.out
index 6a9a969..830accb 100644
--- a/test/trace_processor/track_event_typed_args_slices.out
+++ b/test/trace_processor/track_event_typed_args_slices.out
@@ -1,4 +1,4 @@
-"thread","ts","dur","category","name","arg_set_id"
-"t1",1000,0,"cat","name1",2
-"t1",2000,0,"cat","name2",3
-"t1",3000,0,"cat","name3",4
+"track","process","thread","thread_process","ts","dur","category","name","arg_set_id"
+"[NULL]","[NULL]","t1","[NULL]",1000,0,"cat","name1",1
+"[NULL]","[NULL]","t1","[NULL]",2000,0,"cat","name2",2
+"[NULL]","[NULL]","t1","[NULL]",3000,0,"cat","name3",3
diff --git a/test/trace_processor/vulkan_api_events.out b/test/trace_processor/vulkan_api_events.out
new file mode 100644
index 0000000..de409f9
--- /dev/null
+++ b/test/trace_processor/vulkan_api_events.out
@@ -0,0 +1,5 @@
+"track_name","track_desc","ts","dur","slice_name","depth","flat_key","int_value","context_id","command_buffer","submission_id"
+"Vulkan Events","[NULL]",10,2,"vkQueueSubmit",0,"pid",42,"[NULL]",100,1
+"Vulkan Events","[NULL]",10,2,"vkQueueSubmit",0,"tid",43,"[NULL]",100,1
+"Vulkan Events","[NULL]",20,2,"vkQueueSubmit",0,"pid",44,"[NULL]",200,2
+"Vulkan Events","[NULL]",20,2,"vkQueueSubmit",0,"tid",45,"[NULL]",200,2
diff --git a/test/trace_processor/vulkan_api_events.py b/test/trace_processor/vulkan_api_events.py
new file mode 100644
index 0000000..b279f7a
--- /dev/null
+++ b/test/trace_processor/vulkan_api_events.py
@@ -0,0 +1,40 @@
+#!/usr/bin/python
+# Copyright (C) 2020 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.
+
+from os import sys, path
+sys.path.append(path.dirname(path.dirname(path.abspath(__file__))))
+import synth_common
+
+trace = synth_common.create_trace()
+
+trace.add_vk_queue_submit(
+ ts=10,
+ dur=2,
+ pid=42,
+ tid=43,
+ vk_queue=10,
+ vk_command_buffers=[100],
+ submission_id=1)
+
+trace.add_vk_queue_submit(
+ ts=20,
+ dur=2,
+ pid=44,
+ tid=45,
+ vk_queue=11,
+ vk_command_buffers=[200, 300, 400],
+ submission_id=2)
+
+print(trace.trace.SerializeToString())
diff --git a/test/trace_processor/vulkan_api_events.sql b/test/trace_processor/vulkan_api_events.sql
new file mode 100644
index 0000000..89fccd9
--- /dev/null
+++ b/test/trace_processor/vulkan_api_events.sql
@@ -0,0 +1,23 @@
+--
+-- Copyright 2020 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
+--
+-- https://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.
+--
+SELECT track.name AS track_name, gpu_track.description AS track_desc, ts, dur,
+ gpu_slice.name AS slice_name, depth, flat_key, int_value,
+ gpu_slice.context_id, command_buffer, submission_id
+FROM gpu_track
+LEFT JOIN track USING (id)
+INNER JOIN gpu_slice ON gpu_track.id=gpu_slice.track_id
+LEFT JOIN args ON gpu_slice.arg_set_id = args.arg_set_id
+ORDER BY ts;
diff --git a/tools/BUILD.gn b/tools/BUILD.gn
index 6214548..a018fd4 100644
--- a/tools/BUILD.gn
+++ b/tools/BUILD.gn
@@ -45,9 +45,7 @@
if (is_linux && enable_perfetto_heapprofd) {
executable("profiling_sample_distribution") {
- sources = [
- "profiling_sample_distribution.cc",
- ]
+ sources = [ "profiling_sample_distribution.cc" ]
deps = [
"../gn:default_deps",
"../src/base",
@@ -57,12 +55,8 @@
}
executable("idle_alloc") {
- deps = [
- "../gn:default_deps",
- ]
- sources = [
- "idle_alloc.cc",
- ]
+ deps = [ "../gn:default_deps" ]
+ sources = [ "idle_alloc.cc" ]
}
# The protoc binary can end up in out/protoc or out/gcc_like_host/protoc
@@ -73,22 +67,14 @@
if (current_toolchain != host_toolchain) {
copy("copy_protoc") {
testonly = true
- deps = [
- protoc_target,
- ]
+ deps = [ protoc_target ]
host_out_dir = get_label_info(protoc_target, "root_out_dir")
- sources = [
- "$host_out_dir/protoc",
- ]
- outputs = [
- "$root_build_dir/protoc",
- ]
+ sources = [ "$host_out_dir/protoc" ]
+ outputs = [ "$root_build_dir/protoc" ]
}
} else {
# Nothing to do, in this case protoc is already built in the root out dir.
group("copy_protoc") {
- public_deps = [
- protoc_target,
- ]
+ public_deps = [ protoc_target ]
}
}
diff --git a/tools/busy_threads/BUILD.gn b/tools/busy_threads/BUILD.gn
index 0f33776..84391fe 100644
--- a/tools/busy_threads/BUILD.gn
+++ b/tools/busy_threads/BUILD.gn
@@ -18,7 +18,5 @@
"../../gn:default_deps",
"../../src/base",
]
- sources = [
- "busy_threads.cc",
- ]
+ sources = [ "busy_threads.cc" ]
}
diff --git a/tools/compact_reencode/BUILD.gn b/tools/compact_reencode/BUILD.gn
index 6556b9d..799f313 100644
--- a/tools/compact_reencode/BUILD.gn
+++ b/tools/compact_reencode/BUILD.gn
@@ -31,7 +31,5 @@
"../../protos/perfetto/trace/ftrace:zero",
"../../src/base",
]
- sources = [
- "main.cc",
- ]
+ sources = [ "main.cc" ]
}
diff --git a/tools/cpu_utilization/BUILD.gn b/tools/cpu_utilization/BUILD.gn
index 1b70388..ccbdd2f 100644
--- a/tools/cpu_utilization/BUILD.gn
+++ b/tools/cpu_utilization/BUILD.gn
@@ -18,7 +18,5 @@
"../../gn:default_deps",
"../../src/base",
]
- sources = [
- "cpu_utilization.cc",
- ]
+ sources = [ "cpu_utilization.cc" ]
}
diff --git a/tools/diff_test_trace_processor.py b/tools/diff_test_trace_processor.py
index 2d92f39..cb1ba78 100755
--- a/tools/diff_test_trace_processor.py
+++ b/tools/diff_test_trace_processor.py
@@ -295,7 +295,7 @@
elif args.test_type == 'metrics':
index = os.path.join(test_dir, 'metrics', 'index')
else:
- print('Unknown test type {}. Supported: queries, metircs'.format(
+ print('Unknown test type {}. Supported: queries, metrics'.format(
args.test_type))
return 1
diff --git a/tools/dump_ftrace_stats/BUILD.gn b/tools/dump_ftrace_stats/BUILD.gn
index 3a047d5..1ee0cc0 100644
--- a/tools/dump_ftrace_stats/BUILD.gn
+++ b/tools/dump_ftrace_stats/BUILD.gn
@@ -19,7 +19,5 @@
"../../include/perfetto/base",
"../../src/base",
]
- sources = [
- "main.cc",
- ]
+ sources = [ "main.cc" ]
}
diff --git a/tools/ftrace_proto_gen/BUILD.gn b/tools/ftrace_proto_gen/BUILD.gn
index a63d696..1b96c30 100644
--- a/tools/ftrace_proto_gen/BUILD.gn
+++ b/tools/ftrace_proto_gen/BUILD.gn
@@ -17,9 +17,7 @@
perfetto_host_executable("ftrace_proto_gen") {
testonly = true
- sources = [
- "main.cc",
- ]
+ sources = [ "main.cc" ]
deps = [
":lib",
"../../gn:default_deps",
@@ -37,9 +35,7 @@
"../../gn:gtest_and_gmock",
"../../gn:protobuf_full",
]
- sources = [
- "ftrace_proto_gen_unittest.cc",
- ]
+ sources = [ "ftrace_proto_gen_unittest.cc" ]
}
source_set("lib") {
diff --git a/tools/ftrace_proto_gen/ftrace_descriptor_gen.cc b/tools/ftrace_proto_gen/ftrace_descriptor_gen.cc
index 4339e47..9384622 100644
--- a/tools/ftrace_proto_gen/ftrace_descriptor_gen.cc
+++ b/tools/ftrace_proto_gen/ftrace_descriptor_gen.cc
@@ -47,7 +47,7 @@
* limitations under the License.
*/
- )";
+)";
*fout << "// Autogenerated by:\n";
*fout << std::string("// ") + __FILE__ + "\n";
*fout << "// Do not edit.\n";
diff --git a/tools/ftrace_proto_gen/ftrace_proto_gen.cc b/tools/ftrace_proto_gen/ftrace_proto_gen.cc
index 4ef59b3..7ed8110 100644
--- a/tools/ftrace_proto_gen/ftrace_proto_gen.cc
+++ b/tools/ftrace_proto_gen/ftrace_proto_gen.cc
@@ -49,7 +49,7 @@
* limitations under the License.
*/
- )";
+)";
} // namespace
@@ -124,8 +124,7 @@
*fout << std::string("// ") + __FILE__ + "\n";
*fout << "// Do not edit.\n\n";
*fout << R"(syntax = "proto2";)"
- << "\n";
- *fout << "option optimize_for = LITE_RUNTIME;\n\n";
+ << "\n\n";
for (const std::string& group : groups) {
*fout << R"(import "protos/perfetto/trace/ftrace/)" << group
@@ -267,7 +266,6 @@
s += R"(
syntax = "proto2";
-option optimize_for = LITE_RUNTIME;
package perfetto.protos;
)";
diff --git a/tools/gen_amalgamated b/tools/gen_amalgamated
index ea6e254..79a572d 100755
--- a/tools/gen_amalgamated
+++ b/tools/gen_amalgamated
@@ -117,6 +117,7 @@
# ----------------------------------------------------------------------------
tool_name = os.path.basename(__file__)
+project_root = os.path.abspath(os.path.dirname(os.path.dirname(__file__)))
preamble = """// Copyright (C) 2019 The Android Open Source Project
//
// Licensed under the Apache License, Version 2.0 (the "License");
@@ -143,6 +144,12 @@
return [item for item in items if re.match(whitelist, item)]
+def normalize_path(path):
+ path = os.path.relpath(path, project_root)
+ path = re.sub(r'^out/[^/]+/', '', path)
+ return path
+
+
class Error(Exception):
pass
@@ -332,7 +339,8 @@
if not rel_path in allowed_files:
return
with open(full_path) as f:
- self.source.append('// %s begin header: %s' % (tool_name, rel_path))
+ self.source.append(
+ '// %s begin header: %s' % (tool_name, normalize_path(full_path)))
self.source.extend(
self._process_source_includes(include_dirs, allowed_files, f))
return
@@ -351,12 +359,13 @@
if not os.path.exists(full_path):
raise Error('Source file %s not found' % source_name)
with open(full_path) as f:
- self.source.append('// %s begin source: %s' % (tool_name, source_name))
+ self.source.append(
+ '// %s begin source: %s' % (tool_name, normalize_path(full_path)))
try:
self.source.extend(
self._patch_source(
- source_name,
- self._process_source_includes(include_dirs, deps, f)))
+ source_name, self._process_source_includes(
+ include_dirs, deps, f)))
except Error as e:
raise Error('Failed adding source %s: %s' % (source_name, e.message))
@@ -368,7 +377,8 @@
full_path = os.path.join(gn_utils.repo_root(), include_dir, header_name)
if os.path.exists(full_path):
with open(full_path) as f:
- self.header.append('// %s begin header: %s' % (tool_name, full_path))
+ self.header.append(
+ '// %s begin header: %s' % (tool_name, normalize_path(full_path)))
self.header.extend(self._process_header_includes(include_dirs, f))
return
if self._compute_deps_only:
@@ -387,7 +397,8 @@
return
raise Error('Header file %s not found' % header_name)
with open(full_path) as f:
- self.header.append('// %s begin header: %s' % (tool_name, header_name))
+ self.header.append(
+ '// %s begin header: %s' % (tool_name, normalize_path(full_path)))
try:
self.header.extend(self._process_header_includes(include_dirs, f))
except Error as e:
@@ -507,8 +518,8 @@
Example build command:
%s
-""" % (header_file, source_file, ' '.join(self.cflags), ' '.join(
- self.ldflags), ' '.join(self.libs), ' '.join(build_cmd))
+""" % (header_file, source_file, ' '.join(self.cflags), ' '.join(self.ldflags),
+ ' '.join(self.libs), ' '.join(build_cmd))
def get_build_command(self, output_prefix):
"""Returns an example command line for building the output source."""
diff --git a/tools/gen_android_bp b/tools/gen_android_bp
index ebc440a..7c1c444 100755
--- a/tools/gen_android_bp
+++ b/tools/gen_android_bp
@@ -62,6 +62,7 @@
'//src/traced/probes:traced_probes',
'//src/traced/service:traced',
'//test/cts:perfetto_cts_deps',
+ '//test/cts:perfetto_cts_jni_deps',
]
# Host targets
@@ -144,7 +145,11 @@
with open(os.path.join(ROOT_DIR, 'tools', 'test_data.txt')) as f:
lines = f.readlines()
for line in (line.strip() for line in lines if not line.startswith('#')):
- assert os.path.exists(line), line
+ assert os.path.exists(line), 'file %s should exist' % line
+ if line.startswith('test/data/'):
+ # Skip test data files that require GCS. They are only for benchmarks.
+ # We don't run benchmarks in the android tree.
+ continue
if line.endswith('/'):
yield line + '**/*'
else:
@@ -166,9 +171,6 @@
('required', {'libperfetto_android_internal', 'trigger_perfetto'}),
],
'libperfetto_android_internal': [('static_libs', {'libhealthhalutils'}),],
- 'traced_perf': [
- ('include_dirs', {'bionic/libc/kernel'}),
- ],
'trace_processor_shell': [
('dist', {'targets': ['sdk_repo']}),
('stl', 'libc++_static'),
@@ -226,6 +228,10 @@
module.shared_libs.add('libz')
+def enable_uapi_headers(module):
+ module.include_dirs.add('bionic/libc/kernel')
+
+
# Android equivalents for third-party libraries that the upstream project
# depends on.
builtin_deps = {
@@ -240,6 +246,7 @@
'//gn:libunwindstack': enable_libunwindstack,
'//gn:sqlite': enable_sqlite,
'//gn:zlib': enable_zlib,
+ '//gn:bionic_kernel_uapi_headers' : enable_uapi_headers,
}
# ----------------------------------------------------------------------------
@@ -515,7 +522,7 @@
if target.proto_plugin == 'proto':
suffixes = ['pb']
source_module.genrule_shared_libs.add('libprotobuf-cpp-lite')
- cmd += ['--cpp_out=' + cpp_out_dir]
+ cmd += ['--cpp_out=lite=true:' + cpp_out_dir]
elif target.proto_plugin == 'protozero':
suffixes = ['pbzero']
plugin = create_modules_from_target(blueprint, gn, protozero_plugin)
diff --git a/tools/gen_bazel b/tools/gen_bazel
index f8150d3..00568b2 100755
--- a/tools/gen_bazel
+++ b/tools/gen_bazel
@@ -165,7 +165,10 @@
continue
res += ' %s = ' % k
if isinstance(v, basestring):
- res += '"%s",\n' % v
+ if v.startswith('PERFETTO_CONFIG.'):
+ res += '%s,\n' % v
+ else:
+ res += '"%s",\n' % v
elif isinstance(v, bool):
res += '%s,\n' % v
elif isinstance(v, list):
@@ -198,7 +201,7 @@
# Public visibility for targets in Bazel.
-PUBLIC_VISIBILITY = ['//visibility:public']
+PUBLIC_VISIBILITY = 'PERFETTO_CONFIG.public_visibility'
def get_bazel_label_name(gn_name):
diff --git a/tools/gen_binary_descriptors b/tools/gen_binary_descriptors
index 439d596..839d7c0 100755
--- a/tools/gen_binary_descriptors
+++ b/tools/gen_binary_descriptors
@@ -37,6 +37,8 @@
'src/protozero/test/example_proto/test_messages.descriptor.h',
'protos/perfetto/trace/track_event/track_event.proto':
'src/trace_processor/importers/proto/track_event.descriptor.h',
+ 'protos/perfetto/metrics/custom_options.proto':
+ 'src/trace_processor/metrics/custom_options.descriptor.h',
}
ROOT_DIR = os.path.dirname(os.path.dirname(os.path.realpath(__file__)))
@@ -83,6 +85,8 @@
protoc_path,
'--include_imports',
'--proto_path=.',
+ '--proto_path=' + \
+ os.path.join(ROOT_DIR, "buildtools", "protobuf", "src"),
'--descriptor_set_out={}'.format(fdescriptor.name),
source,
],
diff --git a/tools/gen_merged_protos b/tools/gen_merged_protos
index 5cfece7..a8f9aa6 100755
--- a/tools/gen_merged_protos
+++ b/tools/gen_merged_protos
@@ -218,12 +218,12 @@
def main():
- config_result = merge_protos(COMMON_PROTOS + CONFIG_PROTOS,
- MERGED_CONFIG_PROTO, False)
- trace_result = merge_protos(COMMON_PROTOS + TRACE_PROTOS + CONFIG_PROTOS,
- MERGED_TRACE_PROTO, False)
- trace_result = merge_protos(METRICS_PROTOS, MERGED_METRICS_PROTO, True)
- return 0 if config_result and trace_result else 1
+ result = merge_protos(COMMON_PROTOS + CONFIG_PROTOS, MERGED_CONFIG_PROTO,
+ False)
+ result &= merge_protos(COMMON_PROTOS + TRACE_PROTOS + CONFIG_PROTOS,
+ MERGED_TRACE_PROTO, False)
+ result &= merge_protos(METRICS_PROTOS, MERGED_METRICS_PROTO, True)
+ return 0 if result else 1
if __name__ == '__main__':
diff --git a/tools/heap_profile b/tools/heap_profile
index eb5035f..8662bbf 100755
--- a/tools/heap_profile
+++ b/tools/heap_profile
@@ -31,8 +31,8 @@
import urllib
TRACE_TO_TEXT_SHAS = {
- 'linux': 'cd6d89e0ada48c0d7850206d80c324b912a3db42',
- 'mac': 'aadf14ce5988e5d5e283fb816f72bb2bba8cc9e4',
+ 'linux': 'f9c206e242c49ebd4ec5e4138c61f4fb2816065b',
+ 'mac': '7e1803f5c51d0763061d2980fd9af5750ac9d9c8',
}
TRACE_TO_TEXT_PATH = tempfile.gettempdir()
TRACE_TO_TEXT_BASE_URL = ('https://storage.googleapis.com/perfetto/')
@@ -99,8 +99,11 @@
duration_ms: {duration}
write_into_file: true
flush_timeout_ms: 30000
+flush_period_ms: 604800000
'''
+# flush_period_ms of 1 week to suppress trace_processor_shell warning.
+
CONTINUOUS_DUMP = """
continuous_dump_config {{
dump_phase_ms: 0
@@ -119,6 +122,13 @@
IS_INTERRUPTED = True
+def print_no_profile_error():
+ print("No profiles generated", file=sys.stderr)
+ print(
+ "If this is unexpected, check "
+ "https://docs.perfetto.dev/#/heapprofd?id=troubleshooting.",
+ file=sys.stderr)
+
def main(argv):
parser = argparse.ArgumentParser()
parser.add_argument(
@@ -344,6 +354,7 @@
old_handler = signal.signal(signal.SIGINT, sigint_handler)
print("Profiling active. Press Ctrl+C to terminate.")
print("You may disconnect your device.")
+ print()
exists = True
device_connected = True
while not device_connected or (exists and not IS_INTERRUPTED):
@@ -385,16 +396,12 @@
if 'heap_profile-' in word:
profile_path = word
if profile_path is None:
- print("Could not find trace_to_text output path.", file=sys.stderr)
+ print_no_profile_error();
return 1
profile_files = os.listdir(profile_path)
if not profile_files:
- print("No profiles generated", file=sys.stderr)
- print(
- "If this is unexpected, check "
- "https://docs.perfetto.dev/#/heapprofd?id=troubleshooting.",
- file=sys.stderr)
+ print_no_profile_error();
return 1
subprocess.check_call(
@@ -417,7 +424,8 @@
env=os.environ,
stdout=fd)
if ret != 0:
- print("Failed to symbolize.", file=sys.stderr)
+ print("Failed to symbolize. Continuing without symbols.",
+ file=sys.stderr)
print("Wrote profiles to {} (symlink {})".format(profile_path, symlink_path))
print("These can be viewed using pprof. Googlers: head to pprof/ and "
diff --git a/tools/install-build-deps b/tools/install-build-deps
index 43545f6..e1e9c20 100755
--- a/tools/install-build-deps
+++ b/tools/install-build-deps
@@ -44,11 +44,11 @@
BUILD_DEPS_HOST = [
# GN
('buildtools/mac/gn',
- 'https://storage.googleapis.com/perfetto/gn-mac-b5b65ca39d93a7cde9fa713be31b114755252f28',
- 'b5b65ca39d93a7cde9fa713be31b114755252f28', 'darwin'),
+ 'https://storage.googleapis.com/perfetto/gn-mac-1695-83dad00a',
+ '4c0d45772aea4146699772165e8112fa76ceb295', 'darwin'),
('buildtools/linux64/gn',
- 'https://storage.googleapis.com/perfetto/gn-linux64-1370d9c5358868b7b66292821b6fe61950826870',
- '1370d9c5358868b7b66292821b6fe61950826870', 'linux'),
+ 'https://storage.googleapis.com/perfetto/gn-linux64-1695-83dad00a',
+ 'fcabfc379bccaa65b4e2fc791594ba124dafc7d0', 'linux'),
# clang-format
('buildtools/mac/clang-format',
@@ -84,7 +84,7 @@
# lib from sources. Keep the SHA1s in sync with Chrome's src/buildtools/DEPS.
('buildtools/libcxx',
'https://chromium.googlesource.com/chromium/llvm-project/libcxx.git',
- '5938e0582bac570a41edb3d6a2217c299adc1bc6', 'all'),
+ '78d6a7767ed57b50122a161b91f59f19c9bd0d19', 'all'),
('buildtools/libcxxabi',
'https://chromium.googlesource.com/chromium/llvm-project/libcxxabi.git',
'0d529660e32d77d9111912d73f2c74fc5fa2a858', 'all'),
@@ -95,13 +95,13 @@
# Keep the revision in sync with Chrome's PACKAGE_VERSION in
# tools/clang/scripts/update.py.
('buildtools/clang.tgz',
- 'https://commondatastorage.googleapis.com/chromium-browser-clang/Linux_x64/clang-365097-f7e52fbd-8.tgz',
- 'fe1b1e5bd7381ae655661cb9658487389561568d', 'linux'),
+ 'https://commondatastorage.googleapis.com/chromium-browser-clang/Linux_x64/clang-n332890-c2443155-2.tgz',
+ 'd6501ffdb5dbb0ffe8a4b873cc092a9929e661ec', 'linux'),
# Keep in sync with chromium DEPS.
('buildtools/libfuzzer',
'https://chromium.googlesource.com/chromium/llvm-project/compiler-rt/lib/fuzzer.git',
- 'b9f51dc8c98065df0c8da13c051046f5bab833db', 'linux'),
+ 'debe7d2d1982e540fbd6bd78604bf001753f9e74', 'linux'),
# Benchmarking tool.
('buildtools/benchmark.zip',
@@ -132,7 +132,7 @@
# These dependencies are for libunwindstack, which is used by src/profiling.
('buildtools/android-core',
'https://android.googlesource.com/platform/system/core.git',
- '3f407fcc37b401c91784700c0a691ba8b1f7ef15', 'all'),
+ '8bf4e29e44098e3232ff646331675fb113064162', 'all'),
('buildtools/lzma',
'https://android.googlesource.com/platform/external/lzma.git',
'7851dce6f4ca17f5caa1c93a4e0a45686b1d56c3', 'all'),
@@ -146,8 +146,8 @@
# Example traces for regression tests.
(
'buildtools/test_data.zip',
- 'https://storage.googleapis.com/perfetto/test-data-20191107-164334.zip',
- '499f11fbc2b04ef7742662a26b85ef03141e24bd',
+ 'https://storage.googleapis.com/perfetto/test-data-20200122-100845.zip',
+ '56ac45b5239fda50d33cf05bfd329dcb3efb0b2a',
'all',
),
diff --git a/tools/protoprofile/BUILD.gn b/tools/protoprofile/BUILD.gn
index d23cbf8..48fbc85 100644
--- a/tools/protoprofile/BUILD.gn
+++ b/tools/protoprofile/BUILD.gn
@@ -30,10 +30,6 @@
"../../src/base",
"../../src/protozero",
]
- sources = [
- "main.cc",
- ]
- deps = [
- "../../gn:protobuf_full",
- ]
+ sources = [ "main.cc" ]
+ deps = [ "../../gn:protobuf_full" ]
}
diff --git a/tools/sanitizers_unittests/BUILD.gn b/tools/sanitizers_unittests/BUILD.gn
index be69e1a..26ef638 100644
--- a/tools/sanitizers_unittests/BUILD.gn
+++ b/tools/sanitizers_unittests/BUILD.gn
@@ -18,7 +18,5 @@
"../../gn:default_deps",
"../../gn:gtest_and_gmock",
]
- sources = [
- "sanitizers_unittest.cc",
- ]
+ sources = [ "sanitizers_unittest.cc" ]
}
diff --git a/tools/skippy/BUILD.gn b/tools/skippy/BUILD.gn
index 087c2ad1..b2926c0 100644
--- a/tools/skippy/BUILD.gn
+++ b/tools/skippy/BUILD.gn
@@ -18,7 +18,5 @@
"../../gn:default_deps",
"../../src/base",
]
- sources = [
- "skippy.cc",
- ]
+ sources = [ "skippy.cc" ]
}
diff --git a/tools/test_data.txt b/tools/test_data.txt
index d2dd686..abcb65d 100644
--- a/tools/test_data.txt
+++ b/tools/test_data.txt
@@ -2,3 +2,4 @@
# to the root.
src/traced/probes/ftrace/test/data/
src/traced/probes/filesystem/testdata/
+test/data/kallsyms.txt
diff --git a/tools/trace_to_text/BUILD.gn b/tools/trace_to_text/BUILD.gn
index 41c844d..bb0cf7b 100644
--- a/tools/trace_to_text/BUILD.gn
+++ b/tools/trace_to_text/BUILD.gn
@@ -50,10 +50,12 @@
"../../src/profiling/symbolizer:symbolize_database",
]
public_deps = [
- "../../gn:zlib",
"../../include/perfetto/ext/base",
"../../include/perfetto/profiling:deobfuscator",
]
+ if (enable_perfetto_zlib) {
+ public_deps += [ "../../gn:zlib" ]
+ }
sources = [
"utils.cc",
"utils.h",
@@ -61,9 +63,7 @@
}
source_set("pprofbuilder") {
- public_deps = [
- "../../include/perfetto/profiling:pprof_builder",
- ]
+ public_deps = [ "../../include/perfetto/profiling:pprof_builder" ]
deps = [
":utils",
"../../gn:default_deps",
@@ -76,17 +76,13 @@
"../../src/profiling/symbolizer",
"../../src/profiling/symbolizer:symbolize_database",
]
- sources = [
- "pprof_builder.cc",
- ]
+ sources = [ "pprof_builder.cc" ]
}
# Exposed in bazel builds.
static_library("libpprofbuilder") {
complete_static_lib = true
- deps = [
- ":pprofbuilder",
- ]
+ deps = [ ":pprofbuilder" ]
}
# The core source files that are used both by the "full" version (the host
@@ -131,9 +127,7 @@
"../../gn:default_deps",
"../../include/perfetto/base",
]
- sources = [
- "lite_fallbacks.cc",
- ]
+ sources = [ "lite_fallbacks.cc" ]
}
# Full target for the host. Depends on libprotobuf-full.
@@ -144,9 +138,11 @@
":utils",
"../../gn:default_deps",
"../../gn:protobuf_full",
- "../../gn:zlib",
"../../protos/perfetto/trace:zero",
]
+ if (enable_perfetto_zlib) {
+ deps += [ "../../gn:zlib" ]
+ }
sources = [
"proto_full_utils.cc",
"proto_full_utils.h",
diff --git a/tools/trace_to_text/pprof_builder.cc b/tools/trace_to_text/pprof_builder.cc
index 4da0d9d..4f57829 100644
--- a/tools/trace_to_text/pprof_builder.cc
+++ b/tools/trace_to_text/pprof_builder.cc
@@ -214,7 +214,8 @@
max_symbol_id_(max_symbol_id) {
// The pprof format expects the first entry in the string table to be the
// empty string.
- Intern("");
+ int64_t empty_id = Intern("");
+ PERFETTO_CHECK(empty_id == 0);
}
std::vector<Iterator> BuildViewIterators(trace_processor::TraceProcessor* tp,
@@ -375,7 +376,9 @@
std::string frame_name = frame_it.Get(1).string_value;
int64_t mapping_id = frame_it.Get(2).long_value;
int64_t rel_pc = frame_it.Get(3).long_value;
- int64_t symbol_set_id = frame_it.Get(4).long_value;
+ base::Optional<int64_t> symbol_set_id;
+ if (!frame_it.Get(4).is_null())
+ symbol_set_id = frame_it.Get(4).long_value;
seen_mappings->emplace(mapping_id);
auto* glocation = result_->add_location();
@@ -386,7 +389,7 @@
// mapping.start_offset)).
glocation->set_address(static_cast<uint64_t>(rel_pc));
if (symbol_set_id) {
- for (const Line& line : LineForSymbolSetId(symbol_set_id)) {
+ for (const Line& line : LineForSymbolSetId(*symbol_set_id)) {
seen_symbol_ids->emplace(line.symbol_id);
auto* gline = glocation->add_line();
gline->set_line(line.line_number);
diff --git a/tools/trace_to_text/trace_to_text.cc b/tools/trace_to_text/trace_to_text.cc
index 3fb86d8..1616a2d 100644
--- a/tools/trace_to_text/trace_to_text.cc
+++ b/tools/trace_to_text/trace_to_text.cc
@@ -16,8 +16,6 @@
#include "tools/trace_to_text/trace_to_text.h"
-#include <zlib.h>
-
#include <google/protobuf/compiler/importer.h>
#include <google/protobuf/dynamic_message.h>
#include <google/protobuf/io/zero_copy_stream_impl.h>
@@ -31,6 +29,10 @@
#include "protos/perfetto/trace/trace.pbzero.h"
#include "protos/perfetto/trace/trace_packet.pbzero.h"
+#if PERFETTO_BUILDFLAG(PERFETTO_ZLIB)
+#include <zlib.h>
+#endif
+
namespace perfetto {
namespace trace_to_text {
@@ -78,6 +80,7 @@
void PrintCompressedPackets(const std::string& packets,
Message* compressed_msg_scratch,
ZeroCopyOutputStream* output) {
+#if PERFETTO_BUILDFLAG(PERFETTO_ZLIB)
uint8_t out[4096];
std::vector<uint8_t> data;
@@ -120,6 +123,24 @@
}
WriteToZeroCopyOutput(output, kCompressedPacketsSuffix,
sizeof(kCompressedPacketsSuffix) - 1);
+#else
+ base::ignore_result(packets);
+ base::ignore_result(compressed_msg_scratch);
+ base::ignore_result(kIndentedPacketPrefix);
+ base::ignore_result(kIndentedPacketSuffix);
+ WriteToZeroCopyOutput(output, kCompressedPacketsPrefix,
+ sizeof(kCompressedPacketsPrefix) - 1);
+ static const char kErrMsg[] =
+ "Cannot decode compressed packets. zlib not enabled in the build config";
+ WriteToZeroCopyOutput(output, kErrMsg, sizeof(kErrMsg) - 1);
+ WriteToZeroCopyOutput(output, kCompressedPacketsSuffix,
+ sizeof(kCompressedPacketsSuffix) - 1);
+ static bool log_once = [] {
+ PERFETTO_ELOG("%s", kErrMsg);
+ return true;
+ }();
+ base::ignore_result(log_once);
+#endif // PERFETTO_BUILDFLAG(PERFETTO_ZLIB)
}
} // namespace
diff --git a/tools/trace_to_text/utils.cc b/tools/trace_to_text/utils.cc
index 73645f6..e655b38 100644
--- a/tools/trace_to_text/utils.cc
+++ b/tools/trace_to_text/utils.cc
@@ -39,8 +39,9 @@
using Iterator = trace_processor::TraceProcessor::Iterator;
-
+#if PERFETTO_BUILDFLAG(PERFETTO_ZLIB)
constexpr size_t kCompressionBufferSize = 500 * 1024;
+#endif
std::map<std::string, std::set<std::string>> GetHeapGraphClasses(
trace_processor::TraceProcessor* tp) {
@@ -179,7 +180,6 @@
return true;
}
-
void DeobfuscateDatabase(
trace_processor::TraceProcessor* tp,
const std::map<std::string, profiling::ObfuscatedClass>& mapping,
@@ -229,6 +229,8 @@
output_->write(data, static_cast<std::streamsize>(sz));
}
+#if PERFETTO_BUILDFLAG(PERFETTO_ZLIB)
+
DeflateTraceWriter::DeflateTraceWriter(std::ostream* output)
: TraceWriter(output),
buf_(base::PagedMemory::Allocate(kCompressionBufferSize)),
@@ -270,6 +272,15 @@
PERFETTO_FATAL("Expected %d got %d: %s", actual_code, expected_code,
stream_.msg);
}
+#else
+
+DeflateTraceWriter::DeflateTraceWriter(std::ostream* output)
+ : TraceWriter(output) {
+ PERFETTO_ELOG("Cannot compress. Zlib is not enabled in the build config");
+}
+DeflateTraceWriter::~DeflateTraceWriter() = default;
+
+#endif // PERFETTO_BUILDFLAG(PERFETTO_ZLIB)
} // namespace trace_to_text
} // namespace perfetto
diff --git a/tools/trace_to_text/utils.h b/tools/trace_to_text/utils.h
index 19bd3ca..d708e04 100644
--- a/tools/trace_to_text/utils.h
+++ b/tools/trace_to_text/utils.h
@@ -26,13 +26,15 @@
#include <memory>
#include <vector>
-#include <zlib.h>
-
#include "perfetto/base/build_config.h"
#include "perfetto/ext/base/optional.h"
#include "perfetto/ext/base/paged_memory.h"
#include "perfetto/profiling/deobfuscator.h"
+#if PERFETTO_BUILDFLAG(PERFETTO_ZLIB)
+#include <zlib.h>
+#endif
+
namespace perfetto {
namespace trace_processor {
@@ -83,6 +85,7 @@
std::ostream* output_;
};
+#if PERFETTO_BUILDFLAG(PERFETTO_ZLIB)
class DeflateTraceWriter : public TraceWriter {
public:
DeflateTraceWriter(std::ostream* output);
@@ -100,6 +103,17 @@
uint8_t* const end_;
};
+#else
+
+// Fallback implementation. Will print an error and write uncompressed.
+class DeflateTraceWriter : public TraceWriter {
+ public:
+ DeflateTraceWriter(std::ostream* output);
+ ~DeflateTraceWriter() override;
+};
+
+#endif // PERFETTO_BUILDFLAG(PERFETTO_ZLIB)
+
} // namespace trace_to_text
} // namespace perfetto
diff --git a/ui/BUILD.gn b/ui/BUILD.gn
index b27e380..b488557 100644
--- a/ui/BUILD.gn
+++ b/ui/BUILD.gn
@@ -28,23 +28,44 @@
# +----------------------------------------------------------------------------+
# | The outer "ui" target to just ninja -C out/xxx ui |
# +----------------------------------------------------------------------------+
+
group("ui") {
deps = [
- ":assets_dist",
- ":catapult_dist",
":chrome_extension_assets_dist",
":chrome_extension_bundle_dist",
- ":controller_bundle_dist",
- ":engine_bundle_dist",
- ":frontend_bundle_dist",
- ":index_dist",
- ":scss",
+ ":dist",
+ ":gen_dist_file_map",
+ ":service_worker_bundle_dist",
":test_scripts",
- ":typefaces_dist",
- ":wasm_dist",
+
+ # IMPORTANT: Only add deps here if they are NOT part of the production UI
+ # (e.g., tests, extensions, ...). Any UI dep should go in the
+ # |ui_dist_targets| list below. The only exception is the service worker
+ # target, that depends on that list.
]
}
+# The list of targets that produces dist/ files for the UI. This list is used
+# also by the gen_dist_file_map to generate the map of hashes of all UI files,
+# which is turn used by the service worker code for the offline caching.
+ui_dist_targets = [
+ ":assets_dist",
+ ":catapult_dist",
+ ":controller_bundle_dist",
+ ":engine_bundle_dist",
+ ":frontend_bundle_dist",
+ ":index_dist",
+ ":scss",
+ ":typefaces_dist",
+ ":wasm_dist",
+]
+
+# Buils the ui, but not service worker, tests and extensions.
+group("dist") {
+ deps = ui_dist_targets
+}
+
+# A minimal page to profile the WASM engine without the all UI.
group("query") {
deps = [
":query_bundle_dist",
@@ -64,9 +85,7 @@
"outputs",
"depfile",
])
- deps = [
- ":node_modules",
- ]
+ deps = [ ":node_modules" ]
if (defined(invoker.deps)) {
deps += invoker.deps
}
@@ -95,9 +114,7 @@
assert(defined(invoker.input))
assert(defined(invoker.output))
forward_variables_from(invoker, [ "deps" ])
- inputs = [
- invoker.input,
- ]
+ inputs = [ invoker.input ]
outputs = [
invoker.output,
invoker.output + ".map",
@@ -151,41 +168,37 @@
# included by the .html files.
bundle("frontend_bundle") {
- deps = [
- ":transpile_all_ts",
- ]
+ deps = [ ":transpile_all_ts" ]
input = "$target_out_dir/frontend/index.js"
output = "$target_out_dir/frontend_bundle.js"
}
bundle("chrome_extension_bundle") {
- deps = [
- ":transpile_all_ts",
- ]
+ deps = [ ":transpile_all_ts" ]
input = "$target_out_dir/chrome_extension/index.js"
output = "$target_out_dir/chrome_extension_bundle.js"
}
bundle("controller_bundle") {
- deps = [
- ":transpile_all_ts",
- ]
+ deps = [ ":transpile_all_ts" ]
input = "$target_out_dir/controller/index.js"
output = "$target_out_dir/controller_bundle.js"
}
bundle("engine_bundle") {
- deps = [
- ":transpile_all_ts",
- ]
+ deps = [ ":transpile_all_ts" ]
input = "$target_out_dir/engine/index.js"
output = "$target_out_dir/engine_bundle.js"
}
+bundle("service_worker_bundle") {
+ deps = [ ":transpile_service_worker_ts" ]
+ input = "$target_out_dir/service_worker/service_worker.js"
+ output = "$target_out_dir/service_worker.js"
+}
+
bundle("query_bundle") {
- deps = [
- ":transpile_all_ts",
- ]
+ deps = [ ":transpile_all_ts" ]
input = "$target_out_dir/query/index.js"
output = "$target_out_dir/query_bundle.js"
}
@@ -203,9 +216,7 @@
"../protos/perfetto/ipc/consumer_port.proto",
"../protos/perfetto/ipc/wire_protocol.proto",
]
- outputs = [
- "$ui_gen_dir/protos.js",
- ]
+ outputs = [ "$ui_gen_dir/protos.js" ]
node_cmd = "pbjs"
args = [
"-t",
@@ -222,15 +233,9 @@
# Protobuf.js requires to first generate .js files from the .proto and then
# create .ts definitions for them.
node_bin("protos_to_ts") {
- deps = [
- ":protos_to_js",
- ]
- inputs = [
- "$ui_gen_dir/protos.js",
- ]
- outputs = [
- "$ui_gen_dir/protos.d.ts",
- ]
+ deps = [ ":protos_to_js" ]
+ inputs = [ "$ui_gen_dir/protos.js" ]
+ outputs = [ "$ui_gen_dir/protos.d.ts" ]
node_cmd = "pbts"
args = [
"-p",
@@ -252,9 +257,7 @@
":protos_to_ts",
":wasm_gen",
]
- inputs = [
- "tsconfig.json",
- ]
+ inputs = [ "tsconfig.json" ]
outputs = [
"$target_out_dir/frontend/index.js",
"$target_out_dir/engine/index.js",
@@ -270,6 +273,7 @@
"--filter=*.ts",
"--exclude=node_modules",
"--exclude=dist",
+ "--exclude=service_worker",
"--deps=obj/ui/frontend/index.js",
"--output=" + rebase_path(depfile),
],
@@ -284,6 +288,26 @@
]
}
+node_bin("transpile_service_worker_ts") {
+ deps = [
+ ":dist_symlink",
+ ":gen_dist_file_map",
+ ]
+ inputs = [
+ "tsconfig.json",
+ "src/service_worker/service_worker.ts",
+ ]
+ outputs = [ "$target_out_dir/service_worker/service_worker.js" ]
+
+ node_cmd = "tsc"
+ args = [
+ "--project",
+ rebase_path("src/service_worker", root_build_dir),
+ "--outDir",
+ rebase_path(target_out_dir, root_build_dir),
+ ]
+}
+
# +----------------------------------------------------------------------------+
# | Build css. |
# +----------------------------------------------------------------------------+
@@ -301,13 +325,9 @@
# Build css.
node_bin("scss") {
- deps = [
- ":dist_symlink",
- ]
+ deps = [ ":dist_symlink" ]
inputs = [ scss_root ] + scss_srcs
- outputs = [
- "$ui_dir/perfetto.css",
- ]
+ outputs = [ "$ui_dir/perfetto.css" ]
node_cmd = "node-sass"
args = [
@@ -321,12 +341,8 @@
# | Copy rules: create the final output directory. |
# +----------------------------------------------------------------------------+
copy("index_dist") {
- sources = [
- "index.html",
- ]
- outputs = [
- "$ui_dir/index.html",
- ]
+ sources = [ "index.html" ]
+ outputs = [ "$ui_dir/index.html" ]
}
copy("typefaces_dist") {
@@ -339,18 +355,12 @@
"../buildtools/typefaces/RobotoMono-Regular.woff2",
]
- outputs = [
- "$ui_dir/assets/{{source_file_part}}",
- ]
+ outputs = [ "$ui_dir/assets/{{source_file_part}}" ]
}
copy("query_dist") {
- sources = [
- "query.html",
- ]
- outputs = [
- "$ui_dir/query.html",
- ]
+ sources = [ "query.html" ]
+ outputs = [ "$ui_dir/query.html" ]
}
copy("assets_dist") {
@@ -377,9 +387,7 @@
"src/assets/rec_ring_buf.png",
"src/assets/rec_vmstat.png",
] + [ scss_root ] + scss_srcs
- outputs = [
- "$ui_dir/assets/{{source_file_part}}",
- ]
+ outputs = [ "$ui_dir/assets/{{source_file_part}}" ]
}
copy("chrome_extension_assets_dist") {
sources = [
@@ -387,47 +395,41 @@
"src/assets/logo.png",
"src/chrome_extension/manifest.json",
]
- outputs = [
- "$chrome_extension_dir/{{source_file_part}}",
- ]
+ outputs = [ "$chrome_extension_dir/{{source_file_part}}" ]
}
sorcery("frontend_bundle_dist") {
- deps = [
- ":frontend_bundle",
- ]
+ deps = [ ":frontend_bundle" ]
input = "$target_out_dir/frontend_bundle.js"
output = "$ui_dir/frontend_bundle.js"
}
sorcery("chrome_extension_bundle_dist") {
- deps = [
- ":chrome_extension_bundle",
- ]
+ deps = [ ":chrome_extension_bundle" ]
input = "$target_out_dir/chrome_extension_bundle.js"
output = "$chrome_extension_dir/chrome_extension_bundle.js"
}
sorcery("controller_bundle_dist") {
- deps = [
- ":controller_bundle",
- ]
+ deps = [ ":controller_bundle" ]
input = "$target_out_dir/controller_bundle.js"
output = "$ui_dir/controller_bundle.js"
}
sorcery("engine_bundle_dist") {
- deps = [
- ":engine_bundle",
- ]
+ deps = [ ":engine_bundle" ]
input = "$target_out_dir/engine_bundle.js"
output = "$ui_dir/engine_bundle.js"
}
+sorcery("service_worker_bundle_dist") {
+ deps = [ ":service_worker_bundle" ]
+ input = "$target_out_dir/service_worker.js"
+ output = "$ui_dir/service_worker.js"
+}
+
sorcery("query_bundle_dist") {
- deps = [
- ":query_bundle",
- ]
+ deps = [ ":query_bundle" ]
input = "$target_out_dir/query_bundle.js"
output = "$ui_dir/query_bundle.js"
}
@@ -441,9 +443,7 @@
"$root_build_dir/wasm/trace_processor.wasm",
"$root_build_dir/wasm/trace_to_text.wasm",
]
- outputs = [
- "$ui_dir/{{source_file_part}}",
- ]
+ outputs = [ "$ui_dir/{{source_file_part}}" ]
}
copy("wasm_gen") {
@@ -477,9 +477,7 @@
"$root_build_dir/wasm/trace_to_text.wasm.map",
]
}
- outputs = [
- "$ui_gen_dir/{{source_file_part}}",
- ]
+ outputs = [ "$ui_gen_dir/{{source_file_part}}" ]
}
# Copy over the vulcanized legacy trace viewer.
@@ -488,9 +486,7 @@
"../buildtools/catapult_trace_viewer/catapult_trace_viewer.html",
"../buildtools/catapult_trace_viewer/catapult_trace_viewer.js",
]
- outputs = [
- "$ui_dir/assets/{{source_file_part}}",
- ]
+ outputs = [ "$ui_dir/assets/{{source_file_part}}" ]
}
# +----------------------------------------------------------------------------+
@@ -505,17 +501,13 @@
rebase_path("$target_out_dir/node_exists", ""),
]
inputs = []
- outputs = [
- "$target_out_dir/node_exists",
- ]
+ outputs = [ "$target_out_dir/node_exists" ]
}
# Creates a symlink from out/xxx/ui/node_modules -> ../../../ui/node_modules.
# This allows to run rollup and other node tools from the out/xxx directory.
action("node_modules_symlink") {
- deps = [
- ":check_node_exists",
- ]
+ deps = [ ":check_node_exists" ]
script = "../gn/standalone/build_tool_wrapper.py"
stamp_file = "$target_out_dir/.$target_name.stamp"
@@ -527,15 +519,11 @@
rebase_path("node_modules", target_out_dir),
rebase_path("$target_out_dir/node_modules", root_build_dir),
]
- outputs = [
- stamp_file,
- ]
+ outputs = [ stamp_file ]
}
group("node_modules") {
- deps = [
- ":node_modules_symlink",
- ]
+ deps = [ ":node_modules_symlink" ]
}
# Creates a symlink from //ui/dist -> ../../out/xxx/ui. Used only for
@@ -553,12 +541,8 @@
rebase_path(target_out_dir, "."),
rebase_path("dist", root_build_dir),
]
- inputs = [
- "$root_build_dir",
- ]
- outputs = [
- stamp_file,
- ]
+ inputs = [ "$root_build_dir" ]
+ outputs = [ stamp_file ]
}
group("test_scripts") {
@@ -569,19 +553,36 @@
}
copy("copy_unittests_script") {
- sources = [
- "config/ui_unittests_template",
- ]
- outputs = [
- "$root_build_dir/ui_unittests",
- ]
+ sources = [ "config/ui_unittests_template" ]
+ outputs = [ "$root_build_dir/ui_unittests" ]
}
copy("copy_tests_script") {
- sources = [
- "config/ui_tests_template",
- ]
- outputs = [
- "$root_build_dir/ui_tests",
- ]
+ sources = [ "config/ui_tests_template" ]
+ outputs = [ "$root_build_dir/ui_tests" ]
+}
+
+# This target generates an map containing all the UI subresources and their
+# hashes. This is used by the service worker code for offline caching.
+# This taarget needs to be kept at the end of the BUILD.gn file, because of the
+# get_target_outputs() call (fails otherwise due to GN's evaluation order).
+action("gen_dist_file_map") {
+ out_file_path = "$ui_gen_dir/dist_file_map.ts"
+
+ dist_files = []
+ foreach(target, ui_dist_targets) {
+ foreach(dist_file, get_target_outputs(target)) {
+ dist_files += [ rebase_path(dist_file, root_build_dir) ]
+ }
+ }
+ deps = [ ":dist" ]
+ script = "../gn/standalone/write_ui_dist_file_map.py"
+ inputs = []
+ outputs = [ out_file_path ]
+ args = [
+ "--out",
+ rebase_path(out_file_path, root_build_dir),
+ "--strip",
+ rebase_path(ui_dir, root_build_dir),
+ ] + dist_files
}
diff --git a/ui/index.html b/ui/index.html
index 0e1833a..6fa32a6 100644
--- a/ui/index.html
+++ b/ui/index.html
@@ -6,11 +6,11 @@
<!-- WebComponents V0 origin trial token for https://ui.perfetto.dev Expires 17 Dec 2020.
See https://crbug.com/1021137. -->
<meta http-equiv="origin-trial" content="AtzsILqIzNPGftktQTEYxI9GpnqFBuse5uB5n4JQO3Wa1ky4TCKmnXZli0A9g9p7Es7Il9pqarELntnfm0HriwkAAABreyJvcmlnaW4iOiJodHRwczovL3VpLnBlcmZldHRvLmRldjo0NDMiLCJmZWF0dXJlIjoiV2ViQ29tcG9uZW50c1YwIiwiZXhwaXJ5IjoxNjA4MjI2NDQzLCJpc1N1YmRvbWFpbiI6dHJ1ZX0=">
+ <!-- WebComponents V0 origin trial token for http://localhost:10000 Expires 28 Jan 2021.
+ See https://crbug.com/1021137. -->
+ <meta http-equiv="origin-trial" content="AicMEv5glMGL1lq6ZRsxFJj8xlhn3XDYZrHK0/2KreAD/r62vTFjUBOueeMTxWuU1IlRXqCugRFDD7rY45YEgwkAAABTeyJvcmlnaW4iOiJodHRwOi8vbG9jYWxob3N0OjEwMDAwIiwiZmVhdHVyZSI6IldlYkNvbXBvbmVudHNWMCIsImV4cGlyeSI6MTYxMTg0MDczNH0=">
<link href="perfetto.css" rel="stylesheet">
<link rel="icon" type="image/png" href="assets/logo.png">
- <link rel="preload" href="controller_bundle.js" as="script">
- <link rel="preload" href="engine_bundle.js" as="script">
- <link rel="preload" href="trace_processor.wasm" as="fetch">
</head>
<body>
<main>
diff --git a/ui/src/assets/record.scss b/ui/src/assets/record.scss
index 7600ebd..d5d0e6a 100644
--- a/ui/src/assets/record.scss
+++ b/ui/src/assets/record.scss
@@ -136,12 +136,12 @@
border: 1px solid #eee;
outline: none;
margin: 4px;
- border-radius: 10px;
+ border-radius: 20px;
padding: 4px;
height: 30px;
&:hover, &:active {
- box-shadow: 0 0 4px 0px #999;
- background-color: hsl(88, 50%, 84%);
+ box-shadow: 0 0 4px 0px #ccc;
+ background-color: #fafafa;
}
i {
margin: 3px;
@@ -274,6 +274,7 @@
transition: opacity 0.25s ease;
opacity: 0;
visibility: hidden;
+ overflow: auto;
&:not(.active) {
max-height: 0;
@@ -693,7 +694,6 @@
&.two-columns {
height: 400px;
- width: auto;
margin: var(--record-section-padding);
optgroup {
display: grid;
@@ -719,10 +719,6 @@
height: 152px;
}
- .chrome-categories {
- height: 152px;
- }
-
textarea.extra-input {
width: 100%;
height: 60px;
@@ -774,6 +770,8 @@
font-size: 12px;
line-height: 20px;
overflow-y: auto;
+ white-space: pre-wrap;
+ word-wrap: break-word;
// 510px and not 500px, so the overflowing line gets truncated, giving
// a clear indication that the code box scrolls.
diff --git a/ui/src/assets/sidebar.scss b/ui/src/assets/sidebar.scss
index 7cb1ce2..7868f27 100644
--- a/ui/src/assets/sidebar.scss
+++ b/ui/src/assets/sidebar.scss
@@ -184,7 +184,7 @@
}
}
- > .num-queued-queries {
+ > .dbg-info-square {
width: 24px;
height: 22px;
line-height: 22px;
@@ -194,11 +194,15 @@
border-radius: 5px;
font-size: 12px;
text-align: center;
- &.rpc {
+ &.green {
background: #7aca75;
color: #12161b;
}
- &.failed {
+ &.amber {
+ background: #FFC107;
+ color: #333;
+ }
+ &.red {
background: #d32f2f;
color: #fff;
}
diff --git a/ui/src/assets/topbar.scss b/ui/src/assets/topbar.scss
index 49c06df..03a907f 100644
--- a/ui/src/assets/topbar.scss
+++ b/ui/src/assets/topbar.scss
@@ -201,4 +201,50 @@
right: -90%;
}
}
+
+ .notification-btn {
+ @include transition(0.25s);
+ font-size: 16px;
+ padding: 8px 10px;
+ margin: 0 10px;
+ border-radius: 2px;
+ background: hsl(210, 10%, 73%);
+ &:hover {
+ background: hsl(210, 10%, 83%);
+ }
+
+ &.preferred {
+ background: hsl(210, 98%, 53%);
+ color: #fff;
+ &:hover {
+ background: hsl(210, 98%, 63%);
+ }
+ }
+ }
+}
+
+.helpful-hint {
+ position: absolute;
+ right: 5px;
+ top: 5px;
+ width: 300px;
+ background-color: white;
+ font-size: 12px;
+ color: #3f4040;
+ display: grid;
+ border-radius: 5px;
+ padding: 8px;
+ box-shadow: 1px 3px 15px rgba(23, 32, 44, 0.3);
+}
+
+.hint-text {
+ padding-bottom: 5px
+}
+
+.hint-dismiss-button {
+ color: #f4fafb;
+ background-color: #19212b;
+ width: fit-content;
+ padding: 3px;
+ border-radius: 3px;
}
diff --git a/ui/src/chrome_extension/chrome_tracing_controller.ts b/ui/src/chrome_extension/chrome_tracing_controller.ts
index 356bd44..280068a 100644
--- a/ui/src/chrome_extension/chrome_tracing_controller.ts
+++ b/ui/src/chrome_extension/chrome_tracing_controller.ts
@@ -208,8 +208,14 @@
fetchCategories();
return;
}
- // Otherwise, we find attach to the target temporarily.
- this.devtoolsSocket.findAndAttachTarget(async _ => {
+ // Otherwise, we attach temporarily.
+ this.devtoolsSocket.attachToBrowser(async (error?: string) => {
+ if (error) {
+ this.sendErrorMessage(
+ `Could not attach to DevTools browser target ` +
+ `(req. Chrome >= M81): ${error}`);
+ return;
+ }
fetchCategories();
this.devtoolsSocket.detach();
});
@@ -230,7 +236,13 @@
}
handleStartTracing(traceConfig: Protocol.Tracing.TraceConfig) {
- this.devtoolsSocket.findAndAttachTarget(async _ => {
+ this.devtoolsSocket.attachToBrowser(async (error?: string) => {
+ if (error) {
+ this.sendErrorMessage(
+ `Could not attach to DevTools browser target ` +
+ `(req. Chrome >= M81): ${error}`);
+ return;
+ }
await this.api.Tracing.start({
traceConfig,
streamFormat: 'proto',
diff --git a/ui/src/chrome_extension/devtools_socket.ts b/ui/src/chrome_extension/devtools_socket.ts
index aa23f8f..bb40f5c 100644
--- a/ui/src/chrome_extension/devtools_socket.ts
+++ b/ui/src/chrome_extension/devtools_socket.ts
@@ -64,25 +64,20 @@
throw new Error('Call unexpected');
}
- findTarget(then: (target: chrome.debugger.Debuggee) => void) {
- chrome.debugger.getTargets(targets => {
- const perfettoTab =
- targets.find(target => target.title.includes('Perfetto'));
- if (perfettoTab === undefined) {
- console.log('No perfetto tab found');
- return;
- }
- this.target = {targetId: perfettoTab.id};
- then(this.target);
- });
+ attachToBrowser(then: (error?: string) => void) {
+ this.attachToTarget({targetId: 'browser'}, then);
}
- findAndAttachTarget(then: (target: chrome.debugger.Debuggee) => void) {
- this.findTarget(t => {
- chrome.debugger.attach(t, /*requiredVersion=*/ '1.3', () => {
- this.openCallback();
- then(t);
- });
+ private attachToTarget(
+ target: chrome.debugger.Debuggee, then: (error?: string) => void) {
+ chrome.debugger.attach(target, /*requiredVersion=*/ '1.3', () => {
+ if (chrome.runtime.lastError) {
+ then(chrome.runtime.lastError.message);
+ return;
+ }
+ this.target = target;
+ this.openCallback();
+ then();
});
}
diff --git a/ui/src/chrome_extension/index.ts b/ui/src/chrome_extension/index.ts
index 2d8f4fc..6350c84 100644
--- a/ui/src/chrome_extension/index.ts
+++ b/ui/src/chrome_extension/index.ts
@@ -54,7 +54,7 @@
}
chrome.declarativeContent.onPageChanged.removeRules(undefined, () => {
chrome.declarativeContent.onPageChanged.addRules([
- enableOnHostWithSuffix('.perfetto.local'),
+ enableOnHostWithSuffix('localhost'),
enableOnHostWithSuffix('.perfetto.dev'),
]);
});
diff --git a/ui/src/chrome_extension/manifest.json b/ui/src/chrome_extension/manifest.json
index 5abd7bb..5008c01 100644
--- a/ui/src/chrome_extension/manifest.json
+++ b/ui/src/chrome_extension/manifest.json
@@ -2,8 +2,9 @@
"name": "Perfetto UI",
"key":"MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAhm3X7qutsrskke84ltokTObnFJakd/d0XFQ6Ox2wQueHTGJM5GUNPTY/x8bdreNtGnfzvt/Sd0vABbR0wsS6lz5yY+g6ksMXJnigFe9N7uz8E3KojDrl3xYjIe+mkiJo8yxxzPydgb7GjQ6jmsX3g+yjj67kXzm9rZFkmoZ5WmqwBZlguPYVRN/W8CIIqBZkC3Qmq6uSG7b/g93YbwqmTmGiL2sAzgvXtqvDOD6503abtQkRC795E4VjJd+ffyeRH38fAEz5ZIrA6GJsfmov1TZTIu1NTwqylSpBYl5as7C6gpmuxDV4SvHvGT2hMQuIufDhZhErjI3B7bcX+XLe1wIDAQAB",
"description": "Enables the Perfetto trace viewer (https://ui.perfetto.dev) to record Chrome browser traces.",
- "version": "0.0.0.9",
+ "version": "0.0.0.11",
"manifest_version": 2,
+ "minimum_chrome_version": "81.0.4022.0",
"permissions": [
"declarativeContent",
"debugger"
@@ -19,7 +20,7 @@
},
"externally_connectable": {
"matches": [
- "*://*.perfetto.local/*",
+ "*://localhost/*",
"https://*.perfetto.dev/*"
]
}
diff --git a/ui/src/common/actions.ts b/ui/src/common/actions.ts
index c5f7f63..8e43ca5 100644
--- a/ui/src/common/actions.ts
+++ b/ui/src/common/actions.ts
@@ -426,18 +426,26 @@
},
selectHeapProfile(
- state: StateDraft, args: {id: number, upid: number, ts: number}): void {
- state.currentSelection =
- {kind: 'HEAP_PROFILE', id: args.id, upid: args.upid, ts: args.ts};
+ state: StateDraft,
+ args: {id: number, upid: number, ts: number, type: string}): void {
+ state.currentSelection = {
+ kind: 'HEAP_PROFILE',
+ id: args.id,
+ upid: args.upid,
+ ts: args.ts,
+ type: args.type
+ };
},
showHeapProfileFlamegraph(
- state: StateDraft, args: {id: number, upid: number, ts: number}): void {
+ state: StateDraft,
+ args: {id: number, upid: number, ts: number, type: string}): void {
state.currentHeapProfileFlamegraph = {
kind: 'HEAP_PROFILE_FLAMEGRAPH',
id: args.id,
upid: args.upid,
ts: args.ts,
+ type: args.type,
};
},
diff --git a/ui/src/common/flamegraph_unittest.ts b/ui/src/common/flamegraph_unittest.ts
index fc19250..6b3e178 100644
--- a/ui/src/common/flamegraph_unittest.ts
+++ b/ui/src/common/flamegraph_unittest.ts
@@ -162,7 +162,7 @@
{
id: 2,
parentId: 1,
- name: 'A2',
+ name: '[merged]',
depth: 1,
totalSize: 10,
selfSize: 0,
@@ -269,7 +269,7 @@
{
id: 3,
parentId: 1,
- name: 'A3',
+ name: '[merged]',
depth: 1,
totalSize: 5,
selfSize: 0,
@@ -278,7 +278,7 @@
{
id: 6,
parentId: 3,
- name: 'A36',
+ name: '[merged]',
depth: 2,
totalSize: 3,
selfSize: 0,
@@ -392,7 +392,7 @@
{
id: 3,
parentId: 1,
- name: 'A3',
+ name: '[merged]',
depth: 1,
totalSize: 5,
selfSize: 0,
@@ -507,7 +507,7 @@
{
id: 3,
parentId: 1,
- name: 'A3',
+ name: '[merged]',
depth: 1,
totalSize: 4,
selfSize: 0,
@@ -597,7 +597,7 @@
{
id: 1,
parentId: -1,
- name: 'A',
+ name: '[merged]',
depth: 0,
totalSize: 12,
selfSize: 0,
@@ -821,7 +821,7 @@
{
id: 4,
parentId: 1,
- name: 'A4',
+ name: '[merged]',
depth: 1,
totalSize: 35,
selfSize: 0,
@@ -857,7 +857,7 @@
{
id: 10,
parentId: 4,
- name: 'A410',
+ name: '[merged]',
depth: 2,
totalSize: 25,
selfSize: 0,
@@ -866,7 +866,7 @@
{
id: 15,
parentId: 7,
- name: 'A715',
+ name: '[merged]',
depth: 2,
totalSize: 25,
selfSize: 0,
diff --git a/ui/src/common/flamegraph_util.ts b/ui/src/common/flamegraph_util.ts
index f4f4d16..383f603 100644
--- a/ui/src/common/flamegraph_util.ts
+++ b/ui/src/common/flamegraph_util.ts
@@ -66,6 +66,7 @@
copiedCallsite.parentId =
getCallsitesParentHash(copiedCallsite, mergedCallsites);
+ let mergedAny = false;
// If current callsite is small, find other small callsites with same depth
// and parent and merge them into the current one, marking them as merged.
if (copiedCallsite.totalSize <= minSizeDisplayed && i + 1 < data.length) {
@@ -77,10 +78,14 @@
nextCallsite.totalSize <= minSizeDisplayed) {
copiedCallsite.totalSize += nextCallsite.totalSize;
mergedCallsites.set(nextCallsite.id, copiedCallsite.id);
+ mergedAny = true;
}
j++;
nextCallsite = data[j];
}
+ if (mergedAny) {
+ copiedCallsite.name = '[merged]';
+ }
}
mergedData.push(copiedCallsite);
}
@@ -112,4 +117,4 @@
i++;
}
return totalSize;
-}
\ No newline at end of file
+}
diff --git a/ui/src/common/state.ts b/ui/src/common/state.ts
index cf9fc43..b7f2f40 100644
--- a/ui/src/common/state.ts
+++ b/ui/src/common/state.ts
@@ -163,6 +163,7 @@
id: number;
upid: number;
ts: number;
+ type: string;
}
export interface HeapProfileFlamegraph {
@@ -170,6 +171,7 @@
id: number;
upid: number;
ts: number;
+ type: string;
expandedCallsite?: CallsiteInfo;
viewingOption?: string;
}
@@ -424,6 +426,214 @@
];
}
+export function getBuiltinChromeCategoryList(): string[] {
+ // List of static Chrome categories, last updated at Chromium 81.0.4021.0 from
+ // Chromium's //base/trace_event/builtin_categories.h.
+ return [
+ 'accessibility',
+ 'AccountFetcherService',
+ 'android_webview',
+ 'audio',
+ 'base',
+ 'benchmark',
+ 'blink',
+ 'blink.animations',
+ 'blink.console',
+ 'blink_gc',
+ 'blink.net',
+ 'blink_style',
+ 'blink.user_timing',
+ 'blink.worker',
+ 'Blob',
+ 'browser',
+ 'browsing_data',
+ 'CacheStorage',
+ 'camera',
+ 'cast_perf_test',
+ 'cast.stream',
+ 'cc',
+ 'cc.debug',
+ 'cdp.perf',
+ 'chromeos',
+ 'cma',
+ 'compositor',
+ 'content',
+ 'content_capture',
+ 'devtools',
+ 'devtools.timeline',
+ 'devtools.timeline.async',
+ 'download',
+ 'download_service',
+ 'drm',
+ 'drmcursor',
+ 'dwrite',
+ 'DXVA Decoding',
+ 'EarlyJava',
+ 'evdev',
+ 'event',
+ 'exo',
+ 'explore_sites',
+ 'FileSystem',
+ 'file_system_provider',
+ 'fonts',
+ 'GAMEPAD',
+ 'gpu',
+ 'gpu.capture',
+ 'headless',
+ 'hwoverlays',
+ 'identity',
+ 'IndexedDB',
+ 'input',
+ 'io',
+ 'ipc',
+ 'Java',
+ 'jni',
+ 'jpeg',
+ 'latency',
+ 'latencyInfo',
+ 'leveldb',
+ 'loading',
+ 'log',
+ 'login',
+ 'media',
+ 'media_router',
+ 'memory',
+ 'midi',
+ 'mojom',
+ 'mus',
+ 'native',
+ 'navigation',
+ 'net',
+ 'netlog',
+ 'offline_pages',
+ 'omnibox',
+ 'oobe',
+ 'ozone',
+ 'passwords',
+ 'p2p',
+ 'page-serialization',
+ 'pepper',
+ 'ppapi',
+ 'ppapi proxy',
+ 'rail',
+ 'renderer',
+ 'renderer_host',
+ 'renderer.scheduler',
+ 'RLZ',
+ 'safe_browsing',
+ 'screenlock_monitor',
+ 'sequence_manager',
+ 'service_manager',
+ 'ServiceWorker',
+ 'shell',
+ 'shortcut_viewer',
+ 'shutdown',
+ 'SiteEngagement',
+ 'skia',
+ 'startup',
+ 'sync',
+ 'sync_lock_contention',
+ 'thread_pool',
+ 'test_gpu',
+ 'test_tracing',
+ 'toplevel',
+ 'ui',
+ 'v8',
+ 'v8.execute',
+ 'ValueStoreFrontend::Backend',
+ 'views',
+ 'views.frame',
+ 'viz',
+ 'vk',
+ 'wayland',
+ 'webaudio',
+ 'weblayer',
+ 'WebCore',
+ 'webrtc',
+ 'xr',
+ 'disabled-by-default-animation-worklet',
+ 'disabled-by-default-audio-worklet',
+ 'disabled-by-default-blink.debug',
+ 'disabled-by-default-blink.debug.display_lock',
+ 'disabled-by-default-blink.debug.layout',
+ 'disabled-by-default-blink.debug.layout.trees',
+ 'disabled-by-default-blink.feature_usage',
+ 'disabled-by-default-blink_gc',
+ 'disabled-by-default-blink.image_decoding',
+ 'disabled-by-default-blink.invalidation',
+ 'disabled-by-default-cc',
+ 'disabled-by-default-cc.debug',
+ 'disabled-by-default-cc.debug.cdp-perf',
+ 'disabled-by-default-cc.debug.display_items',
+ 'disabled-by-default-cc.debug.picture',
+ 'disabled-by-default-cc.debug.scheduler',
+ 'disabled-by-default-cc.debug.scheduler.frames',
+ 'disabled-by-default-cc.debug.scheduler.now',
+ 'disabled-by-default-cpu_profiler',
+ 'disabled-by-default-cpu_profiler.debug',
+ 'disabled-by-default-devtools.screenshot',
+ 'disabled-by-default-devtools.timeline',
+ 'disabled-by-default-devtools.timeline.frame',
+ 'disabled-by-default-devtools.timeline.inputs',
+ 'disabled-by-default-devtools.timeline.invalidationTracking',
+ 'disabled-by-default-devtools.timeline.layers',
+ 'disabled-by-default-devtools.timeline.picture',
+ 'disabled-by-default-file',
+ 'disabled-by-default-fonts',
+ 'disabled-by-default-gpu_cmd_queue',
+ 'disabled-by-default-gpu.dawn',
+ 'disabled-by-default-gpu.debug',
+ 'disabled-by-default-gpu_decoder',
+ 'disabled-by-default-gpu.device',
+ 'disabled-by-default-gpu.service',
+ 'disabled-by-default-histogram_samples',
+ 'disabled-by-default-ipc.flow',
+ 'disabled-by-default-java-heap-profiler',
+ 'disabled-by-default-layer-element',
+ 'disabled-by-default-lifecycles',
+ 'disabled-by-default-loading',
+ 'disabled-by-default-memory-infra',
+ 'disabled-by-default-memory-infra.v8.code_stats',
+ 'disabled-by-default-net',
+ 'disabled-by-default-network',
+ 'disabled-by-default-paint-worklet',
+ 'disabled-by-default-power',
+ 'disabled-by-default-renderer.scheduler',
+ 'disabled-by-default-renderer.scheduler.debug',
+ 'disabled-by-default-sequence_manager',
+ 'disabled-by-default-sequence_manager.debug',
+ 'disabled-by-default-sequence_manager.verbose_snapshots',
+ 'disabled-by-default-skia',
+ 'disabled-by-default-skia.gpu',
+ 'disabled-by-default-skia.gpu.cache',
+ 'disabled-by-default-SyncFileSystem',
+ 'disabled-by-default-system_stats',
+ 'disabled-by-default-thread_pool_diagnostics',
+ 'disabled-by-default-toplevel.flow',
+ 'disabled-by-default-toplevel.ipc',
+ 'disabled-by-default-v8.compile',
+ 'disabled-by-default-v8.cpu_profiler',
+ 'disabled-by-default-v8.cpu_profiler.hires',
+ 'disabled-by-default-v8.gc',
+ 'disabled-by-default-v8.gc_stats',
+ 'disabled-by-default-v8.ic_stats',
+ 'disabled-by-default-v8.runtime',
+ 'disabled-by-default-v8.runtime_stats',
+ 'disabled-by-default-v8.runtime_stats_sampling',
+ 'disabled-by-default-v8.turbofan',
+ 'disabled-by-default-v8.wasm',
+ 'disabled-by-default-video_and_image_capture',
+ 'disabled-by-default-viz.debug.overlay_planes',
+ 'disabled-by-default-viz.hit_testing_flow',
+ 'disabled-by-default-viz.overdraw',
+ 'disabled-by-default-viz.quads',
+ 'disabled-by-default-viz.surface_id_flow',
+ 'disabled-by-default-viz.surface_lifetime',
+ 'disabled-by-default-viz.triangles',
+ 'disabled-by-default-worker.scheduler',
+ ];
+}
+
export function createEmptyState(): State {
return {
route: null,
diff --git a/ui/src/controller/adb.ts b/ui/src/controller/adb.ts
index 4888431..7b3c580 100644
--- a/ui/src/controller/adb.ts
+++ b/ui/src/controller/adb.ts
@@ -82,6 +82,9 @@
};
async findDevice() {
+ if (!('usb' in navigator)) {
+ throw new Error('WebUSB not supported by the browser (requires HTTPS)');
+ }
return navigator.usb.requestDevice({filters: [this.filter]});
}
diff --git a/ui/src/controller/adb_base_controller.ts b/ui/src/controller/adb_base_controller.ts
index 7f1afb1..31eb5ed 100644
--- a/ui/src/controller/adb_base_controller.ts
+++ b/ui/src/controller/adb_base_controller.ts
@@ -112,6 +112,7 @@
}
async findDevice(): Promise<USBDevice|undefined> {
+ if (!('usb' in navigator)) return undefined;
const connectedDevice = globals.state.recordingTarget;
if (!isAdbTarget(connectedDevice)) return undefined;
const devices = await navigator.usb.getDevices();
diff --git a/ui/src/controller/heap_profile_controller.ts b/ui/src/controller/heap_profile_controller.ts
index 973a92f..2f3b07d 100644
--- a/ui/src/controller/heap_profile_controller.ts
+++ b/ui/src/controller/heap_profile_controller.ts
@@ -85,7 +85,8 @@
selectedHeapProfile.viewingOption :
DEFAULT_VIEWING_OPTION,
selection.ts,
- selectedHeapProfile.upid)
+ selectedHeapProfile.upid,
+ selectedHeapProfile.type)
.then(flamegraphData => {
if (flamegraphData !== undefined && selection &&
selection.kind === selectedHeapProfile.kind &&
@@ -119,6 +120,7 @@
id: heapProfile.id,
upid: heapProfile.upid,
ts: heapProfile.ts,
+ type: heapProfile.type,
expandedCallsite: heapProfile.expandedCallsite,
viewingOption: heapProfile.viewingOption
};
@@ -130,6 +132,7 @@
(this.lastSelectedHeapProfile !== undefined &&
(this.lastSelectedHeapProfile.id !== selection.id ||
this.lastSelectedHeapProfile.ts !== selection.ts ||
+ this.lastSelectedHeapProfile.type !== selection.type ||
this.lastSelectedHeapProfile.upid !== selection.upid ||
this.lastSelectedHeapProfile.viewingOption !==
selection.viewingOption ||
@@ -151,8 +154,8 @@
async getFlamegraphData(
- baseKey: string, viewingOption: string, ts: number,
- upid: number): Promise<CallsiteInfo[]> {
+ baseKey: string, viewingOption: string, ts: number, upid: number,
+ type: string): Promise<CallsiteInfo[]> {
let currentData: CallsiteInfo[];
const key = `${baseKey}-${viewingOption}`;
if (this.flamegraphDatasets.has(key)) {
@@ -163,7 +166,7 @@
// Collecting data for drawing flamegraph for selected heap profile.
// Data needs to be in following format:
// id, name, parent_id, depth, total_size
- const tableName = await this.prepareViewsAndTables(ts, upid);
+ const tableName = await this.prepareViewsAndTables(ts, upid, type);
currentData =
await this.getFlamegraphDataFromTables(tableName, viewingOption);
this.flamegraphDatasets.set(key, currentData);
@@ -175,25 +178,32 @@
tableName: string, viewingOption = DEFAULT_VIEWING_OPTION) {
let orderBy = '';
let sizeIndex = 4;
+ // TODO(fmayer): Improve performance so this is no longer necessary.
+ // Alternatively consider collapsing frames of the same label.
+ const maxDepth = 100;
switch (viewingOption) {
case SPACE_MEMORY_ALLOCATED_NOT_FREED_KEY:
- orderBy = `where size > 0 order by depth, parent_hash, size desc, name`;
+ orderBy = `where cumulative_size > 0 and depth < ${
+ maxDepth} order by depth, parent_id,
+ cumulative_size desc, name`;
sizeIndex = 4;
break;
case ALLOC_SPACE_MEMORY_ALLOCATED_KEY:
- orderBy =
- `where alloc_size > 0 order by depth, parent_hash, alloc_size desc,
- name`;
+ orderBy = `where cumulative_alloc_size > 0 and depth < ${
+ maxDepth} order by depth, parent_id,
+ cumulative_alloc_size desc, name`;
sizeIndex = 5;
break;
case OBJECTS_ALLOCATED_NOT_FREED_KEY:
- orderBy =
- `where count > 0 order by depth, parent_hash, count desc, name`;
+ orderBy = `where cumulative_count > 0 and depth < ${
+ maxDepth} order by depth, parent_id,
+ cumulative_count desc, name`;
sizeIndex = 6;
break;
case OBJECTS_ALLOCATED_KEY:
- orderBy = `where alloc_count > 0 order by depth, parent_hash,
- alloc_count desc, name`;
+ orderBy = `where cumulative_alloc_count > 0 and depth < ${
+ maxDepth} order by depth, parent_id,
+ cumulative_alloc_count desc, name`;
sizeIndex = 7;
break;
default:
@@ -201,14 +211,15 @@
}
const callsites = await this.args.engine.query(
- `SELECT hash, name, parent_hash, depth, size, alloc_size, count,
- alloc_count, map_name, self_size from ${tableName} ${orderBy}`);
+ `SELECT id, IFNULL(DEMANGLE(name), name), IFNULL(parent_id, -1), depth,
+ cumulative_size, cumulative_alloc_size, cumulative_count,
+ cumulative_alloc_count, map_name, size from ${tableName} ${orderBy}`);
const flamegraphData: CallsiteInfo[] = new Array();
const hashToindex: Map<number, number> = new Map();
for (let i = 0; i < callsites.numRecords; i++) {
const hash = callsites.columns[0].longValues![i];
- const name = callsites.columns[1].stringValues![i];
+ let name = callsites.columns[1].stringValues![i];
const parentHash = callsites.columns[2].longValues![i];
const depth = +callsites.columns[3].longValues![i];
const totalSize = +callsites.columns[sizeIndex].longValues![i];
@@ -216,6 +227,9 @@
const selfSize = +callsites.columns[9].longValues![i];
const parentId =
hashToindex.has(+parentHash) ? hashToindex.get(+parentHash)! : -1;
+ if (depth === maxDepth - 1) {
+ name += ' [tree truncated]';
+ }
hashToindex.set(+hash, i);
// Instead of hash, we will store index of callsite in this original array
// as an id of callsite. That way, we have quicker access to parent and it
@@ -226,106 +240,19 @@
return flamegraphData;
}
- private async prepareViewsAndTables(ts: number, upid: number):
+ private async prepareViewsAndTables(ts: number, upid: number, type: string):
Promise<string> {
// Creating unique names for views so we can reuse and not delete them
// for each marker.
- const tableNameCallsiteNameSize =
- this.tableName(`callsite_with_name_and_size`);
- const tableNameCallsiteHashNameSize =
- this.tableName(`callsite_hash_name_size`);
const tableNameGroupedCallsitesForFlamegraph =
this.tableName(`grouped_callsites_for_flamegraph`);
- // Joining the callsite table with frame table then with alloc table to get
- // the size and name for each callsite.
- // TODO(taylori): Make frame name nullable in the trace processor for
- // consistency with the other columns.
- await this.args.engine.query(
- `create view if not exists ${tableNameCallsiteNameSize} as
- select id, parent_id, depth, IFNULL(DEMANGLE(name), name) as name,
- map_name, size, alloc_size, count, alloc_count from (
- select cs.id as id, parent_id, depth,
- coalesce(symbols.name,
- case when fr.name != '' then fr.name else map.name end) as name,
- map.name as map_name,
- SUM(IFNULL(size, 0)) as size,
- SUM(IFNULL(size, 0)) as size,
- SUM(case when size > 0 then size else 0 end) as alloc_size,
- SUM(IFNULL(count, 0)) as count,
- SUM(case when count > 0 then count else 0 end) as alloc_count
- from stack_profile_callsite cs
- join stack_profile_frame fr on cs.frame_id = fr.id
- join stack_profile_mapping map on fr.mapping = map.id
- left join (
- select symbol_set_id, FIRST_VALUE(name) OVER(PARTITION BY
- symbol_set_id) as name
- from stack_profile_symbol GROUP BY symbol_set_id
- ) as symbols using(symbol_set_id)
- left join heap_profile_allocation alloc on alloc.callsite_id = cs.id
- and alloc.ts <= ${ts} and alloc.upid = ${upid} group by cs.id)`);
- // Recursive query to compute the hash for each callsite based on names
- // rather than ids.
- // We get all the children of the row in question and emit a row with hash
- // equal hash(name, parent.hash). Roots without the parent will have -1 as
- // hash. Slices will be merged into a big slice.
- await this.args.engine.query(
- `create view if not exists ${tableNameCallsiteHashNameSize} as
- with recursive callsite_table_names(
- id, hash, name, map_name, size, alloc_size, count, alloc_count,
- parent_hash, depth) AS (
- select id, hash(name) as hash, name, map_name, size, alloc_size, count,
- alloc_count, -1, depth
- from ${tableNameCallsiteNameSize}
- where depth = 0
- union all
- select cs.id, hash(cs.name, ctn.hash) as hash, cs.name, cs.map_name,
- cs.size, cs.alloc_size, cs.count, cs.alloc_count, ctn.hash, cs.depth
- from callsite_table_names ctn
- inner join ${tableNameCallsiteNameSize} cs ON ctn.id = cs.parent_id
- )
- select hash, name, map_name, parent_hash, depth, SUM(size) as size,
- SUM(case when alloc_size > 0 then alloc_size else 0 end)
- as alloc_size, SUM(count) as count,
- SUM(case when alloc_count > 0 then alloc_count else 0 end)
- as alloc_count
- from callsite_table_names
- group by hash`);
-
- // Recursive query to compute the cumulative size of each callsite.
- // Base case: We get all the callsites where the size is non-zero.
- // Recursive case: We get the callsite which is the parent of the current
- // callsite(in terms of hashes) and emit a row with the size of the current
- // callsite plus all the info of the parent.
- // Grouping: For each callsite, our recursive table has n rows where n is
- // the number of descendents with a non-zero self size. We need to group on
- // the hash and sum all the sizes to get the cumulative size for each
- // callsite hash.
await this.args.engine.query(`create temp table if not exists ${
- tableNameGroupedCallsitesForFlamegraph}
- as with recursive callsite_children(
- hash, name, map_name, parent_hash, depth, size, alloc_size, count,
- alloc_count, self_size, self_alloc_size, self_count, self_alloc_count)
- as (
- select hash, name, map_name, parent_hash, depth, size, alloc_size,
- count, alloc_count, size as self_size, alloc_size as self_alloc_size,
- count as self_count, alloc_count as self_alloc_count
- from ${tableNameCallsiteHashNameSize}
- union all
- select chns.hash, chns.name, chns.map_name, chns.parent_hash,
- chns.depth, cc.size, cc.alloc_size, cc.count, cc.alloc_count,
- chns.size, chns.alloc_size, chns.count, chns.alloc_count
- from ${tableNameCallsiteHashNameSize} chns
- inner join callsite_children cc on chns.hash = cc.parent_hash
- )
- select hash, name, map_name, parent_hash, depth, SUM(size) as size,
- SUM(case when alloc_size > 0 then alloc_size else 0 end)
- as alloc_size, SUM(count) as count,
- SUM(case when alloc_count > 0 then alloc_count else 0 end) as
- alloc_count,
- self_size, self_alloc_size, self_count, self_alloc_count
- from callsite_children
- group by hash`);
+ tableNameGroupedCallsitesForFlamegraph} as
+ select id, name, map_name, parent_id, depth, cumulative_size,
+ cumulative_alloc_size, cumulative_count, cumulative_alloc_count,
+ size, alloc_size, count, alloc_count
+ from experimental_flamegraph(${ts}, ${upid}, '${type}')`);
return tableNameGroupedCallsitesForFlamegraph;
}
diff --git a/ui/src/controller/trace_controller.ts b/ui/src/controller/trace_controller.ts
index 88e2190..76acaa9 100644
--- a/ui/src/controller/trace_controller.ts
+++ b/ui/src/controller/trace_controller.ts
@@ -374,10 +374,14 @@
const upidToProcessTracks = new Map();
const rawProcessTracks = await engine.query(`
- select id, upid, process_track.name, max(depth) as maxDepth
+ select
+ process_track.id as track_id,
+ process_track.upid,
+ process_track.name,
+ max(slice.depth) as max_depth
from process_track
- inner join slice on slice.track_id = process_track.id
- group by track_id
+ join slice on slice.track_id = process_track.id
+ group by process_track.id
`);
for (let i = 0; i < rawProcessTracks.numRecords; i++) {
const trackId = rawProcessTracks.columns[0].longValues![i];
@@ -403,7 +407,9 @@
}
const heapProfiles = await engine.query(`
- select distinct(upid) from heap_profile_allocation`);
+ select distinct(upid) from heap_profile_allocation
+ union
+ select distinct(upid) from heap_graph_object`);
const heapUpids: Set<number> = new Set();
for (let i = 0; i < heapProfiles.numRecords; i++) {
@@ -467,6 +473,32 @@
});
}
+ // Add global slice tracks.
+ const globalSliceTracks = await engine.query(`
+ select
+ track.name as track_name,
+ track.id as track_id,
+ max(depth) as max_depth
+ from track
+ join slice on track.id = slice.track_id
+ where track.type = 'track'
+ group by track_id
+ `);
+
+ for (let i = 0; i < globalSliceTracks.numRecords; i++) {
+ const name = globalSliceTracks.columns[0].stringValues![i];
+ const trackId = +globalSliceTracks.columns[1].longValues![i];
+ const maxDepth = +globalSliceTracks.columns[2].longValues![i];
+
+ tracksToAdd.push({
+ engineId: this.engineId,
+ kind: SLICE_TRACK_KIND,
+ name: `${name}`,
+ trackGroup: SCROLLING_TRACK_GROUP,
+ config: {maxDepth, trackId},
+ });
+ }
+
interface CounterTrack {
name: string;
trackId: number;
@@ -687,8 +719,6 @@
name: `${threadName} [${tid}]`,
trackGroup: pUuid,
config: {
- upid,
- utid,
maxDepth: threadTrack.maxDepth,
trackId: threadTrack.trackId
},
@@ -839,9 +869,9 @@
select first_thread.ts as ts,
coalesce(min(runnable.ts), (select end_ts from trace_bounds)) -
first_thread.ts as dur,
- runnable.utid as utid
- from runnable
- JOIN first_thread using(utid) group by utid`);
+ first_thread.utid as utid
+ from first_thread
+ LEFT JOIN runnable using(utid) group by utid`);
await engine.query(`create view full_runnable as
select * from runnable UNION
diff --git a/ui/src/frontend/colorizer.ts b/ui/src/frontend/colorizer.ts
index 5fa6681..f4c5780 100644
--- a/ui/src/frontend/colorizer.ts
+++ b/ui/src/frontend/colorizer.ts
@@ -63,21 +63,40 @@
return (128 + (32 * cpu)) % 256;
}
-export function colorForState(state: string): Color {
+const DARK_GREEN: Color = {
+ c: 'dark green',
+ h: 120,
+ s: 44,
+ l: 34
+};
+const LIME_GREEN: Color = {
+ c: 'lime green',
+ h: 75,
+ s: 55,
+ l: 47
+};
+const LIGHT_GREY: Color = {
+ c: 'light grey',
+ h: 0,
+ s: 0,
+ l: 87
+};
+
+export function colorForState(state: string): Readonly<Color> {
switch (state) {
case 'Running':
case 'Busy':
- return {c: 'dark green', h: 120, s: 44, l: 34};
+ return DARK_GREEN;
case 'Runnable':
case 'R':
case 'R+':
- return {c: 'lime green', h: 75, s: 55, l: 47};
+ return LIME_GREEN;
default:
- return {c: 'light grey', h: 0, s: 0, l: 87};
+ return LIGHT_GREY;
}
}
-export function colorForTid(tid: number) {
+export function colorForTid(tid: number): Color {
const colorIdx = hash(tid.toString(), MD_PALETTE.length);
return Object.assign({}, MD_PALETTE[colorIdx]);
}
diff --git a/ui/src/frontend/flamegraph.ts b/ui/src/frontend/flamegraph.ts
index 4c4d3e4..e74befe 100644
--- a/ui/src/frontend/flamegraph.ts
+++ b/ui/src/frontend/flamegraph.ts
@@ -259,11 +259,13 @@
let selfSizeWidth = 0;
if (this.hoveredCallsite.selfSize > 0) {
+ const selfPercentage =
+ this.hoveredCallsite.selfSize / this.totalSize * 100;
const selfSizeText = `self: ${
this.displaySize(
this.hoveredCallsite.selfSize,
unit,
- unit === 'B' ? 1024 : 1000)} (${percentage.toFixed(2)}%)`;
+ unit === 'B' ? 1024 : 1000)} (${selfPercentage.toFixed(2)}%)`;
lineSplitter = splitIfTooBig(
selfSizeText, width, ctx.measureText(selfSizeText).width);
selfSizeWidth = lineSplitter.lineWidth;
@@ -305,15 +307,18 @@
if (unit === '') return totalSize.toLocaleString();
if (totalSize === 0) return `0 ${unit}`;
const units = [
- ['', 0],
+ ['', 1],
['K', step],
['M', Math.pow(step, 2)],
['G', Math.pow(step, 3)]
];
let unitsIndex = Math.trunc(Math.log(totalSize) / Math.log(step));
unitsIndex = unitsIndex > units.length - 1 ? units.length - 1 : unitsIndex;
- return `${(totalSize / +units[unitsIndex][1]).toLocaleString()} ${
- units[unitsIndex][0]}${unit}`;
+ const result = totalSize / +units[unitsIndex][1];
+ const resultString = totalSize % +units[unitsIndex][1] === 0 ?
+ result.toString() :
+ result.toFixed(2);
+ return `${resultString} ${units[unitsIndex][0]}${unit}`;
}
onMouseMove({x, y}: {x: number, y: number}) {
diff --git a/ui/src/frontend/frontend_local_state.ts b/ui/src/frontend/frontend_local_state.ts
index b38fe94..97acfd3 100644
--- a/ui/src/frontend/frontend_local_state.ts
+++ b/ui/src/frontend/frontend_local_state.ts
@@ -99,6 +99,7 @@
showNotePreview = false;
localOnlyMode = false;
sidebarVisible = true;
+ showPanningHint = false;
// This is used to calculate the tracks within a Y range for area selection.
areaY: Range = {};
visibleTracks = new Set<string>();
@@ -107,6 +108,7 @@
currentTab?: Tab;
scrollToTrackId?: string|number;
httpRpcState: HttpRpcState = {connected: false};
+ newVersionAvailable = false;
private scrollBarWidth?: number;
private _omniboxState: OmniboxState = {
@@ -224,6 +226,7 @@
selectArea(
startSec: number, endSec: number,
tracks = this._selectedArea.area ? this._selectedArea.area.tracks : []) {
+ this.showPanningHint = true;
this._selectedArea = {
area: {startSec, endSec, tracks},
lastUpdate: Date.now() / 1000
diff --git a/ui/src/frontend/globals.ts b/ui/src/frontend/globals.ts
index 0fb518d..7c384ba 100644
--- a/ui/src/frontend/globals.ts
+++ b/ui/src/frontend/globals.ts
@@ -20,6 +20,7 @@
import {FrontendLocalState} from './frontend_local_state';
import {RafScheduler} from './raf_scheduler';
+import {ServiceWorkerController} from './service_worker_controller';
type Dispatch = (action: DeferredAction) => void;
type TrackDataStore = Map<string, {}>;
@@ -85,6 +86,7 @@
private _state?: State = undefined;
private _frontendLocalState?: FrontendLocalState = undefined;
private _rafScheduler?: RafScheduler = undefined;
+ private _serviceWorkerController?: ServiceWorkerController = undefined;
// TODO(hjd): Unify trackDataStore, queryResults, overviewStore, threads.
private _trackDataStore?: TrackDataStore = undefined;
@@ -126,6 +128,7 @@
this._state = createEmptyState();
this._frontendLocalState = new FrontendLocalState();
this._rafScheduler = new RafScheduler();
+ this._serviceWorkerController = new ServiceWorkerController();
// TODO(hjd): Unify trackDataStore, queryResults, overviewStore, threads.
this._trackDataStore = new Map<string, {}>();
@@ -157,6 +160,10 @@
return assertExists(this._rafScheduler);
}
+ get serviceWorkerController() {
+ return assertExists(this._serviceWorkerController);
+ }
+
// TODO(hjd): Unify trackDataStore, queryResults, overviewStore, threads.
get overviewStore(): OverviewStore {
return assertExists(this._overviewStore);
@@ -262,6 +269,7 @@
this._state = undefined;
this._frontendLocalState = undefined;
this._rafScheduler = undefined;
+ this._serviceWorkerController = undefined;
// TODO(hjd): Unify trackDataStore, queryResults, overviewStore, threads.
this._trackDataStore = undefined;
diff --git a/ui/src/frontend/help_modal.ts b/ui/src/frontend/help_modal.ts
index 39ff0e4..1227d47 100644
--- a/ui/src/frontend/help_modal.ts
+++ b/ui/src/frontend/help_modal.ts
@@ -35,41 +35,39 @@
helpModelOpen = true;
showModal({
title: 'Perfetto Help',
- content:
- m('.help',
- m('h2', 'Navigation'),
- m(
- 'table',
- m(
- 'tr',
- m('td', keycap('w'), '/', keycap('s')),
- m('td', 'Zoom in/out'),
- ),
- m(
- 'tr',
- m('td', keycap('a'), '/', keycap('d')),
- m('td', 'Pan left/right'),
- ),
- ),
- m('h2', 'Mouse Controls'),
- m('table',
- m('tr', m('td', 'Click'), m('td', 'Select event')),
- m('tr', m('td', 'Ctrl + Scroll wheel'), m('td', 'Zoom in/out')),
- m('tr', m('td', 'Click + Drag'), m('td', 'Pan left/right')),
+ content: m(
+ '.help',
+ m('h2', 'Navigation'),
+ m(
+ 'table',
+ m(
+ 'tr',
+ m('td', keycap('w'), '/', keycap('s')),
+ m('td', 'Zoom in/out'),
+ ),
+ m(
+ 'tr',
+ m('td', keycap('a'), '/', keycap('d')),
+ m('td', 'Pan left/right'),
+ ),
+ ),
+ m('h2', 'Mouse Controls'),
+ m('table',
+ m('tr', m('td', 'Click'), m('td', 'Select event')),
+ m('tr', m('td', 'Ctrl + Scroll wheel'), m('td', 'Zoom in/out')),
+ m('tr', m('td', 'Click + Drag'), m('td', 'Select area')),
+ m('tr', m('td', 'Shift + Click + Drag'), m('td', 'Pan left/right'))),
+ m('h2', 'Other'),
+ m(
+ 'table',
m('tr',
- m('td', 'Shift + Click + Drag'),
- m('td', 'Select a time span'))),
- m('h2', 'Other'),
- m(
- 'table',
- m('tr',
- m('td', keycap('f'), ' (with event selected)'),
- m('td', 'Scroll + zoom to current selection')),
- m('tr',
- m('td', keycap('m'), ' (with event selected)'),
- m('td', 'Select time span of event')),
- m('tr', m('td', keycap('?')), m('td', 'Show help')),
- )),
+ m('td', keycap('f'), ' (with event selected)'),
+ m('td', 'Scroll + zoom to current selection')),
+ m('tr',
+ m('td', keycap('m'), ' (with event selected)'),
+ m('td', 'Select time span of event')),
+ m('tr', m('td', keycap('?')), m('td', 'Show help')),
+ )),
buttons: [],
}).finally(() => {
helpModelOpen = false;
diff --git a/ui/src/frontend/index.ts b/ui/src/frontend/index.ts
index c9f75bc..e1d5c64 100644
--- a/ui/src/frontend/index.ts
+++ b/ui/src/frontend/index.ts
@@ -78,7 +78,7 @@
// want to keep in the global state. Figure out a more generic and type-safe
// mechanism to achieve this.
- publishOverviewData(data: {[key: string]: QuantizedLoad | QuantizedLoad[]}) {
+ publishOverviewData(data: {[key: string]: QuantizedLoad|QuantizedLoad[]}) {
for (const [key, value] of Object.entries(data)) {
if (!globals.overviewStore.has(key)) {
globals.overviewStore.set(key, []);
@@ -251,6 +251,7 @@
dispatch);
forwardRemoteCalls(frontendChannel.port2, new FrontendApi(router));
globals.initialize(dispatch, controller);
+ globals.serviceWorkerController.install();
// We proxy messages between the extension and the controller because the
// controller's worker can't access chrome.runtime.
diff --git a/ui/src/frontend/keyboard_event_handler.ts b/ui/src/frontend/keyboard_event_handler.ts
index 3132234..642722e 100644
--- a/ui/src/frontend/keyboard_event_handler.ts
+++ b/ui/src/frontend/keyboard_event_handler.ts
@@ -46,6 +46,9 @@
globals.frontendLocalState.setVidTimestamp(Number.MIN_SAFE_INTEGER);
}
}
+ if (down && 'b' === key && (e.ctrlKey || e.metaKey)) {
+ globals.frontendLocalState.toggleSidebar();
+ }
if (down && '?' === key) {
toggleHelp();
}
diff --git a/ui/src/frontend/legacy_trace_viewer.ts b/ui/src/frontend/legacy_trace_viewer.ts
index c55451d..253d6af 100644
--- a/ui/src/frontend/legacy_trace_viewer.ts
+++ b/ui/src/frontend/legacy_trace_viewer.ts
@@ -18,12 +18,48 @@
import {globals} from './globals';
-export function isLegacyTrace(fileName: string): boolean {
- fileName = fileName.toLowerCase();
- return (
- fileName.endsWith('.json') || fileName.endsWith('.json.gz') ||
+function readText(blob: Blob): Promise<string> {
+ return new Promise((resolve, reject) => {
+ const reader = new FileReader();
+ reader.onload = () => {
+ if (typeof reader.result === 'string') {
+ return resolve(reader.result);
+ }
+ };
+ reader.onerror = err => {
+ reject(err);
+ };
+ reader.readAsText(blob);
+ });
+}
+
+export async function isLegacyTrace(file: File): Promise<boolean> {
+ const fileName = file.name.toLowerCase();
+ if (fileName.endsWith('.json') || fileName.endsWith('.json.gz') ||
fileName.endsWith('.zip') || fileName.endsWith('.ctrace') ||
- fileName.endsWith('.html'));
+ fileName.endsWith('.html')) {
+ return true;
+ }
+
+ // Sometimes systrace formatted traces end with '.trace'. This is a
+ // little generic to assume all such traces are systrace format though
+ // so we read the beginning of the file and check to see if is has the
+ // systrace header (several comment lines):
+ if (fileName.endsWith('.trace')) {
+ const header = await readText(file.slice(0, 512));
+ const lines = header.split('\n');
+ let commentCount = 0;
+ for (const line of lines) {
+ if (line.startsWith('#')) {
+ commentCount++;
+ }
+ }
+ if (commentCount > 5) {
+ return true;
+ }
+ }
+
+ return false;
}
export function openFileWithLegacyTraceViewer(file: File) {
diff --git a/ui/src/frontend/pan_and_zoom_handler.ts b/ui/src/frontend/pan_and_zoom_handler.ts
index 9d2bda1..1f504b4 100644
--- a/ui/src/frontend/pan_and_zoom_handler.ts
+++ b/ui/src/frontend/pan_and_zoom_handler.ts
@@ -44,8 +44,8 @@
const WHEEL_ZOOM_SPEED = -0.02;
const EDITING_RANGE_CURSOR = 'ew-resize';
-const SHIFT_CURSOR = 'text';
-const DEFAULT_CURSOR = 'default';
+const DRAG_CURSOR = 'text';
+const PAN_CURSOR = 'move';
enum Pan {
None = 0,
@@ -94,28 +94,29 @@
private contentOffsetX: number;
private onPanned: (movedPx: number) => void;
private onZoomed: (zoomPositionPx: number, zoomRatio: number) => void;
- private shouldDrag: (currentPx: number) => boolean;
- private onDrag:
+ private editSelection: (currentPx: number) => boolean;
+ private onSelection:
(dragStartX: number, dragStartY: number, prevX: number, currentX: number,
currentY: number, editing: boolean) => void;
constructor(
- {element, contentOffsetX, onPanned, onZoomed, shouldDrag, onDrag}: {
- element: HTMLElement,
- contentOffsetX: number,
- onPanned: (movedPx: number) => void,
- onZoomed: (zoomPositionPx: number, zoomRatio: number) => void,
- shouldDrag: (currentPx: number) => boolean,
- onDrag:
- (dragStartX: number, dragStartY: number, prevX: number,
- currentX: number, currentY: number, editing: boolean) => void,
- }) {
+ {element, contentOffsetX, onPanned, onZoomed, editSelection, onSelection}:
+ {
+ element: HTMLElement,
+ contentOffsetX: number,
+ onPanned: (movedPx: number) => void,
+ onZoomed: (zoomPositionPx: number, zoomRatio: number) => void,
+ editSelection: (currentPx: number) => boolean,
+ onSelection:
+ (dragStartX: number, dragStartY: number, prevX: number,
+ currentX: number, currentY: number, editing: boolean) => void,
+ }) {
this.element = element;
this.contentOffsetX = contentOffsetX;
this.onPanned = onPanned;
this.onZoomed = onZoomed;
- this.shouldDrag = shouldDrag;
- this.onDrag = onDrag;
+ this.editSelection = editSelection;
+ this.onSelection = onSelection;
document.body.addEventListener('keydown', this.boundOnKeyDown);
document.body.addEventListener('keyup', this.boundOnKeyUp);
@@ -125,16 +126,14 @@
let prevX = -1;
let dragStartX = -1;
let dragStartY = -1;
- let drag = false;
+ let edit = false;
new DragGestureHandler(
this.element,
(x, y) => {
- // If we started our drag on a time range boundary or shift is down
- // then we are drag selecting rather than panning.
- if (drag || this.shiftDown) {
- this.onDrag(dragStartX, dragStartY, prevX, x, y, !this.shiftDown);
- } else {
+ if (this.shiftDown) {
this.onPanned(prevX - x);
+ } else {
+ this.onSelection(dragStartX, dragStartY, prevX, x, y, edit);
}
prevX = x;
},
@@ -142,19 +141,18 @@
prevX = x;
dragStartX = x;
dragStartY = y;
- drag = this.shouldDrag(x);
+ edit = this.editSelection(x);
// Set the cursor style based on where the cursor is when the drag
// starts.
- if (drag) {
+ if (edit) {
this.element.style.cursor = EDITING_RANGE_CURSOR;
- } else if (this.shiftDown) {
- this.element.style.cursor = SHIFT_CURSOR;
+ } else if (!this.shiftDown) {
+ this.element.style.cursor = DRAG_CURSOR;
}
},
() => {
// Reset the cursor now the drag has ended.
- this.element.style.cursor =
- this.shiftDown ? SHIFT_CURSOR : DEFAULT_CURSOR;
+ this.element.style.cursor = this.shiftDown ? PAN_CURSOR : DRAG_CURSOR;
dragStartX = -1;
dragStartY = -1;
});
@@ -213,14 +211,13 @@
// the cursor flickering between styles if you drag fast and get too
// far from the current time range.
if (e.buttons === 0) {
- if (!this.shouldDrag(this.mousePositionX)) {
- this.element.style.cursor =
- this.shiftDown ? SHIFT_CURSOR : DEFAULT_CURSOR;
- } else {
+ if (this.editSelection(this.mousePositionX)) {
this.element.style.cursor = EDITING_RANGE_CURSOR;
+ } else {
+ this.element.style.cursor = this.shiftDown ? PAN_CURSOR : DRAG_CURSOR;
}
}
- if (this.shiftDown) {
+ if (!this.shiftDown) {
const pos = this.mousePositionX - TRACK_SHELL_WIDTH;
const ts = globals.frontendLocalState.timeScale.pxToTime(pos);
globals.frontendLocalState.setHoveredTimestamp(ts);
@@ -283,17 +280,15 @@
if (down === this.shiftDown) return;
this.shiftDown = down;
if (this.shiftDown) {
+ globals.frontendLocalState.setHoveredTimestamp(-1);
+ this.element.style.cursor = PAN_CURSOR;
+ } else {
if (this.mousePositionX) {
- this.element.style.cursor = SHIFT_CURSOR;
+ this.element.style.cursor = DRAG_CURSOR;
const pos = this.mousePositionX - TRACK_SHELL_WIDTH;
const ts = globals.frontendLocalState.timeScale.pxToTime(pos);
globals.frontendLocalState.setHoveredTimestamp(ts);
}
- } else {
- globals.frontendLocalState.setHoveredTimestamp(-1);
- this.element.style.cursor = DEFAULT_CURSOR;
}
-
- globals.frontendLocalState.setShowTimeSelectPreview(this.shiftDown);
}
}
diff --git a/ui/src/frontend/panel_container.ts b/ui/src/frontend/panel_container.ts
index 9d2eaa5..8698422 100644
--- a/ui/src/frontend/panel_container.ts
+++ b/ui/src/frontend/panel_container.ts
@@ -234,13 +234,18 @@
const ctx = assertExists(this.ctx);
const canvas = assertExists(ctx.canvas);
canvas.style.height = `${this.canvasHeight}px`;
+
+ // If're we're non-scrolling canvas and the scroll-limiter should always
+ // have the same height. Enforce this by explicitly setting the height.
+ if (!this.attrs.doesScroll) {
+ const scrollLimiter = canvas.parentElement;
+ if (scrollLimiter) {
+ scrollLimiter.style.height = `${this.canvasHeight}px`;
+ }
+ }
+
const dpr = window.devicePixelRatio;
- // On non-MacOS if there is a solid scroll bar it can cover important
- // pixels, reduce the size of the canvas so it doesn't overlap with
- // the scroll bar.
- ctx.canvas.width =
- (this.parentWidth - globals.frontendLocalState.getScrollbarWidth()) *
- dpr;
+ ctx.canvas.width = this.parentWidth * dpr;
ctx.canvas.height = this.canvasHeight * dpr;
ctx.scale(dpr, dpr);
}
@@ -260,7 +265,11 @@
const oldWidth = this.parentWidth;
const oldHeight = this.parentHeight;
const clientRect = assertExists(dom.parentElement).getBoundingClientRect();
- this.parentWidth = clientRect.width;
+ // On non-MacOS if there is a solid scroll bar it can cover important
+ // pixels, reduce the size of the canvas so it doesn't overlap with
+ // the scroll bar.
+ this.parentWidth =
+ clientRect.width - globals.frontendLocalState.getScrollbarWidth();
this.parentHeight = clientRect.height;
return this.parentHeight !== oldHeight || this.parentWidth !== oldWidth;
}
diff --git a/ui/src/frontend/record_page.ts b/ui/src/frontend/record_page.ts
index 135c874..a1d1b54 100644
--- a/ui/src/frontend/record_page.ts
+++ b/ui/src/frontend/record_page.ts
@@ -20,11 +20,11 @@
import {MeminfoCounters, VmstatCounters} from '../common/protos';
import {
AdbRecordingTarget,
+ getBuiltinChromeCategoryList,
getDefaultRecordingTargets,
isAdbTarget,
isAndroidTarget,
isChromeTarget,
- isLinuxTarget,
RecordingTarget
} from '../common/state';
import {MAX_TIME, RecordMode} from '../common/state';
@@ -592,11 +592,13 @@
}
function ChromeCategoriesSelection() {
- // The categories are displayed only if the extension is installed, because
- // they come from the chrome.debugging API, not available from normal web
- // pages.
- const categories = globals.state.chromeCategories;
- if (!categories) return [];
+ // If we are attempting to record via the Chrome extension, we receive the
+ // list of actually supported categories via DevTools. Otherwise, we fall back
+ // to an integrated list of categories from a recent version of Chrome.
+ let categories = globals.state.chromeCategories;
+ if (!categories || !isChromeTarget(globals.state.recordingTarget)) {
+ categories = getBuiltinChromeCategoryList();
+ }
// Show "disabled-by-default" categories last.
const categoriesMap = new Map<string, string>();
@@ -613,9 +615,10 @@
categoriesMap.set(
cat, `${cat.replace(disabledPrefix, '')} (high overhead)`);
});
+
return m(Dropdown, {
title: 'Additional Chrome categories',
- cssClass: '.multicolumn.two-columns.chrome-categories',
+ cssClass: '.multicolumn.two-columns',
options: categoriesMap,
set: (cfg, val) => cfg.chromeCategoriesSelected = val,
get: (cfg) => cfg.chromeCategoriesSelected
@@ -743,7 +746,7 @@
),
m('.chip',
{onclick: addAndroidDevice},
- m('button', 'Add Device'),
+ m('button', 'Add ADB Device'),
m('i.material-icons', 'add')));
}
@@ -850,7 +853,7 @@
'Start Recording'.`)) :
[];
}
- return m(CodeSnippet, {text: getRecordCommand(target), hardWhitespace: true});
+ return m(CodeSnippet, {text: getRecordCommand(target)});
}
function getRecordCommand(target: RecordingTarget) {
@@ -895,29 +898,16 @@
onclick: onStartRecordingPressed
},
'Start Recording');
- const showCmd =
- m(`button`,
- {
- onclick: () => {
- location.href = '#!/record?p=instructions';
- globals.rafScheduler.scheduleFullRedraw();
- }
- },
- 'Show Command');
const buttons: m.Children = [];
if (isAndroidTarget(target)) {
- if (!recInProgress) {
- buttons.push(showCmd);
- if (isAdbTarget(target)) buttons.push(start);
+ if (!recInProgress && isAdbTarget(target)) {
+ buttons.push(start);
}
} else if (isChromeTarget(target) && state.extensionInstalled) {
buttons.push(start);
- } else if (isLinuxTarget(target)) {
- buttons.push(showCmd);
}
-
return m('.button', buttons);
}
@@ -973,7 +963,9 @@
try {
device = await new AdbOverWebUsb().findDevice();
} catch (e) {
- console.error(`No device found: ${e.name}: ${e.message}`);
+ const err = `No device found: ${e.name}: ${e.message}`;
+ console.error(err, e);
+ alert(err);
return;
}
diff --git a/ui/src/frontend/record_widgets.ts b/ui/src/frontend/record_widgets.ts
index 3d683f7..ebc2267 100644
--- a/ui/src/frontend/record_widgets.ts
+++ b/ui/src/frontend/record_widgets.ts
@@ -258,12 +258,7 @@
onclick: () => copyToClipboard(attrs.text),
},
m('i.material-icons', 'assignment')),
- m('code',
- {
- style: {
- 'white-space': attrs.hardWhitespace ? 'pre' : null,
- },
- },
- attrs.text), );
+ m('code', attrs.text),
+ );
}
}
diff --git a/ui/src/frontend/service_worker_controller.ts b/ui/src/frontend/service_worker_controller.ts
new file mode 100644
index 0000000..efffa21
--- /dev/null
+++ b/ui/src/frontend/service_worker_controller.ts
@@ -0,0 +1,120 @@
+// Copyright (C) 2020 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.
+
+// Handles registration, unregistration and lifecycle of the service worker.
+// This class contains only the controlling logic, all the code in here runs in
+// the main thread, not in the service worker thread.
+// The actual service worker code is in src/service_worker.
+// Design doc: http://go/perfetto-offline.
+
+import {reportError} from '../base/logging';
+import {globals} from './globals';
+
+// We use a dedicated |caches| object to share a global boolean beween the main
+// thread and the SW. SW cannot use local-storage or anything else other than
+// IndexedDB (which would be overkill).
+const BYPASS_ID = 'BYPASS_SERVICE_WORKER';
+
+export class ServiceWorkerController {
+ private _initialWorker: ServiceWorker|null = null;
+ private _bypassed = false;
+ private _installing = false;
+
+ // Caller should reload().
+ async setBypass(bypass: boolean) {
+ if (!('serviceWorker' in navigator)) return; // Not supported.
+ this._bypassed = bypass;
+ if (bypass) {
+ await caches.open(BYPASS_ID); // Create the entry.
+ for (const reg of await navigator.serviceWorker.getRegistrations()) {
+ await reg.unregister();
+ }
+ } else {
+ await caches.delete(BYPASS_ID);
+ this.install();
+ }
+ globals.rafScheduler.scheduleFullRedraw();
+ }
+
+ onStateChange(sw: ServiceWorker) {
+ globals.rafScheduler.scheduleFullRedraw();
+ if (sw.state === 'installing') {
+ this._installing = true;
+ } else if (sw.state === 'activated') {
+ this._installing = false;
+ // Don't show the notification if the site was served straight
+ // from the network (e.g., on the very first visit or after
+ // Ctrl+Shift+R). In these cases, we are already at the last
+ // version.
+ if (sw !== this._initialWorker && this._initialWorker) {
+ globals.frontendLocalState.newVersionAvailable = true;
+ }
+ } else if (
+ sw.state === 'redundant' && sw !== this._initialWorker &&
+ !this._bypassed) {
+ // Note that upon updates, the initial SW will hit the 'redundant'
+ // state by design once the new one is activated. That's why the
+ // != _initialWorker above.
+
+ // In the other cases, the 'redundant' state signals a failure in the
+ // SW installation. This can happen, for instance, if the subresource
+ // integrity check fails. In that case there doesn't seem to be any easy
+ // way to get the failure output from the service worker.
+ reportError(
+ 'Service Worker installation failed.\n' +
+ 'Please attach the JavaScript console output to the bug.');
+ }
+ }
+
+ monitorWorker(sw: ServiceWorker|null) {
+ if (!sw) return;
+ sw.addEventListener('error', (e) => reportError(e));
+ sw.addEventListener('statechange', () => this.onStateChange(sw));
+ this.onStateChange(sw); // Trigger updates for the current state.
+ }
+
+ async install() {
+ if (!('serviceWorker' in navigator)) return; // Not supported.
+
+ if (await caches.has(BYPASS_ID)) {
+ this._bypassed = true;
+ console.log('Skipping service worker registration, disabled by the user');
+ return;
+ }
+ navigator.serviceWorker.register('service_worker.js').then(registration => {
+ this._initialWorker = registration.active;
+
+ // At this point there are two options:
+ // 1. This is the first time we visit the site (or cache was cleared) and
+ // no SW is installed yet. In this case |installing| will be set.
+ // 2. A SW is already installed (though it might be obsolete). In this
+ // case |active| will be set.
+ this.monitorWorker(registration.installing);
+ this.monitorWorker(registration.active);
+
+ // Setup the event that shows the "A new release is available"
+ // notification.
+ registration.addEventListener('updatefound', () => {
+ this.monitorWorker(registration.installing);
+ });
+ });
+ }
+
+ get bypassed() {
+ return this._bypassed;
+ }
+ get installing() {
+ return this._installing;
+ }
+}
\ No newline at end of file
diff --git a/ui/src/frontend/sidebar.ts b/ui/src/frontend/sidebar.ts
index 4e7c3aa..a295a75 100644
--- a/ui/src/frontend/sidebar.ts
+++ b/ui/src/frontend/sidebar.ts
@@ -311,12 +311,7 @@
globals.frontendLocalState.localOnlyMode = false;
if (e.target.dataset['useCatapultLegacyUi'] === '1') {
- // Switch back to the old catapult UI.
- if (isLegacyTrace(file.name)) {
- openFileWithLegacyTraceViewer(file);
- return;
- }
- openInOldUIWithSizeCheck(file);
+ openWithLegacyUi(file);
return;
}
@@ -343,7 +338,15 @@
}
globals.dispatch(Actions.openTraceFromFile({file}));
+}
+async function openWithLegacyUi(file: File) {
+ // Switch back to the old catapult UI.
+ if (await isLegacyTrace(file)) {
+ openFileWithLegacyTraceViewer(file);
+ return;
+ }
+ openInOldUIWithSizeCheck(file);
}
function openInOldUIWithSizeCheck(trace: Blob) {
@@ -464,7 +467,7 @@
}
-const SidebarFooter: m.Component = {
+const EngineRPCWidget: m.Component = {
view() {
let cssClass = '';
let title = 'Number of pending SQL queries';
@@ -478,7 +481,7 @@
for (const engine of engines) {
mode = engine.mode;
if (engine.failed !== undefined) {
- cssClass += '.failed';
+ cssClass += '.red';
title = 'Query engine crashed\n' + engine.failed;
failed = true;
}
@@ -499,7 +502,7 @@
}
if (mode === 'HTTP_RPC') {
- cssClass += '.rpc';
+ cssClass += '.green';
label = 'RPC';
title += '\n(Query engine: native accelerator over HTTP+RPC)';
} else {
@@ -508,6 +511,88 @@
}
return m(
+ `.dbg-info-square${cssClass}`,
+ {title},
+ m('div', label),
+ m('div', `${failed ? 'FAIL' : globals.numQueuedQueries}`));
+ }
+};
+
+const ServiceWorkerWidget: m.Component = {
+ view() {
+ let cssClass = '';
+ let title = 'Service Worker: ';
+ let label = 'N/A';
+ const ctl = globals.serviceWorkerController;
+ if ((!('serviceWorker' in navigator))) {
+ label = 'N/A';
+ title += 'not supported by the browser (requires HTTPS)';
+ } else if (ctl.bypassed) {
+ label = 'OFF';
+ cssClass = '.red';
+ title += 'Bypassed, using live network. Double-click to re-enable';
+ } else if (ctl.installing) {
+ label = 'UPD';
+ cssClass = '.amber';
+ title += 'Installing / updating ...';
+ } else if (!navigator.serviceWorker.controller) {
+ label = 'N/A';
+ title += 'Not available, using network';
+ } else {
+ label = 'ON';
+ cssClass = '.green';
+ title += 'Serving from cache. Ready for offline use';
+ }
+
+ const toggle = async () => {
+ if (globals.serviceWorkerController.bypassed) {
+ globals.serviceWorkerController.setBypass(false);
+ return;
+ }
+ showModal({
+ title: 'Disable service worker?',
+ content: m(
+ 'div',
+ m('p', `If you continue the service worker will be disabled until
+ manually re-enabled.`),
+ m('p', `All future requests will be served from the network and the
+ UI won't be available offline.`),
+ m('p', `You should do this only if you are debugging the UI
+ or if you are experiencing caching-related problems.`),
+ m('p', `Disabling will cause a refresh of the UI, the current state
+ will be lost.`),
+ ),
+ buttons: [
+ {
+ text: 'Disable and reload',
+ primary: true,
+ id: 'sw-bypass-enable',
+ action: () => {
+ globals.serviceWorkerController.setBypass(true).then(
+ () => location.reload());
+ }
+ },
+ {
+ text: 'Cancel',
+ primary: false,
+ id: 'sw-bypass-cancel',
+ action: () => {}
+ }
+ ]
+ });
+ };
+
+ return m(
+ `.dbg-info-square${cssClass}`,
+ {title, ondblclick: toggle},
+ m('div', 'SW'),
+ m('div', label));
+ }
+};
+
+const SidebarFooter: m.Component = {
+ view() {
+ return m(
'.sidebar-footer',
m('button',
{
@@ -516,10 +601,8 @@
m('i.material-icons',
{title: 'Toggle Perf Debug Mode'},
'assessment')),
- m(`.num-queued-queries${cssClass}`,
- {title},
- m('div', label),
- m('div', `${failed ? 'FAIL' : globals.numQueuedQueries}`)),
+ m(EngineRPCWidget),
+ m(ServiceWorkerWidget),
);
}
};
diff --git a/ui/src/frontend/topbar.ts b/ui/src/frontend/topbar.ts
index 2163ace..a7bd25f 100644
--- a/ui/src/frontend/topbar.ts
+++ b/ui/src/frontend/topbar.ts
@@ -32,6 +32,8 @@
[COMMAND]: 'e.g. select * from sched left join thread using(utid) limit 10'
};
+export const DISMISSED_PANNING_HINT_KEY = 'dismissedPanningHint';
+
let selResult = 0;
let numResults = 0;
let mode: Mode = SEARCH;
@@ -229,8 +231,65 @@
}
}
+
+class NewVersionNotification implements m.ClassComponent {
+ view() {
+ if (!globals.frontendLocalState.newVersionAvailable) return;
+ return m(
+ '.new-version-toast',
+ 'A new version of the UI is available!',
+ m('button.notification-btn.preferred',
+ {
+ onclick: () => {
+ location.reload();
+ }
+ },
+ 'Reload'),
+ m('button.notification-btn',
+ {
+ onclick: () => {
+ globals.frontendLocalState.newVersionAvailable = false;
+ globals.rafScheduler.scheduleFullRedraw();
+ }
+ },
+ 'Dismiss'),
+ );
+ }
+}
+
+
+class HelpPanningNotification implements m.ClassComponent {
+ view() {
+ const dismissed = localStorage.getItem(DISMISSED_PANNING_HINT_KEY);
+ if (dismissed === 'true' || !globals.frontendLocalState.showPanningHint) {
+ return;
+ }
+ return m(
+ '.helpful-hint',
+ m('.hint-text',
+ 'Are you trying to pan? Use the WASD keys or hold shift to click ' +
+ 'and drag. Press \'?\' for more help.'),
+ m('button.hint-dismiss-button',
+ {
+ onclick: () => {
+ globals.frontendLocalState.showPanningHint = false;
+ localStorage.setItem(DISMISSED_PANNING_HINT_KEY, 'true');
+ globals.rafScheduler.scheduleFullRedraw();
+ }
+ },
+ 'Dismiss'),
+ );
+ }
+}
+
export class Topbar implements m.ClassComponent {
view() {
- return m('.topbar', m(Omnibox), m(Progress));
+ return m(
+ '.topbar',
+ globals.frontendLocalState.newVersionAvailable ?
+ m(NewVersionNotification) :
+ m(Omnibox),
+ m(Progress),
+ m(HelpPanningNotification));
}
}
diff --git a/ui/src/frontend/track_panel.ts b/ui/src/frontend/track_panel.ts
index b8c778d..098bd81 100644
--- a/ui/src/frontend/track_panel.ts
+++ b/ui/src/frontend/track_panel.ts
@@ -198,7 +198,7 @@
'.track',
{
style: {
- height: `${attrs.track.getHeight()}px`,
+ height: `${Math.max(24, attrs.track.getHeight())}px`,
},
id: 'track_' + attrs.trackState.id,
},
diff --git a/ui/src/frontend/viewer_page.ts b/ui/src/frontend/viewer_page.ts
index 49e6d22..aa8d0c4 100644
--- a/ui/src/frontend/viewer_page.ts
+++ b/ui/src/frontend/viewer_page.ts
@@ -32,6 +32,7 @@
import {TimeAxisPanel} from './time_axis_panel';
import {computeZoom} from './time_scale';
import {TimeSelectionPanel} from './time_selection_panel';
+import {DISMISSED_PANNING_HINT_KEY} from './topbar';
import {TrackGroupPanel} from './track_group_panel';
import {TrackPanel} from './track_panel';
import {VideoPanel} from './video_panel';
@@ -131,7 +132,10 @@
const frontendLocalState = globals.frontendLocalState;
const updateDimensions = () => {
const rect = vnode.dom.getBoundingClientRect();
- frontendLocalState.updateResolution(0, rect.width - TRACK_SHELL_WIDTH);
+ frontendLocalState.updateResolution(
+ 0,
+ rect.width - TRACK_SHELL_WIDTH -
+ frontendLocalState.getScrollbarWidth());
};
updateDimensions();
@@ -167,6 +171,8 @@
tStart = tEnd - origDelta;
}
frontendLocalState.updateVisibleTime(new TimeSpan(tStart, tEnd));
+ // If the user has panned they no longer need the hint.
+ localStorage.setItem(DISMISSED_PANNING_HINT_KEY, 'true');
globals.rafScheduler.scheduleRedraw();
},
onZoomed: (zoomedPositionPx: number, zoomRatio: number) => {
@@ -179,10 +185,10 @@
frontendLocalState.updateVisibleTime(newSpan);
globals.rafScheduler.scheduleRedraw();
},
- shouldDrag: (currentPx: number) => {
+ editSelection: (currentPx: number) => {
return onTimeRangeBoundary(currentPx) !== null;
},
- onDrag: (
+ onSelection: (
dragStartX: number,
dragStartY: number,
prevX: number,
diff --git a/ui/src/service_worker/service_worker.ts b/ui/src/service_worker/service_worker.ts
new file mode 100644
index 0000000..3289352
--- /dev/null
+++ b/ui/src/service_worker/service_worker.ts
@@ -0,0 +1,166 @@
+// Copyright (C) 2020 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.
+
+// This script handles the caching of the UI resources, allowing it to work
+// offline (as long as the UI site has been visited at least once).
+// Design doc: http://go/perfetto-offline.
+
+// When a new version of the UI is released (e.g. v1 -> v2), the following
+// happens on the next visit:
+// 1. The v1 (old) service worker is activated (at this point we don't know yet
+// that v2 is released).
+// 2. /index.html is requested. The SW intercepts the request and serves
+// v1 from cache.
+// 3. The browser checks if a new version of service_worker.js is available. It
+// does that by comparing the bytes of the current and new version.
+// 5. service_worker.js v2 will not be byte identical with v1, even if v2 was a
+// css-only change. This is due to the hashes in UI_DIST_MAP below. For this
+// reason v2 is installed in the background (it takes several seconds).
+// 6. The 'install' handler is triggered, the new resources are fetched and
+// populated in the cache.
+// 7. The 'activate' handler is triggered. The old caches are deleted at this
+// point.
+// 8. frontend/index.ts (in setupServiceWorker()) is notified about the activate
+// and shows a notification prompting to reload the UI.
+//
+// If the user just closes the tab or hits refresh, v2 will be served anyways
+// on the next load.
+
+// UI_DIST_FILES is map of {file_name -> sha1}.
+// It is really important that this map is bundled directly in the
+// service_worker.js bundle file, as it's used to cause the browser to
+// re-install the service worker and re-fetch resources when anything changes.
+// This is why the map contains the SHA1s even if we don't directly use them in
+// the code (because it makes the final .js file content-dependent).
+
+import {UI_DIST_MAP} from '../gen/dist_file_map';
+
+declare var self: ServiceWorkerGlobalScope;
+
+const CACHE_NAME = 'dist-' + UI_DIST_MAP.hex_digest.substr(0, 16);
+const LOG_TAG = `ServiceWorker[${UI_DIST_MAP.hex_digest.substr(0, 16)}]: `;
+
+
+function shouldHandleHttpRequest(req: Request): boolean {
+ // Suppress warning: 'only-if-cached' can be set only with 'same-origin' mode.
+ // This seems to be a chromium bug. An internal code search suggests this is a
+ // socially acceptable workaround.
+ if (req.cache === 'only-if-cached' && req.mode !== 'same-origin') {
+ return false;
+ }
+
+ const url = new URL(req.url);
+ return req.method === 'GET' && url.origin === self.location.origin;
+}
+
+async function handleHttpRequest(req: Request): Promise<Response> {
+ if (!shouldHandleHttpRequest(req)) {
+ throw new Error(LOG_TAG + `${req.url} shouldn't have been handled`);
+ }
+
+ // We serve from the cache even if req.cache == 'no-cache'. It's a bit
+ // contra-intuitive but it's the most consistent option. If the user hits the
+ // reload button*, the browser requests the "/" index with a 'no-cache' fetch.
+ // However all the other resources (css, js, ...) are requested with a
+ // 'default' fetch (this is just how Chrome works, it's not us). If we bypass
+ // the service worker cache when we get a 'no-cache' request, we can end up in
+ // an inconsistent state where the index.html is more recent than the other
+ // resources, which is undesirable.
+ // * Only Ctrl+R. Ctrl+Shift+R will always bypass service-worker for all the
+ // requests (index.html and the rest) made in that tab.
+ try {
+ const cacheOps = {cacheName: CACHE_NAME} as CacheQueryOptions;
+ const cachedRes = await caches.match(req, cacheOps);
+ if (cachedRes) {
+ console.debug(LOG_TAG + `serving ${req.url} from cache`);
+ return cachedRes;
+ }
+ console.warn(LOG_TAG + `cache miss on ${req.url}`);
+ } catch (exc) {
+ console.error(LOG_TAG + `Cache request failed for ${req.url}`, exc);
+ }
+
+ // In any other case, just propagate the fetch on the network, which is the
+ // safe behavior.
+ console.debug(LOG_TAG + `falling back on network fetch() for ${req.url}`);
+ return fetch(req);
+}
+
+// The install() event is fired:
+// - The very first time the site is visited, after frontend/index.ts has
+// executed the serviceWorker.register() method.
+// - *After* the site is loaded, if the service_worker.js code
+// has changed (because of the hashes in UI_DIST_MAP, service_worker.js will
+// change if anything in the UI has changed).
+self.addEventListener('install', event => {
+ const doInstall = async () => {
+ if (await caches.has('BYPASS_SERVICE_WORKER')) {
+ // Throw will prevent the installation.
+ throw new Error(LOG_TAG + 'skipping installation, bypass enabled');
+ }
+ console.log(LOG_TAG + 'installation started');
+ const cache = await caches.open(CACHE_NAME);
+ const urlsToCache: RequestInfo[] = [];
+ for (const [file, integrity] of Object.entries(UI_DIST_MAP.files)) {
+ const reqOpts:
+ RequestInit = {cache: 'reload', mode: 'same-origin', integrity};
+ urlsToCache.push(new Request(file, reqOpts));
+ if (file === 'index.html' && location.host !== 'storage.googleapis.com') {
+ // Disable cachinig of '/' for cases where the UI is hosted on GCS.
+ // GCS doesn't support auto indexes. GCS returns a 404 page on / that
+ // fails the integrity check.
+ urlsToCache.push(new Request('/', reqOpts));
+ }
+ }
+ await cache.addAll(urlsToCache);
+ console.log(LOG_TAG + 'installation completed');
+
+ // skipWaiting() still waits for the install to be complete. Without this
+ // call, the new version would be activated only when all tabs are closed.
+ // Instead, we ask to activate it immediately. This is safe because each
+ // service worker version uses a different cache named after the SHA256 of
+ // the contents. When the old version is activated, the activate() method
+ // below will evict the cache for the old versions. If there is an old still
+ // opened, any further request from that tab will be a cache-miss and go
+ // through the network (which is inconsitent, but not the end of the world).
+ self.skipWaiting();
+ };
+ event.waitUntil(doInstall());
+});
+
+self.addEventListener('activate', (event) => {
+ console.warn(LOG_TAG + 'activated');
+ const doActivate = async () => {
+ // Clear old caches.
+ for (const key of await caches.keys()) {
+ if (key !== CACHE_NAME) await caches.delete(key);
+ }
+ // This makes a difference only for the very first load, when no service
+ // worker is present. In all the other cases the skipWaiting() will hot-swap
+ // the active service worker anyways.
+ await self.clients.claim();
+ };
+ event.waitUntil(doActivate());
+});
+
+self.addEventListener('fetch', event => {
+ // The early return here will cause the browser to fall back on standard
+ // network-based fetch.
+ if (!shouldHandleHttpRequest(event.request)) {
+ console.debug(LOG_TAG + `serving ${event.request.url} from network`);
+ return;
+ }
+
+ event.respondWith(handleHttpRequest(event.request));
+});
diff --git a/ui/src/service_worker/tsconfig.json b/ui/src/service_worker/tsconfig.json
new file mode 100644
index 0000000..7b58182
--- /dev/null
+++ b/ui/src/service_worker/tsconfig.json
@@ -0,0 +1,14 @@
+{
+ "extends": "../../tsconfig.base.json",
+ "include": [ "." ],
+ "exclude": [
+ "../gen/"
+ ],
+ "compilerOptions": {
+ "lib": [
+ "webworker",
+ "es2018",
+ ],
+ "types" : []
+ }
+}
diff --git a/ui/src/tracks/chrome_slices/common.ts b/ui/src/tracks/chrome_slices/common.ts
index faa40c3..41eb3c2 100644
--- a/ui/src/tracks/chrome_slices/common.ts
+++ b/ui/src/tracks/chrome_slices/common.ts
@@ -18,8 +18,6 @@
export interface Config {
maxDepth: number;
- upid: number;
- utid: number;
trackId: number;
}
diff --git a/ui/src/tracks/heap_profile/common.ts b/ui/src/tracks/heap_profile/common.ts
index fc9da62..0a8a16d 100644
--- a/ui/src/tracks/heap_profile/common.ts
+++ b/ui/src/tracks/heap_profile/common.ts
@@ -17,6 +17,7 @@
export interface Data extends TrackData {
tsStarts: Float64Array;
+ types: string[];
}
export interface Config {
diff --git a/ui/src/tracks/heap_profile/controller.ts b/ui/src/tracks/heap_profile/controller.ts
index 61ad335..bab0b15 100644
--- a/ui/src/tracks/heap_profile/controller.ts
+++ b/ui/src/tracks/heap_profile/controller.ts
@@ -28,11 +28,23 @@
async onBoundsChange(start: number, end: number, resolution: number):
Promise<Data> {
if (this.config.upid === undefined) {
- return {start, end, resolution, length: 0, tsStarts: new Float64Array()};
+ return {
+ start,
+ end,
+ resolution,
+ length: 0,
+ tsStarts: new Float64Array(),
+ types: new Array<string>()
+ };
}
const result = await this.query(`
- select distinct(ts) from heap_profile_allocation where upid = ${
- this.config.upid}`);
+ select * from
+ (select distinct(ts) as ts, 'native' as type from heap_profile_allocation
+ where upid = ${this.config.upid}
+ union
+ select distinct(graph_sample_ts) as ts, 'graph' as type from
+ heap_graph_object
+ where upid = ${this.config.upid}) order by ts`);
const numRows = +result.numRecords;
const data: Data = {
start,
@@ -40,10 +52,12 @@
resolution,
length: numRows,
tsStarts: new Float64Array(numRows),
+ types: new Array<string>(numRows),
};
for (let row = 0; row < numRows; row++) {
data.tsStarts[row] = +result.columns[0].longValues![row];
+ data.types[row] = result.columns[1].stringValues![row];
}
return data;
diff --git a/ui/src/tracks/heap_profile/frontend.ts b/ui/src/tracks/heap_profile/frontend.ts
index 8eaba5e..86d177e 100644
--- a/ui/src/tracks/heap_profile/frontend.ts
+++ b/ui/src/tracks/heap_profile/frontend.ts
@@ -118,10 +118,11 @@
if (index !== -1) {
const ts = data.tsStarts[index];
+ const type = data.types[index];
globals.dispatch(Actions.showHeapProfileFlamegraph(
- {id: index, upid: this.config.upid, ts}));
- globals.makeSelection(
- Actions.selectHeapProfile({id: index, upid: this.config.upid, ts}));
+ {id: index, upid: this.config.upid, ts, type}));
+ globals.makeSelection(Actions.selectHeapProfile(
+ {id: index, upid: this.config.upid, ts, type}));
return true;
}
return false;
diff --git a/ui/src/tracks/thread_state/frontend.ts b/ui/src/tracks/thread_state/frontend.ts
index 0b01644..cae38f2 100644
--- a/ui/src/tracks/thread_state/frontend.ts
+++ b/ui/src/tracks/thread_state/frontend.ts
@@ -31,7 +31,7 @@
} from './common';
const MARGIN_TOP = 4;
-const RECT_HEIGHT = 12;
+const RECT_HEIGHT = 14;
class ThreadStateTrack extends Track<Config, Data> {
static readonly kind = THREAD_STATE_TRACK_KIND;
@@ -54,6 +54,11 @@
if (data === undefined) return; // Can't possibly draw anything.
+ const shouldGroupBusyStates = groupBusyStates(data.resolution);
+
+ ctx.textAlign = 'center';
+ ctx.font = '10px Roboto Condensed';
+
for (let i = 0; i < data.starts.length; i++) {
const tStart = data.starts[i];
const tEnd = data.ends[i];
@@ -69,18 +74,16 @@
const color = colorForState(state);
ctx.fillStyle = `hsl(${color.h},${color.s}%,${color.l}%)`;
let rectWidth = rectEnd - rectStart;
- if (groupBusyStates(data.resolution) && rectWidth < 1) {
+ if (shouldGroupBusyStates && rectWidth < 1) {
rectWidth = 1;
}
ctx.fillRect(rectStart, MARGIN_TOP, rectWidth, RECT_HEIGHT);
- // Don't render text when we have less than 5px to play with.
- if (rectWidth < 5) continue;
- ctx.textAlign = 'center';
+ // Don't render text when we have less than 10px to play with.
+ if (rectWidth < 10) continue;
const title = cropText(translateState(state), charWidth, rectWidth);
const rectXCenter = rectStart + rectWidth / 2;
ctx.fillStyle = color.l < 80 ? '#fff' : '#404040';
- ctx.font = '10px Roboto Condensed';
ctx.fillText(title, rectXCenter, MARGIN_TOP + RECT_HEIGHT / 2 + 3);
}
}
diff --git a/ui/tsconfig.base.json b/ui/tsconfig.base.json
new file mode 100644
index 0000000..e240301
--- /dev/null
+++ b/ui/tsconfig.base.json
@@ -0,0 +1,27 @@
+{
+ "compilerOptions": {
+ "baseUrl": ".",
+ "target": "es6",
+ "module": "commonjs",
+ "moduleResolution": "node",
+ // Lints and checks.
+ "allowJs": true,
+ "declaration": false, // Generates corresponding '.d.ts' file.
+ "sourceMap": true, // Generates corresponding '.map' file.
+ "outDir": "./dist", // Redirect output structure to the directory.
+ "removeComments": false, // Do not emit comments to output.
+ "importHelpers": true, // Import emit helpers from 'tslib'.
+ "downlevelIteration": true, // Provide full support for iterables in 'for-of', spread, and destructuring when targeting 'ES5' or 'ES3'.
+ "strict": true, // Enable all strict type-checking options.
+ "noImplicitAny": true, // Raise error on expressions and declarations with an implied 'any' type.
+ "strictNullChecks": true, // Enable strict null checks.
+ "strictFunctionTypes": true, // Enable strict checking of function types.
+ "strictPropertyInitialization": true, // Enable strict checking of property initialization in classes.
+ "noImplicitThis": true, // Raise error on 'this' expressions with an implied 'any' type.
+ "alwaysStrict": true, // Parse in strict mode and emit "use strict" for each source file.
+ "noUnusedLocals": true, // Report errors on unused locals.
+ "noUnusedParameters": true, // Report errors on unused parameters.
+ "noImplicitReturns": true, // Report error when not all code paths in function return a value.
+ "noFallthroughCasesInSwitch": true, // Report errors for fallthrough cases in switch statement.
+ }
+}
diff --git a/ui/tsconfig.json b/ui/tsconfig.json
index e0564a8..8f2c266 100644
--- a/ui/tsconfig.json
+++ b/ui/tsconfig.json
@@ -1,7 +1,9 @@
{
+ "extends": "./tsconfig.base.json",
"include": [ "src/" ],
"exclude": [
"./node_modules/",
+ "./src/service_worker/",
"./src/gen/"
],
"compilerOptions": {
@@ -9,31 +11,8 @@
"dom", // Need to be explicitly mentioned now since we're overriding default included libs.
"es2018", // Need this to use Object.values.
],
- "baseUrl": ".",
"paths": {
"*" : ["*", "./node_modules/@tsundoku/micromodal_types/*"]
},
- "target": "es6",
- "module": "commonjs",
- "moduleResolution": "node",
- // Lints and checks.
- "allowJs": true,
- "declaration": false, // Generates corresponding '.d.ts' file.
- "sourceMap": true, // Generates corresponding '.map' file.
- "outDir": "./dist", // Redirect output structure to the directory.
- "removeComments": false, // Do not emit comments to output.
- "importHelpers": true, // Import emit helpers from 'tslib'.
- "downlevelIteration": true, // Provide full support for iterables in 'for-of', spread, and destructuring when targeting 'ES5' or 'ES3'.
- "strict": true, // Enable all strict type-checking options.
- "noImplicitAny": true, // Raise error on expressions and declarations with an implied 'any' type.
- "strictNullChecks": true, // Enable strict null checks.
- "strictFunctionTypes": true, // Enable strict checking of function types.
- "strictPropertyInitialization": true, // Enable strict checking of property initialization in classes.
- "noImplicitThis": true, // Raise error on 'this' expressions with an implied 'any' type.
- "alwaysStrict": true, // Parse in strict mode and emit "use strict" for each source file.
- "noUnusedLocals": true, // Report errors on unused locals.
- "noUnusedParameters": true, // Report errors on unused parameters.
- "noImplicitReturns": true, // Report error when not all code paths in function return a value.
- "noFallthroughCasesInSwitch": true, // Report errors for fallthrough cases in switch statement.
}
}