Merge "trace_processor: allow integers to be compared against doubles"
diff --git a/Android.bp b/Android.bp
index 811700e..4b67947 100644
--- a/Android.bp
+++ b/Android.bp
@@ -63,6 +63,7 @@
"src/protozero/message_handle.cc",
"src/protozero/proto_decoder.cc",
"src/protozero/proto_field_descriptor.cc",
+ "src/protozero/scattered_stream_memory_delegate.cc",
"src/protozero/scattered_stream_null_delegate.cc",
"src/protozero/scattered_stream_writer.cc",
"src/tracing/core/chrome_config.cc",
@@ -207,6 +208,7 @@
"src/protozero/message_handle.cc",
"src/protozero/proto_decoder.cc",
"src/protozero/proto_field_descriptor.cc",
+ "src/protozero/scattered_stream_memory_delegate.cc",
"src/protozero/scattered_stream_null_delegate.cc",
"src/protozero/scattered_stream_writer.cc",
"src/traced/probes/filesystem/file_scanner.cc",
@@ -332,12 +334,14 @@
"src/ipc/service_proxy.cc",
"src/ipc/virtual_destructors.cc",
"src/perfetto_cmd/main.cc",
+ "src/perfetto_cmd/pbtxt_to_pb.cc",
"src/perfetto_cmd/perfetto_cmd.cc",
"src/perfetto_cmd/rate_limiter.cc",
"src/protozero/message.cc",
"src/protozero/message_handle.cc",
"src/protozero/proto_decoder.cc",
"src/protozero/proto_field_descriptor.cc",
+ "src/protozero/scattered_stream_memory_delegate.cc",
"src/protozero/scattered_stream_null_delegate.cc",
"src/protozero/scattered_stream_writer.cc",
"src/tracing/core/chrome_config.cc",
@@ -480,7 +484,7 @@
"src/protozero/message_handle.cc",
"src/protozero/proto_decoder.cc",
"src/protozero/proto_field_descriptor.cc",
- "src/protozero/scattered_stream_delegate_for_testing.cc",
+ "src/protozero/scattered_stream_memory_delegate.cc",
"src/protozero/scattered_stream_null_delegate.cc",
"src/protozero/scattered_stream_writer.cc",
"src/traced/probes/filesystem/file_scanner.cc",
@@ -3929,6 +3933,7 @@
genrule {
name: "perfetto_src_perfetto_cmd_protos_gen",
srcs: [
+ "src/perfetto_cmd/descriptor.proto",
"src/perfetto_cmd/perfetto_cmd_state.proto",
],
tools: [
@@ -3936,6 +3941,7 @@
],
cmd: "mkdir -p $(genDir)/external/perfetto && $(location aprotoc) --cpp_out=$(genDir)/external/perfetto --proto_path=external/perfetto/ $(in)",
out: [
+ "external/perfetto/src/perfetto_cmd/descriptor.pb.cc",
"external/perfetto/src/perfetto_cmd/perfetto_cmd_state.pb.cc",
],
}
@@ -3944,6 +3950,7 @@
genrule {
name: "perfetto_src_perfetto_cmd_protos_gen_headers",
srcs: [
+ "src/perfetto_cmd/descriptor.proto",
"src/perfetto_cmd/perfetto_cmd_state.proto",
],
tools: [
@@ -3951,6 +3958,7 @@
],
cmd: "mkdir -p $(genDir)/external/perfetto && $(location aprotoc) --cpp_out=$(genDir)/external/perfetto --proto_path=external/perfetto/ $(in)",
out: [
+ "external/perfetto/src/perfetto_cmd/descriptor.pb.h",
"external/perfetto/src/perfetto_cmd/perfetto_cmd_state.pb.h",
],
export_include_dirs: [
@@ -4178,6 +4186,7 @@
"src/protozero/message_handle.cc",
"src/protozero/proto_decoder.cc",
"src/protozero/proto_field_descriptor.cc",
+ "src/protozero/scattered_stream_memory_delegate.cc",
"src/protozero/scattered_stream_null_delegate.cc",
"src/protozero/scattered_stream_writer.cc",
"src/tracing/core/chrome_config.cc",
@@ -4385,6 +4394,8 @@
"src/ipc/service_proxy.cc",
"src/ipc/test/ipc_integrationtest.cc",
"src/ipc/virtual_destructors.cc",
+ "src/perfetto_cmd/pbtxt_to_pb.cc",
+ "src/perfetto_cmd/pbtxt_to_pb_unittest.cc",
"src/perfetto_cmd/perfetto_cmd.cc",
"src/perfetto_cmd/rate_limiter.cc",
"src/perfetto_cmd/rate_limiter_unittest.cc",
@@ -4415,7 +4426,7 @@
"src/protozero/proto_decoder_unittest.cc",
"src/protozero/proto_field_descriptor.cc",
"src/protozero/proto_utils_unittest.cc",
- "src/protozero/scattered_stream_delegate_for_testing.cc",
+ "src/protozero/scattered_stream_memory_delegate.cc",
"src/protozero/scattered_stream_null_delegate.cc",
"src/protozero/scattered_stream_writer.cc",
"src/protozero/scattered_stream_writer_unittest.cc",
diff --git a/PRESUBMIT.py b/PRESUBMIT.py
index 2d54a34..9a4902f 100644
--- a/PRESUBMIT.py
+++ b/PRESUBMIT.py
@@ -81,6 +81,21 @@
return []
+def CheckBinaryDescriptors(input_api, output_api):
+ tool = 'tools/gen_binary_descriptors'
+ file_filter = lambda x: input_api.FilterSourceFile(
+ x,
+ white_list=('.*[.]h$', '.*[.]proto$', tool))
+ if not input_api.AffectedSourceFiles(file_filter):
+ return []
+ if subprocess.call([tool, '--check-only']):
+ return [
+ output_api.PresubmitError(
+ 'Please run ' + tool + ' to update binary descriptors.')
+ ]
+ return []
+
+
def CheckMergedTraceConfigProto(input_api, output_api):
tool = 'tools/gen_merged_protos'
build_file_filter = lambda x: input_api.FilterSourceFile(
@@ -102,7 +117,7 @@
for f in input_api.AffectedFiles():
if f.LocalPath() != 'tools/ftrace_proto_gen/event_whitelist':
continue
- if any((not new_line.startswith('removed'))
+ if any((not new_line.startswith('removed'))
and new_line != old_line for old_line, new_line
in itertools.izip(f.OldContents(), f.NewContents())):
return [
diff --git a/include/perfetto/protozero/BUILD.gn b/include/perfetto/protozero/BUILD.gn
index cc75d2d8..06b067f 100644
--- a/include/perfetto/protozero/BUILD.gn
+++ b/include/perfetto/protozero/BUILD.gn
@@ -23,6 +23,7 @@
"proto_decoder.h",
"proto_field_descriptor.h",
"proto_utils.h",
+ "scattered_stream_memory_delegate.h",
"scattered_stream_null_delegate.h",
"scattered_stream_writer.h",
]
diff --git a/src/protozero/scattered_stream_delegate_for_testing.h b/include/perfetto/protozero/scattered_stream_memory_delegate.h
similarity index 79%
rename from src/protozero/scattered_stream_delegate_for_testing.h
rename to include/perfetto/protozero/scattered_stream_memory_delegate.h
index 365ad43..5910fbd 100644
--- a/src/protozero/scattered_stream_delegate_for_testing.h
+++ b/include/perfetto/protozero/scattered_stream_memory_delegate.h
@@ -14,8 +14,8 @@
* limitations under the License.
*/
-#ifndef SRC_PROTOZERO_SCATTERED_STREAM_DELEGATE_FOR_TESTING_H_
-#define SRC_PROTOZERO_SCATTERED_STREAM_DELEGATE_FOR_TESTING_H_
+#ifndef INCLUDE_PERFETTO_PROTOZERO_SCATTERED_STREAM_MEMORY_DELEGATE_H_
+#define INCLUDE_PERFETTO_PROTOZERO_SCATTERED_STREAM_MEMORY_DELEGATE_H_
#include <memory>
#include <vector>
@@ -25,11 +25,11 @@
namespace perfetto {
-class ScatteredStreamDelegateForTesting
+class ScatteredStreamMemoryDelegate
: public protozero::ScatteredStreamWriter::Delegate {
public:
- explicit ScatteredStreamDelegateForTesting(size_t chunk_size);
- ~ScatteredStreamDelegateForTesting() override;
+ explicit ScatteredStreamMemoryDelegate(size_t chunk_size);
+ ~ScatteredStreamMemoryDelegate() override;
// protozero::ScatteredStreamWriter::Delegate implementation.
protozero::ContiguousMemoryRange GetNewBuffer() override;
@@ -54,4 +54,4 @@
} // namespace perfetto
-#endif // SRC_PROTOZERO_SCATTERED_STREAM_DELEGATE_FOR_TESTING_H_
+#endif // INCLUDE_PERFETTO_PROTOZERO_SCATTERED_STREAM_MEMORY_DELEGATE_H_
diff --git a/protos/perfetto/config/BUILD.gn b/protos/perfetto/config/BUILD.gn
index dd8fb4e..75b496b 100644
--- a/protos/perfetto/config/BUILD.gn
+++ b/protos/perfetto/config/BUILD.gn
@@ -20,6 +20,10 @@
generate_python = false
proto_in_dir = "$perfetto_root_path/protos"
proto_out_dir = "$perfetto_root_path/protos"
+ if (!build_with_chromium) {
+ generate_descriptor =
+ "$perfetto_root_path/protos/perfetto/trace/config.descriptor"
+ }
deps = [
"../common:lite",
]
diff --git a/protos/perfetto/config/perfetto_config.proto b/protos/perfetto/config/perfetto_config.proto
index 5345a87..381539e 100644
--- a/protos/perfetto/config/perfetto_config.proto
+++ b/protos/perfetto/config/perfetto_config.proto
@@ -365,6 +365,23 @@
// The configuration for a fake producer used in tests.
message TestConfig {
+ message DummyFields {
+ optional uint32 field_uint32 = 1;
+ optional int32 field_int32 = 2;
+ optional uint64 field_uint64 = 3;
+ optional int64 field_int64 = 4;
+ optional fixed64 field_fixed64 = 5;
+ optional sfixed64 field_sfixed64 = 6;
+ optional fixed32 field_fixed32 = 7;
+ optional sfixed32 field_sfixed32 = 8;
+ optional double field_double = 9;
+ optional float field_float = 10;
+ optional sint64 field_sint64 = 11;
+ optional sint32 field_sint32 = 12;
+ optional string field_string = 13;
+ optional bytes field_bytes = 14;
+ }
+
// The number of messages the fake producer should send.
optional uint32 message_count = 1;
@@ -386,6 +403,8 @@
// Whether the producer should send a event batch when the data source is
// is initially registered.
optional bool send_batch_on_register = 5;
+
+ optional DummyFields dummy_fields = 6;
}
// End of protos/perfetto/config/test_config.proto
diff --git a/protos/perfetto/config/test_config.proto b/protos/perfetto/config/test_config.proto
index c8d57d5..b50012e 100644
--- a/protos/perfetto/config/test_config.proto
+++ b/protos/perfetto/config/test_config.proto
@@ -24,6 +24,23 @@
// The configuration for a fake producer used in tests.
message TestConfig {
+ message DummyFields {
+ optional uint32 field_uint32 = 1;
+ optional int32 field_int32 = 2;
+ optional uint64 field_uint64 = 3;
+ optional int64 field_int64 = 4;
+ optional fixed64 field_fixed64 = 5;
+ optional sfixed64 field_sfixed64 = 6;
+ optional fixed32 field_fixed32 = 7;
+ optional sfixed32 field_sfixed32 = 8;
+ optional double field_double = 9;
+ optional float field_float = 10;
+ optional sint64 field_sint64 = 11;
+ optional sint32 field_sint32 = 12;
+ optional string field_string = 13;
+ optional bytes field_bytes = 14;
+ }
+
// The number of messages the fake producer should send.
optional uint32 message_count = 1;
@@ -45,4 +62,6 @@
// Whether the producer should send a event batch when the data source is
// is initially registered.
optional bool send_batch_on_register = 5;
+
+ optional DummyFields dummy_fields = 6;
}
diff --git a/protos/perfetto/trace/ftrace/ftrace_event.proto b/protos/perfetto/trace/ftrace/ftrace_event.proto
index bc7af38..860eb48 100644
--- a/protos/perfetto/trace/ftrace/ftrace_event.proto
+++ b/protos/perfetto/trace/ftrace/ftrace_event.proto
@@ -321,6 +321,7 @@
// TODO: Figure out a story for reconciling the various clocks.
optional uint64 timestamp = 1;
+ // Kernel pid (do not confuse with userspace pid aka tgid)
optional uint32 pid = 2;
oneof event {
diff --git a/protos/perfetto/trace/perfetto_trace.proto b/protos/perfetto/trace/perfetto_trace.proto
index 520185f..8f00dcf 100644
--- a/protos/perfetto/trace/perfetto_trace.proto
+++ b/protos/perfetto/trace/perfetto_trace.proto
@@ -233,6 +233,7 @@
// TODO: Figure out a story for reconciling the various clocks.
optional uint64 timestamp = 1;
+ // Kernel pid (do not confuse with userspace pid aka tgid)
optional uint32 pid = 2;
oneof event {
diff --git a/src/perfetto_cmd/BUILD.gn b/src/perfetto_cmd/BUILD.gn
index d71b1ed..175d2b0 100644
--- a/src/perfetto_cmd/BUILD.gn
+++ b/src/perfetto_cmd/BUILD.gn
@@ -21,6 +21,7 @@
"../../include/perfetto/traced",
]
deps = [
+ "../../buildtools:protobuf_lite",
"../../gn:default_deps",
"../../protos/perfetto/config:lite",
"../base",
@@ -28,8 +29,11 @@
"../tracing:ipc_consumer",
]
sources = [
+ "pbtxt_to_pb.cc",
+ "pbtxt_to_pb.h",
"perfetto_cmd.cc",
"perfetto_cmd.h",
+ "perfetto_config.descriptor.h",
"rate_limiter.cc",
"rate_limiter.h",
]
@@ -39,6 +43,7 @@
generate_python = false
deps = []
sources = [
+ "descriptor.proto",
"perfetto_cmd_state.proto",
]
proto_in_dir = perfetto_root_path
@@ -53,8 +58,10 @@
"../../gn:default_deps",
"../../gn:gtest_deps",
"../../include/perfetto/base",
+ "../../protos/perfetto/config:lite",
]
sources = [
+ "pbtxt_to_pb_unittest.cc",
"rate_limiter_unittest.cc",
]
}
diff --git a/src/perfetto_cmd/descriptor.proto b/src/perfetto_cmd/descriptor.proto
new file mode 100644
index 0000000..be0fff5
--- /dev/null
+++ b/src/perfetto_cmd/descriptor.proto
@@ -0,0 +1,191 @@
+/*
+ * 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.
+ */
+
+// This is a subset of descriptor.proto from the Protobuf library.
+syntax = "proto2";
+
+package perfetto.protos;
+
+option optimize_for = LITE_RUNTIME;
+
+// The protocol compiler can output a FileDescriptorSet containing the .proto
+// files it parses.
+message FileDescriptorSet {
+ repeated FileDescriptorProto file = 1;
+}
+
+// Describes a complete .proto file.
+message FileDescriptorProto {
+ optional string name = 1; // file name, relative to root of source tree
+ optional string package = 2; // e.g. "foo", "foo.bar", etc.
+
+ // Names of files imported by this file.
+ repeated string dependency = 3;
+ // Indexes of the public imported files in the dependency list above.
+ repeated int32 public_dependency = 10;
+ // Indexes of the weak imported files in the dependency list.
+ // For Google-internal migration only. Do not use.
+ repeated int32 weak_dependency = 11;
+
+ // All top-level definitions in this file.
+ repeated DescriptorProto message_type = 4;
+ repeated EnumDescriptorProto enum_type = 5;
+
+ reserved 6;
+ reserved 7;
+ reserved 8;
+ reserved 9;
+ reserved 12;
+}
+
+// Describes a message type.
+message DescriptorProto {
+ optional string name = 1;
+
+ repeated FieldDescriptorProto field = 2;
+ repeated FieldDescriptorProto extension = 6;
+
+ repeated DescriptorProto nested_type = 3;
+ repeated EnumDescriptorProto enum_type = 4;
+
+ reserved 5;
+
+ repeated OneofDescriptorProto oneof_decl = 8;
+
+ reserved 7;
+
+ // Range of reserved tag numbers. Reserved tag numbers may not be used by
+ // fields or extension ranges in the same message. Reserved ranges may
+ // not overlap.
+ message ReservedRange {
+ optional int32 start = 1; // Inclusive.
+ optional int32 end = 2; // Exclusive.
+ }
+ repeated ReservedRange reserved_range = 9;
+ // Reserved field names, which may not be used by fields in the same message.
+ // A given name may only be reserved once.
+ repeated string reserved_name = 10;
+}
+
+// Describes a field within a message.
+message FieldDescriptorProto {
+ enum Type {
+ // 0 is reserved for errors.
+ // Order is weird for historical reasons.
+ TYPE_DOUBLE = 1;
+ TYPE_FLOAT = 2;
+ // Not ZigZag encoded. Negative numbers take 10 bytes. Use TYPE_SINT64 if
+ // negative values are likely.
+ TYPE_INT64 = 3;
+ TYPE_UINT64 = 4;
+ // Not ZigZag encoded. Negative numbers take 10 bytes. Use TYPE_SINT32 if
+ // negative values are likely.
+ TYPE_INT32 = 5;
+ TYPE_FIXED64 = 6;
+ TYPE_FIXED32 = 7;
+ TYPE_BOOL = 8;
+ TYPE_STRING = 9;
+ // Tag-delimited aggregate.
+ // Group type is deprecated and not supported in proto3. However, Proto3
+ // implementations should still be able to parse the group wire format and
+ // treat group fields as unknown fields.
+ TYPE_GROUP = 10;
+ TYPE_MESSAGE = 11; // Length-delimited aggregate.
+
+ // New in version 2.
+ TYPE_BYTES = 12;
+ TYPE_UINT32 = 13;
+ TYPE_ENUM = 14;
+ TYPE_SFIXED32 = 15;
+ TYPE_SFIXED64 = 16;
+ TYPE_SINT32 = 17; // Uses ZigZag encoding.
+ TYPE_SINT64 = 18; // Uses ZigZag encoding.
+ };
+
+ enum Label {
+ // 0 is reserved for errors
+ LABEL_OPTIONAL = 1;
+ LABEL_REQUIRED = 2;
+ LABEL_REPEATED = 3;
+ };
+
+ optional string name = 1;
+ optional int32 number = 3;
+ optional Label label = 4;
+
+ // If type_name is set, this need not be set. If both this and type_name
+ // are set, this must be one of TYPE_ENUM, TYPE_MESSAGE or TYPE_GROUP.
+ optional Type type = 5;
+
+ // For message and enum types, this is the name of the type. If the name
+ // starts with a '.', it is fully-qualified. Otherwise, C++-like scoping
+ // rules are used to find the type (i.e. first the nested types within this
+ // message are searched, then within the parent, on up to the root
+ // namespace).
+ optional string type_name = 6;
+
+ reserved 2;
+
+ // For numeric types, contains the original text representation of the value.
+ // For booleans, "true" or "false".
+ // For strings, contains the default text contents (not escaped in any way).
+ // For bytes, contains the C escaped value. All bytes >= 128 are escaped.
+ // TODO(kenton): Base-64 encode?
+ optional string default_value = 7;
+
+ // If set, gives the index of a oneof in the containing type's oneof_decl
+ // list. This field is a member of that oneof.
+ optional int32 oneof_index = 9;
+
+ reserved 10;
+
+ reserved 8;
+}
+
+// Describes a oneof.
+message OneofDescriptorProto {
+ optional string name = 1;
+ optional OneofOptions options = 2;
+}
+
+// Describes an enum type.
+message EnumDescriptorProto {
+ optional string name = 1;
+
+ repeated EnumValueDescriptorProto value = 2;
+
+ reserved 3;
+ reserved 4;
+
+ // Reserved enum value names, which may not be reused. A given name may only
+ // be reserved once.
+ repeated string reserved_name = 5;
+}
+
+// Describes a value within an enum.
+message EnumValueDescriptorProto {
+ optional string name = 1;
+ optional int32 number = 2;
+
+ reserved 3;
+}
+
+message OneofOptions {
+ reserved 999;
+
+ // Clients can define custom options in extensions of this message. See above.
+ extensions 1000 to max;
+}
diff --git a/src/perfetto_cmd/pbtxt_to_pb.cc b/src/perfetto_cmd/pbtxt_to_pb.cc
new file mode 100644
index 0000000..ec4af7d
--- /dev/null
+++ b/src/perfetto_cmd/pbtxt_to_pb.cc
@@ -0,0 +1,615 @@
+/*
+ * 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 <ctype.h>
+#include <set>
+#include <stack>
+#include <string>
+
+#include "src/perfetto_cmd/pbtxt_to_pb.h"
+
+#include "google/protobuf/io/zero_copy_stream_impl_lite.h"
+#include "src/perfetto_cmd/descriptor.pb.h"
+
+#include "perfetto/base/file_utils.h"
+#include "perfetto/base/logging.h"
+#include "perfetto/base/string_view.h"
+#include "perfetto/protozero/message.h"
+#include "perfetto/protozero/message_handle.h"
+#include "perfetto/protozero/scattered_stream_memory_delegate.h"
+#include "src/perfetto_cmd/perfetto_config.descriptor.h"
+
+namespace perfetto {
+constexpr char kConfigProtoName[] = ".perfetto.protos.TraceConfig";
+
+using protos::DescriptorProto;
+using protos::EnumDescriptorProto;
+using protos::EnumValueDescriptorProto;
+using protos::FieldDescriptorProto;
+using protos::FileDescriptorSet;
+using ::google::protobuf::io::ZeroCopyInputStream;
+using ::google::protobuf::io::ArrayInputStream;
+
+namespace {
+
+constexpr bool IsIdentifierStart(char c) {
+ return ('A' <= c && c <= 'Z') || ('a' <= c && c <= 'z') || c == '_';
+}
+
+constexpr bool IsIdentifierBody(char c) {
+ return IsIdentifierStart(c) || isdigit(c);
+}
+
+const char* FieldToTypeName(const FieldDescriptorProto* field) {
+ switch (field->type()) {
+ case FieldDescriptorProto::TYPE_UINT64:
+ return "uint64";
+ case FieldDescriptorProto::TYPE_UINT32:
+ return "uint32";
+ case FieldDescriptorProto::TYPE_INT64:
+ return "int64";
+ case FieldDescriptorProto::TYPE_SINT64:
+ return "sint64";
+ case FieldDescriptorProto::TYPE_INT32:
+ return "int32";
+ case FieldDescriptorProto::TYPE_SINT32:
+ return "sint32";
+ case FieldDescriptorProto::TYPE_FIXED64:
+ return "fixed64";
+ case FieldDescriptorProto::TYPE_SFIXED64:
+ return "sfixed64";
+ case FieldDescriptorProto::TYPE_FIXED32:
+ return "fixed32";
+ case FieldDescriptorProto::TYPE_SFIXED32:
+ return "sfixed32";
+ case FieldDescriptorProto::TYPE_DOUBLE:
+ return "double";
+ case FieldDescriptorProto::TYPE_FLOAT:
+ return "float";
+ case FieldDescriptorProto::TYPE_BOOL:
+ return "bool";
+ case FieldDescriptorProto::TYPE_STRING:
+ return "string";
+ case FieldDescriptorProto::TYPE_BYTES:
+ return "bytes";
+ case FieldDescriptorProto::TYPE_GROUP:
+ return "group";
+ case FieldDescriptorProto::TYPE_MESSAGE:
+ return "message";
+ case FieldDescriptorProto::TYPE_ENUM:
+ return "enum";
+ }
+ // For gcc
+ PERFETTO_FATAL("Non conmplete switch");
+}
+
+std::string Format(const char* fmt, std::map<std::string, std::string> args) {
+ std::string result(fmt);
+ for (const auto& key_value : args) {
+ size_t start = result.find(key_value.first);
+ PERFETTO_CHECK(start != std::string::npos);
+ result.replace(start, key_value.first.size(), key_value.second);
+ PERFETTO_CHECK(result.find(key_value.first) == std::string::npos);
+ }
+ return result;
+}
+
+enum ParseState {
+ kWaitingForKey,
+ kReadingKey,
+ kWaitingForValue,
+ kReadingStringValue,
+ kReadingNumericValue,
+ kReadingIdentifierValue,
+};
+
+struct Token {
+ size_t offset;
+ size_t column;
+ size_t row;
+ base::StringView txt;
+
+ size_t size() const { return txt.size(); }
+ std::string ToStdString() const { return txt.ToStdString(); }
+};
+
+struct ParserDelegateContext {
+ const DescriptorProto* descriptor;
+ protozero::Message* message;
+ std::set<std::string> seen_fields;
+};
+
+class ParserDelegate {
+ public:
+ ParserDelegate(
+ const DescriptorProto* descriptor,
+ protozero::Message* message,
+ ErrorReporter* reporter,
+ std::map<std::string, const DescriptorProto*> name_to_descriptor,
+ std::map<std::string, const EnumDescriptorProto*> name_to_enum)
+ : reporter_(reporter),
+ name_to_descriptor_(std::move(name_to_descriptor)),
+ name_to_enum_(std::move(name_to_enum)) {
+ ctx_.push(ParserDelegateContext{descriptor, message, {}});
+ }
+
+ void NumericField(Token key, Token value) {
+ const FieldDescriptorProto* field = FindFieldByName(
+ key, value,
+ {
+ FieldDescriptorProto::TYPE_UINT64,
+ FieldDescriptorProto::TYPE_UINT32, FieldDescriptorProto::TYPE_INT64,
+ FieldDescriptorProto::TYPE_SINT64, FieldDescriptorProto::TYPE_INT32,
+ FieldDescriptorProto::TYPE_SINT32,
+ FieldDescriptorProto::TYPE_FIXED64,
+ FieldDescriptorProto::TYPE_SFIXED64,
+ FieldDescriptorProto::TYPE_FIXED32,
+ FieldDescriptorProto::TYPE_SFIXED32,
+ FieldDescriptorProto::TYPE_DOUBLE, FieldDescriptorProto::TYPE_FLOAT,
+ });
+ if (!field)
+ return;
+ const auto& field_type = field->type();
+ switch (field_type) {
+ case FieldDescriptorProto::TYPE_UINT64:
+ return VarIntField<uint64_t>(field, value);
+ case FieldDescriptorProto::TYPE_UINT32:
+ return VarIntField<uint32_t>(field, value);
+ case FieldDescriptorProto::TYPE_INT64:
+ case FieldDescriptorProto::TYPE_SINT64:
+ return VarIntField<int64_t>(field, value);
+ case FieldDescriptorProto::TYPE_INT32:
+ case FieldDescriptorProto::TYPE_SINT32:
+ return VarIntField<int32_t>(field, value);
+
+ case FieldDescriptorProto::TYPE_FIXED64:
+ case FieldDescriptorProto::TYPE_SFIXED64:
+ return FixedField<int64_t>(field, value);
+
+ case FieldDescriptorProto::TYPE_FIXED32:
+ case FieldDescriptorProto::TYPE_SFIXED32:
+ return FixedField<int32_t>(field, value);
+
+ case FieldDescriptorProto::TYPE_DOUBLE:
+ return FixedFloatField<double>(field, value);
+ case FieldDescriptorProto::TYPE_FLOAT:
+ return FixedFloatField<float>(field, value);
+
+ case FieldDescriptorProto::TYPE_BOOL:
+ case FieldDescriptorProto::TYPE_STRING:
+ case FieldDescriptorProto::TYPE_BYTES:
+ case FieldDescriptorProto::TYPE_GROUP:
+ case FieldDescriptorProto::TYPE_MESSAGE:
+ case FieldDescriptorProto::TYPE_ENUM:
+ PERFETTO_FATAL("Invalid type");
+ }
+ }
+
+ void StringField(Token key, Token value) {
+ const FieldDescriptorProto* field = FindFieldByName(
+ key, value,
+ {
+ FieldDescriptorProto::TYPE_STRING, FieldDescriptorProto::TYPE_BYTES,
+ });
+ if (!field)
+ return;
+ uint32_t field_id = static_cast<uint32_t>(field->number());
+ const auto& field_type = field->type();
+ PERFETTO_CHECK(field_type == FieldDescriptorProto::TYPE_STRING ||
+ field_type == FieldDescriptorProto::TYPE_BYTES);
+
+ msg()->AppendBytes(field_id, value.txt.data(), value.size());
+ }
+
+ void IdentifierField(Token key, Token value) {
+ const FieldDescriptorProto* field = FindFieldByName(
+ key, value,
+ {
+ FieldDescriptorProto::TYPE_BOOL, FieldDescriptorProto::TYPE_ENUM,
+ });
+ if (!field)
+ return;
+ uint32_t field_id = static_cast<uint32_t>(field->number());
+ const auto& field_type = field->type();
+ if (field_type == FieldDescriptorProto::TYPE_BOOL) {
+ if (value.txt != "true" && value.txt != "false") {
+ AddError(value,
+ "Expected 'true' or 'false' for boolean field $k in "
+ "proto $n instead saw '$v'",
+ std::map<std::string, std::string>{
+ {"$k", key.ToStdString()},
+ {"$n", descriptor_name()},
+ {"$v", value.ToStdString()},
+ });
+ return;
+ }
+ msg()->AppendTinyVarInt(field_id, value.txt == "true" ? 1 : 0);
+ } else if (field_type == FieldDescriptorProto::TYPE_ENUM) {
+ const std::string& type_name = field->type_name();
+ const EnumDescriptorProto* enum_descriptor = name_to_enum_[type_name];
+ PERFETTO_CHECK(enum_descriptor);
+ bool found_value = false;
+ int32_t enum_value_number = 0;
+ for (const EnumValueDescriptorProto& enum_value :
+ enum_descriptor->value()) {
+ if (value.ToStdString() != enum_value.name())
+ continue;
+ found_value = true;
+ enum_value_number = enum_value.number();
+ break;
+ }
+ PERFETTO_CHECK(found_value);
+ msg()->AppendVarInt<int32_t>(field_id, enum_value_number);
+ } else {
+ }
+ }
+
+ void BeginNestedMessage(Token key, Token value) {
+ const FieldDescriptorProto* field =
+ FindFieldByName(key, value,
+ {
+ FieldDescriptorProto::TYPE_MESSAGE,
+ });
+ if (!field)
+ return;
+ uint32_t field_id = static_cast<uint32_t>(field->number());
+ const std::string& type_name = field->type_name();
+ const DescriptorProto* nested_descriptor = name_to_descriptor_[type_name];
+ PERFETTO_CHECK(nested_descriptor);
+ auto* nested_msg = msg()->BeginNestedMessage<protozero::Message>(field_id);
+ ctx_.push(ParserDelegateContext{nested_descriptor, nested_msg, {}});
+ }
+
+ void EndNestedMessage() {
+ msg()->Finalize();
+ ctx_.pop();
+ }
+
+ void Eof() {}
+
+ void AddError(size_t row,
+ size_t column,
+ const char* fmt,
+ const std::map<std::string, std::string>& args) {
+ reporter_->AddError(row, column, 0, Format(fmt, args));
+ }
+
+ void AddError(Token token,
+ const char* fmt,
+ const std::map<std::string, std::string>& args) {
+ reporter_->AddError(token.row, token.column, token.size(),
+ Format(fmt, args));
+ }
+
+ private:
+ template <typename T>
+ void VarIntField(const FieldDescriptorProto* field, Token t) {
+ uint32_t field_id = static_cast<uint32_t>(field->number());
+ uint64_t n = 0;
+ PERFETTO_CHECK(ParseInteger(t.txt, &n));
+ if (field->type() == FieldDescriptorProto::TYPE_SINT64 ||
+ field->type() == FieldDescriptorProto::TYPE_SINT32) {
+ msg()->AppendSignedVarInt<T>(field_id, static_cast<T>(n));
+ } else {
+ msg()->AppendVarInt<T>(field_id, static_cast<T>(n));
+ }
+ }
+
+ template <typename T>
+ void FixedField(const FieldDescriptorProto* field, Token t) {
+ uint32_t field_id = static_cast<uint32_t>(field->number());
+ uint64_t n = 0;
+ PERFETTO_CHECK(ParseInteger(t.txt, &n));
+ msg()->AppendFixed<T>(field_id, static_cast<T>(n));
+ }
+
+ template <typename T>
+ void FixedFloatField(const FieldDescriptorProto* field, Token t) {
+ uint32_t field_id = static_cast<uint32_t>(field->number());
+ double n = std::stod(t.ToStdString());
+ msg()->AppendFixed<T>(field_id, static_cast<T>(n));
+ }
+
+ template <typename T>
+ bool ParseInteger(base::StringView s, T* number_ptr) {
+ uint64_t n = 0;
+ PERFETTO_CHECK(sscanf(s.ToStdString().c_str(), "%" PRIu64, &n) == 1);
+ PERFETTO_CHECK(n <= std::numeric_limits<T>::max());
+ *number_ptr = static_cast<T>(n);
+ return true;
+ }
+
+ const FieldDescriptorProto* FindFieldByName(
+ Token key,
+ Token value,
+ std::set<FieldDescriptorProto::Type> valid_field_types) {
+ const std::string field_name = key.ToStdString();
+ const FieldDescriptorProto* field_descriptor = nullptr;
+ for (const auto& f : descriptor()->field()) {
+ if (f.name() == field_name) {
+ field_descriptor = &f;
+ break;
+ }
+ }
+
+ if (!field_descriptor) {
+ AddError(key, "No field named \"$n\" in proto $p",
+ {
+ {"$n", field_name}, {"$p", descriptor_name()},
+ });
+ return nullptr;
+ }
+
+ bool is_repeated =
+ field_descriptor->label() == FieldDescriptorProto::LABEL_REPEATED;
+ auto it_and_inserted = ctx_.top().seen_fields.emplace(field_name);
+ if (!it_and_inserted.second && !is_repeated) {
+ AddError(key, "Saw non-repeating field '$f' more than once",
+ {
+ {"$f", field_name},
+ });
+ }
+
+ if (!valid_field_types.count(field_descriptor->type())) {
+ AddError(value,
+ "Expected value of type $t for field $k in proto $n "
+ "instead saw '$v'",
+ {
+ {"$t", FieldToTypeName(field_descriptor)},
+ {"$k", field_name},
+ {"$n", descriptor_name()},
+ {"$v", value.ToStdString()},
+ });
+ return nullptr;
+ }
+
+ return field_descriptor;
+ }
+
+ const DescriptorProto* descriptor() {
+ PERFETTO_CHECK(!ctx_.empty());
+ return ctx_.top().descriptor;
+ }
+
+ const std::string& descriptor_name() { return descriptor()->name(); }
+
+ protozero::Message* msg() {
+ PERFETTO_CHECK(!ctx_.empty());
+ return ctx_.top().message;
+ }
+
+ std::stack<ParserDelegateContext> ctx_;
+ ErrorReporter* reporter_;
+ std::map<std::string, const DescriptorProto*> name_to_descriptor_;
+ std::map<std::string, const EnumDescriptorProto*> name_to_enum_;
+};
+
+void Parse(const std::string& input, ParserDelegate* delegate) {
+ ParseState state = kWaitingForKey;
+ size_t column = 0;
+ size_t row = 1;
+ size_t depth = 0;
+ bool saw_colon_for_this_key = false;
+ bool saw_semicolon_for_this_value = true;
+ bool comment_till_eol = false;
+ Token key;
+ Token value;
+
+ for (size_t i = 0; i < input.size(); i++, column++) {
+ bool last_character = i + 1 == input.size();
+ char c = input.at(i);
+ if (c == '\n') {
+ column = 0;
+ row++;
+ if (comment_till_eol) {
+ comment_till_eol = false;
+ continue;
+ }
+ }
+ if (comment_till_eol)
+ continue;
+
+ switch (state) {
+ case kWaitingForKey:
+ if (isspace(c))
+ continue;
+ if (c == '#') {
+ comment_till_eol = true;
+ continue;
+ }
+ if (c == '}') {
+ if (depth == 0) {
+ delegate->AddError(row, column, "Unmatched closing brace", {});
+ return;
+ }
+ saw_semicolon_for_this_value = false;
+ depth--;
+ delegate->EndNestedMessage();
+ continue;
+ }
+ if (!saw_semicolon_for_this_value && c == ';') {
+ saw_semicolon_for_this_value = true;
+ continue;
+ }
+ if (IsIdentifierStart(c)) {
+ saw_colon_for_this_key = false;
+ state = kReadingKey;
+ key.offset = i;
+ key.row = row;
+ key.column = column;
+ continue;
+ }
+ break;
+
+ case kReadingKey:
+ if (IsIdentifierBody(c))
+ continue;
+ key.txt = base::StringView(input.data() + key.offset, i - key.offset);
+ state = kWaitingForValue;
+ if (c == '#')
+ comment_till_eol = true;
+ continue;
+
+ case kWaitingForValue:
+ if (isspace(c))
+ continue;
+ if (c == '#') {
+ comment_till_eol = true;
+ continue;
+ }
+ value.offset = i;
+ value.row = row;
+ value.column = column;
+
+ if (c == ':' && !saw_colon_for_this_key) {
+ saw_colon_for_this_key = true;
+ continue;
+ }
+ if (c == '"') {
+ state = kReadingStringValue;
+ continue;
+ }
+ if (c == '-' || isdigit(c)) {
+ state = kReadingNumericValue;
+ continue;
+ }
+ if (IsIdentifierStart(c)) {
+ state = kReadingIdentifierValue;
+ continue;
+ }
+ if (c == '{') {
+ state = kWaitingForKey;
+ depth++;
+ value.txt = base::StringView(input.data() + value.offset, 1);
+ delegate->BeginNestedMessage(key, value);
+ continue;
+ }
+ break;
+
+ case kReadingNumericValue:
+ if (isspace(c) || c == ';' || last_character) {
+ size_t size = i - value.offset + (last_character ? 1 : 0);
+ value.txt = base::StringView(input.data() + value.offset, size);
+ saw_semicolon_for_this_value = c == ';';
+ state = kWaitingForKey;
+ delegate->NumericField(key, value);
+ continue;
+ }
+ if (isdigit(c))
+ continue;
+ break;
+
+ case kReadingStringValue:
+ if (c == '"') {
+ size_t size = i - value.offset - 1;
+ value.column++;
+ value.txt = base::StringView(input.data() + value.offset + 1, size);
+ saw_semicolon_for_this_value = false;
+ state = kWaitingForKey;
+ delegate->StringField(key, value);
+ continue;
+ }
+ continue;
+
+ case kReadingIdentifierValue:
+ if (isspace(c) || c == ';' || c == '#' || last_character) {
+ size_t size = i - value.offset + (last_character ? 1 : 0);
+ value.txt = base::StringView(input.data() + value.offset, size);
+ comment_till_eol = c == '#';
+ saw_semicolon_for_this_value = c == ';';
+ state = kWaitingForKey;
+ delegate->IdentifierField(key, value);
+ continue;
+ }
+ if (IsIdentifierBody(c)) {
+ continue;
+ }
+ break;
+ }
+ PERFETTO_FATAL("Unexpected char %c", c);
+ } // for
+ if (depth > 0)
+ delegate->AddError(row, column, "Nested message not closed", {});
+ if (state != kWaitingForKey)
+ delegate->AddError(row, column, "Unexpected end of input", {});
+ delegate->Eof();
+}
+
+void AddNestedDescriptors(
+ const std::string& prefix,
+ const DescriptorProto* descriptor,
+ std::map<std::string, const DescriptorProto*>* name_to_descriptor,
+ std::map<std::string, const EnumDescriptorProto*>* name_to_enum) {
+ for (const EnumDescriptorProto& enum_descriptor : descriptor->enum_type()) {
+ const std::string name = prefix + "." + enum_descriptor.name();
+ (*name_to_enum)[name] = &enum_descriptor;
+ }
+ for (const DescriptorProto& nested_descriptor : descriptor->nested_type()) {
+ const std::string name = prefix + "." + nested_descriptor.name();
+ (*name_to_descriptor)[name] = &nested_descriptor;
+ AddNestedDescriptors(name, &nested_descriptor, name_to_descriptor,
+ name_to_enum);
+ }
+}
+
+} // namespace
+
+ErrorReporter::ErrorReporter() = default;
+ErrorReporter::~ErrorReporter() = default;
+
+std::vector<uint8_t> PbtxtToPb(const std::string& input,
+ ErrorReporter* reporter) {
+ std::map<std::string, const DescriptorProto*> name_to_descriptor;
+ std::map<std::string, const EnumDescriptorProto*> name_to_enum;
+ FileDescriptorSet file_descriptor_set;
+
+ {
+ file_descriptor_set.ParseFromArray(
+ kPerfettoConfigDescriptor.data(),
+ static_cast<int>(kPerfettoConfigDescriptor.size()));
+ for (const auto& file_descriptor : file_descriptor_set.file()) {
+ for (const auto& enum_descriptor : file_descriptor.enum_type()) {
+ const std::string name =
+ "." + file_descriptor.package() + "." + enum_descriptor.name();
+ name_to_enum[name] = &enum_descriptor;
+ }
+ for (const auto& descriptor : file_descriptor.message_type()) {
+ const std::string name =
+ "." + file_descriptor.package() + "." + descriptor.name();
+ name_to_descriptor[name] = &descriptor;
+ AddNestedDescriptors(name, &descriptor, &name_to_descriptor,
+ &name_to_enum);
+ }
+ }
+ }
+
+ const DescriptorProto* descriptor = name_to_descriptor[kConfigProtoName];
+ PERFETTO_CHECK(descriptor);
+
+ ScatteredStreamMemoryDelegate stream_delegate(base::kPageSize);
+ protozero::ScatteredStreamWriter stream(&stream_delegate);
+ stream_delegate.set_writer(&stream);
+
+ protozero::Message message;
+ message.Reset(&stream);
+ ParserDelegate delegate(descriptor, &message, reporter,
+ std::move(name_to_descriptor),
+ std::move(name_to_enum));
+ Parse(input, &delegate);
+ return stream_delegate.StitchChunks();
+}
+
+} // namespace perfetto
diff --git a/src/perfetto_cmd/pbtxt_to_pb.h b/src/perfetto_cmd/pbtxt_to_pb.h
new file mode 100644
index 0000000..6b9db32
--- /dev/null
+++ b/src/perfetto_cmd/pbtxt_to_pb.h
@@ -0,0 +1,42 @@
+/*
+ * 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_PERFETTO_CMD_PBTXT_TO_PB_H_
+#define SRC_PERFETTO_CMD_PBTXT_TO_PB_H_
+
+#include <stdint.h>
+
+#include <string>
+#include <vector>
+
+namespace perfetto {
+
+class ErrorReporter {
+ public:
+ ErrorReporter();
+ virtual ~ErrorReporter();
+ virtual void AddError(size_t row,
+ size_t column,
+ size_t size,
+ const std::string& message) = 0;
+};
+
+std::vector<uint8_t> PbtxtToPb(const std::string& input,
+ ErrorReporter* reporter);
+
+} // namespace perfetto
+
+#endif // SRC_PERFETTO_CMD_PBTXT_TO_PB_H_
diff --git a/src/perfetto_cmd/pbtxt_to_pb_unittest.cc b/src/perfetto_cmd/pbtxt_to_pb_unittest.cc
new file mode 100644
index 0000000..00e2e3c
--- /dev/null
+++ b/src/perfetto_cmd/pbtxt_to_pb_unittest.cc
@@ -0,0 +1,444 @@
+/*
+ * 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/perfetto_cmd/pbtxt_to_pb.h"
+
+#include <memory>
+#include <string>
+
+#include "gmock/gmock.h"
+#include "gtest/gtest.h"
+
+#include "google/protobuf/io/zero_copy_stream_impl_lite.h"
+#include "perfetto/config/trace_config.pb.h"
+
+namespace perfetto {
+namespace {
+
+using ::testing::StrictMock;
+using ::testing::ElementsAre;
+using ::google::protobuf::io::ZeroCopyInputStream;
+using ::google::protobuf::io::ArrayInputStream;
+
+class MockErrorReporter : public ErrorReporter {
+ public:
+ MockErrorReporter() {}
+ ~MockErrorReporter() = default;
+ MOCK_METHOD4(AddError,
+ void(size_t line,
+ size_t column_start,
+ size_t column_end,
+ const std::string& message));
+};
+
+protos::TraceConfig ToProto(const std::string& input) {
+ StrictMock<MockErrorReporter> reporter;
+ std::vector<uint8_t> output = PbtxtToPb(input, &reporter);
+ EXPECT_FALSE(output.empty());
+ protos::TraceConfig config;
+ config.ParseFromArray(output.data(), static_cast<int>(output.size()));
+ return config;
+}
+
+void ToErrors(const std::string& input, MockErrorReporter* reporter) {
+ std::vector<uint8_t> output = PbtxtToPb(input, reporter);
+}
+
+TEST(PbtxtToPb, OneField) {
+ protos::TraceConfig config = ToProto(R"(
+ duration_ms: 1234
+ )");
+ EXPECT_EQ(config.duration_ms(), 1234);
+}
+
+TEST(PbtxtToPb, TwoFields) {
+ protos::TraceConfig config = ToProto(R"(
+ duration_ms: 1234
+ file_write_period_ms: 5678
+ )");
+ EXPECT_EQ(config.duration_ms(), 1234);
+ EXPECT_EQ(config.file_write_period_ms(), 5678);
+}
+
+TEST(PbtxtToPb, Semicolons) {
+ protos::TraceConfig config = ToProto(R"(
+ duration_ms: 1234;
+ file_write_period_ms: 5678;
+ )");
+ EXPECT_EQ(config.duration_ms(), 1234);
+ EXPECT_EQ(config.file_write_period_ms(), 5678);
+}
+
+TEST(PbtxtToPb, NestedMessage) {
+ protos::TraceConfig config = ToProto(R"(
+ buffers: {
+ size_kb: 123
+ }
+ )");
+ ASSERT_EQ(config.buffers().size(), 1);
+ EXPECT_EQ(config.buffers().Get(0).size_kb(), 123);
+}
+
+TEST(PbtxtToPb, SplitNested) {
+ protos::TraceConfig config = ToProto(R"(
+ buffers: {
+ size_kb: 1
+ }
+ duration_ms: 1000;
+ buffers: {
+ size_kb: 2
+ }
+ )");
+ ASSERT_EQ(config.buffers().size(), 2);
+ EXPECT_EQ(config.buffers().Get(0).size_kb(), 1);
+ EXPECT_EQ(config.buffers().Get(1).size_kb(), 2);
+ EXPECT_EQ(config.duration_ms(), 1000);
+}
+
+TEST(PbtxtToPb, MultipleNestedMessage) {
+ protos::TraceConfig config = ToProto(R"(
+ buffers: {
+ size_kb: 1
+ }
+ buffers: {
+ size_kb: 2
+ }
+ )");
+ ASSERT_EQ(config.buffers().size(), 2);
+ EXPECT_EQ(config.buffers().Get(0).size_kb(), 1);
+ EXPECT_EQ(config.buffers().Get(1).size_kb(), 2);
+}
+
+TEST(PbtxtToPb, NestedMessageCrossFile) {
+ protos::TraceConfig config = ToProto(R"(
+data_sources {
+ config {
+ ftrace_config {
+ drain_period_ms: 42
+ }
+ }
+}
+ )");
+ ASSERT_EQ(
+ config.data_sources().Get(0).config().ftrace_config().drain_period_ms(),
+ 42);
+}
+
+TEST(PbtxtToPb, Booleans) {
+ protos::TraceConfig config = ToProto(R"(
+ write_into_file: false; deferred_start: true;
+ )");
+ EXPECT_EQ(config.write_into_file(), false);
+ EXPECT_EQ(config.deferred_start(), true);
+}
+
+TEST(PbtxtToPb, Comments) {
+ protos::TraceConfig config = ToProto(R"(
+ write_into_file: false # deferred_start: true;
+ buffers# 1
+ # 2
+ :# 3
+ # 4
+ {# 5
+ # 6
+ fill_policy# 7
+ # 8
+ :# 9
+ # 10
+ RING_BUFFER# 11
+ # 12
+ ;# 13
+ # 14
+ } # 15
+ # 16
+ )");
+ EXPECT_EQ(config.write_into_file(), false);
+ EXPECT_EQ(config.deferred_start(), false);
+}
+
+TEST(PbtxtToPb, Enums) {
+ protos::TraceConfig config = ToProto(R"(
+ buffers: {
+ fill_policy: RING_BUFFER
+ }
+ )");
+ EXPECT_EQ(config.buffers().Get(0).fill_policy(),
+ protos::TraceConfig::BufferConfig::RING_BUFFER);
+}
+
+TEST(PbtxtToPb, AllFieldTypes) {
+ protos::TraceConfig config = ToProto(R"(
+data_sources {
+ config {
+ for_testing {
+ dummy_fields {
+ field_uint32: 1;
+ field_uint64: 2;
+ field_int32: 3;
+ field_int64: 4;
+ field_fixed64: 5;
+ field_sfixed64: 6;
+ field_fixed32: 7;
+ field_sfixed32: 8;
+ field_double: 9;
+ field_float: 10;
+ field_sint64: 11;
+ field_sint32: 12;
+ field_string: "13";
+ field_bytes: "14";
+ }
+ }
+ }
+}
+ )");
+ const auto& fields =
+ config.data_sources().Get(0).config().for_testing().dummy_fields();
+ ASSERT_EQ(fields.field_uint32(), 1);
+ ASSERT_EQ(fields.field_uint64(), 2);
+ ASSERT_EQ(fields.field_int32(), 3);
+ ASSERT_EQ(fields.field_int64(), 4);
+ ASSERT_EQ(fields.field_fixed64(), 5);
+ ASSERT_EQ(fields.field_sfixed64(), 6);
+ ASSERT_EQ(fields.field_fixed32(), 7);
+ ASSERT_EQ(fields.field_sfixed32(), 8);
+ ASSERT_EQ(fields.field_double(), 9);
+ ASSERT_EQ(fields.field_float(), 10);
+ ASSERT_EQ(fields.field_sint64(), 11);
+ ASSERT_EQ(fields.field_sint32(), 12);
+ ASSERT_EQ(fields.field_string(), "13");
+ ASSERT_EQ(fields.field_bytes(), "14");
+}
+
+TEST(PbtxtToPb, NegativeNumbers) {
+ protos::TraceConfig config = ToProto(R"(
+data_sources {
+ config {
+ for_testing {
+ dummy_fields {
+ field_int32: -1;
+ field_int64: -2;
+ field_fixed64: -3;
+ field_sfixed64: -4;
+ field_fixed32: -5;
+ field_sfixed32: -6;
+ field_double: -7;
+ field_float: -8;
+ field_sint64: -9;
+ field_sint32: -10;
+ }
+ }
+ }
+}
+ )");
+ const auto& fields =
+ config.data_sources().Get(0).config().for_testing().dummy_fields();
+ ASSERT_EQ(fields.field_int32(), -1);
+ ASSERT_EQ(fields.field_int64(), -2);
+ ASSERT_EQ(fields.field_fixed64(), -3);
+ ASSERT_EQ(fields.field_sfixed64(), -4);
+ ASSERT_EQ(fields.field_fixed32(), -5);
+ ASSERT_EQ(fields.field_sfixed32(), -6);
+ ASSERT_EQ(fields.field_double(), -7);
+ ASSERT_EQ(fields.field_float(), -8);
+ ASSERT_EQ(fields.field_sint64(), -9);
+ ASSERT_EQ(fields.field_sint32(), -10);
+}
+
+TEST(PbtxtToPb, EofEndsNumeric) {
+ protos::TraceConfig config = ToProto(R"(duration_ms: 1234)");
+ EXPECT_EQ(config.duration_ms(), 1234);
+}
+
+TEST(PbtxtToPb, EofEndsIdentifier) {
+ protos::TraceConfig config = ToProto(R"(enable_extra_guardrails: true)");
+ EXPECT_EQ(config.enable_extra_guardrails(), true);
+}
+
+TEST(PbtxtToPb, ExampleConfig) {
+ protos::TraceConfig config = ToProto(R"(
+buffers {
+ size_kb: 100024
+ fill_policy: RING_BUFFER
+}
+
+data_sources {
+ config {
+ name: "linux.ftrace"
+ target_buffer: 0
+ ftrace_config {
+ buffer_size_kb: 512 # 4 (page size) * 128
+ drain_period_ms: 200
+ ftrace_events: "binder_lock"
+ ftrace_events: "binder_locked"
+ atrace_categories: "gfx"
+ }
+ }
+}
+
+data_sources {
+ config {
+ name: "linux.process_stats"
+ target_buffer: 0
+ }
+}
+
+data_sources {
+ config {
+ name: "linux.inode_file_map"
+ target_buffer: 0
+ inode_file_config {
+ scan_delay_ms: 1000
+ scan_interval_ms: 1000
+ scan_batch_size: 500
+ mount_point_mapping: {
+ mountpoint: "/data"
+ scan_roots: "/data/app"
+ }
+ }
+ }
+}
+
+producers {
+ producer_name: "perfetto.traced_probes"
+ shm_size_kb: 4096
+ page_size_kb: 4
+}
+
+duration_ms: 10000
+)");
+ EXPECT_EQ(config.duration_ms(), 10000);
+ EXPECT_EQ(config.buffers().Get(0).size_kb(), 100024);
+ EXPECT_EQ(config.data_sources().Get(0).config().name(), "linux.ftrace");
+ EXPECT_EQ(config.data_sources().Get(0).config().target_buffer(), 0);
+ EXPECT_EQ(config.producers().Get(0).producer_name(),
+ "perfetto.traced_probes");
+}
+
+TEST(PbtxtToPb, UnknownField) {
+ MockErrorReporter reporter;
+ EXPECT_CALL(reporter,
+ AddError(2, 5, 11,
+ "No field named \"not_a_label\" in proto TraceConfig"));
+ ToErrors(R"(
+ not_a_label: false
+ )",
+ &reporter);
+}
+
+TEST(PbtxtToPb, UnknownNestedField) {
+ MockErrorReporter reporter;
+ EXPECT_CALL(
+ reporter,
+ AddError(
+ 4, 5, 16,
+ "No field named \"not_a_field_name\" in proto DataSourceConfig"));
+ ToErrors(R"(
+data_sources {
+ config {
+ not_a_field_name {
+ }
+ }
+}
+ )",
+ &reporter);
+}
+
+TEST(PbtxtToPb, BadBoolean) {
+ MockErrorReporter reporter;
+ EXPECT_CALL(reporter, AddError(2, 22, 3,
+ "Expected 'true' or 'false' for boolean field "
+ "write_into_file in proto TraceConfig instead "
+ "saw 'foo'"));
+ ToErrors(R"(
+ write_into_file: foo;
+ )",
+ &reporter);
+}
+
+TEST(PbtxtToPb, MissingBoolean) {
+ MockErrorReporter reporter;
+ EXPECT_CALL(reporter, AddError(3, 3, 0, "Unexpected end of input"));
+ ToErrors(R"(
+ write_into_file:
+ )",
+ &reporter);
+}
+
+TEST(PbtxtToPb, RootProtoMustNotEndWithBrace) {
+ MockErrorReporter reporter;
+ EXPECT_CALL(reporter, AddError(2, 5, 0, "Unmatched closing brace"));
+ ToErrors(R"(
+ }
+ )",
+ &reporter);
+}
+
+TEST(PbtxtToPb, SawNonRepeatedFieldTwice) {
+ MockErrorReporter reporter;
+ EXPECT_CALL(
+ reporter,
+ AddError(3, 5, 15,
+ "Saw non-repeating field 'write_into_file' more than once"));
+ ToErrors(R"(
+ write_into_file: true;
+ write_into_file: true;
+ )",
+ &reporter);
+}
+
+TEST(PbtxtToPb, WrongTypeBoolean) {
+ MockErrorReporter reporter;
+ EXPECT_CALL(reporter,
+ AddError(2, 18, 4,
+ "Expected value of type uint32 for field duration_ms in "
+ "proto TraceConfig instead saw 'true'"));
+ ToErrors(R"(
+ duration_ms: true;
+ )",
+ &reporter);
+}
+
+TEST(PbtxtToPb, WrongTypeNumber) {
+ MockErrorReporter reporter;
+ EXPECT_CALL(reporter,
+ AddError(2, 14, 3,
+ "Expected value of type message for field buffers in "
+ "proto TraceConfig instead saw '100'"));
+ ToErrors(R"(
+ buffers: 100;
+ )",
+ &reporter);
+}
+
+TEST(PbtxtToPb, NestedMessageDidNotTerminate) {
+ MockErrorReporter reporter;
+ EXPECT_CALL(reporter, AddError(2, 15, 0, "Nested message not closed"));
+ ToErrors(R"(
+ buffers: {)",
+ &reporter);
+}
+
+// TODO(hjd): Add these tests.
+// TEST(PbtxtToPb, WrongTypeString)
+// TEST(PbtxtToPb, OverflowOnIntegers)
+// TEST(PbtxtToPb, NegativeNumbersForUnsignedInt)
+// TEST(PbtxtToPb, UnterminatedString) {
+// TEST(PbtxtToPb, NumberIsEof)
+// TEST(PbtxtToPb, EscapedQuotes)
+// TEST(PbtxtToPb, OneOf)
+
+} // namespace
+} // namespace perfetto
diff --git a/src/perfetto_cmd/perfetto_cmd.cc b/src/perfetto_cmd/perfetto_cmd.cc
index 8c8f20e..54ab538 100644
--- a/src/perfetto_cmd/perfetto_cmd.cc
+++ b/src/perfetto_cmd/perfetto_cmd.cc
@@ -31,6 +31,7 @@
#include "perfetto/base/file_utils.h"
#include "perfetto/base/logging.h"
+#include "perfetto/base/string_view.h"
#include "perfetto/base/time.h"
#include "perfetto/base/utils.h"
#include "perfetto/protozero/proto_utils.h"
@@ -39,6 +40,7 @@
#include "perfetto/tracing/core/data_source_descriptor.h"
#include "perfetto/tracing/core/trace_config.h"
#include "perfetto/tracing/core/trace_packet.h"
+#include "src/perfetto_cmd/pbtxt_to_pb.h"
#include "perfetto/config/trace_config.pb.h"
@@ -59,6 +61,64 @@
perfetto::PerfettoCmd* g_consumer_cmd;
+class LoggingErrorReporter : public ErrorReporter {
+ public:
+ LoggingErrorReporter(std::string file_name, const char* config)
+ : file_name_(file_name), config_(config) {}
+
+ void AddError(size_t row,
+ size_t column,
+ size_t length,
+ const std::string& message) override {
+ parsed_successfully_ = false;
+ std::string line = ExtractLine(row - 1).ToStdString();
+ if (!line.empty() && line[line.length() - 1] == '\n') {
+ line.erase(line.length() - 1);
+ }
+
+ std::string guide(column + length, ' ');
+ for (size_t i = column; i < column + length; i++) {
+ guide[i - 1] = i == column ? '^' : '~';
+ }
+ fprintf(stderr, "%s:%zu:%zu error: %s\n", file_name_.c_str(), row, column,
+ message.c_str());
+ fprintf(stderr, "%s\n", line.c_str());
+ fprintf(stderr, "%s\n", guide.c_str());
+ }
+
+ bool Success() const { return parsed_successfully_; }
+
+ private:
+ base::StringView ExtractLine(size_t line) {
+ const char* start = config_;
+ const char* end = config_;
+
+ for (size_t i = 0; i < line + 1; i++) {
+ start = end;
+ char c;
+ while ((c = *end++) && c != '\n')
+ ;
+ }
+ return base::StringView(start, static_cast<size_t>(end - start));
+ }
+
+ bool parsed_successfully_ = true;
+ std::string file_name_;
+ const char* config_;
+};
+
+bool ParseTraceConfigPbtxt(const std::string& file_name,
+ const std::string& pbtxt,
+ protos::TraceConfig* config) {
+ LoggingErrorReporter reporter(file_name, pbtxt.c_str());
+ std::vector<uint8_t> buf = PbtxtToPb(pbtxt, &reporter);
+ if (!reporter.Success())
+ return false;
+ if (!config->ParseFromArray(buf.data(), static_cast<int>(buf.size())))
+ return false;
+ return true;
+}
+
} // namespace
// Temporary directory for DropBox traces. Note that this is automatically
@@ -77,6 +137,7 @@
--dropbox -d TAG : Upload trace into DropBox using tag TAG (default: %s)
--no-guardrails -n : Ignore guardrails triggered when using --dropbox (for testing).
--reset-guardrails : Resets the state of the guardails and exits (for testing).
+ --txt -t : Parse config as pbtxt. Not a stable API. Not for production use.
--help -h
statsd-specific flags:
@@ -103,6 +164,7 @@
{"background", no_argument, nullptr, 'b'},
{"dropbox", optional_argument, nullptr, 'd'},
{"no-guardrails", optional_argument, nullptr, 'n'},
+ {"txt", optional_argument, nullptr, 't'},
{"alert-id", required_argument, nullptr, OPT_ALERT_ID},
{"config-id", required_argument, nullptr, OPT_CONFIG_ID},
{"config-uid", required_argument, nullptr, OPT_CONFIG_UID},
@@ -110,20 +172,23 @@
{nullptr, 0, nullptr, 0}};
int option_index = 0;
+ std::string config_file_name;
std::string trace_config_raw;
bool background = false;
bool ignore_guardrails = false;
+ bool parse_as_pbtxt = false;
perfetto::protos::TraceConfig::StatsdMetadata statsd_metadata;
RateLimiter limiter;
for (;;) {
int option =
- getopt_long(argc, argv, "c:o:bd::n", long_options, &option_index);
+ getopt_long(argc, argv, "c:o:bd::nt", long_options, &option_index);
if (option == -1)
break; // EOF.
if (option == 'c') {
+ config_file_name = std::string(optarg);
if (strcmp(optarg, "-") == 0) {
std::istreambuf_iterator<char> begin(std::cin), end;
trace_config_raw.assign(begin, end);
@@ -173,6 +238,11 @@
continue;
}
+ if (option == 't') {
+ parse_as_pbtxt = true;
+ continue;
+ }
+
if (option == OPT_RESET_GUARDRAILS) {
PERFETTO_CHECK(limiter.ClearState());
PERFETTO_ILOG("Guardrail state cleared");
@@ -215,7 +285,14 @@
perfetto::protos::TraceConfig trace_config_proto;
PERFETTO_DLOG("Parsing TraceConfig, %zu bytes", trace_config_raw.size());
- bool parsed = trace_config_proto.ParseFromString(trace_config_raw);
+ bool parsed;
+ if (parse_as_pbtxt) {
+ parsed = ParseTraceConfigPbtxt(config_file_name, trace_config_raw,
+ &trace_config_proto);
+ } else {
+ parsed = trace_config_proto.ParseFromString(trace_config_raw);
+ }
+
if (!parsed) {
PERFETTO_ELOG("Could not parse TraceConfig proto");
return 1;
@@ -321,8 +398,15 @@
if (dropbox_tag_.empty()) {
trace_out_stream_.reset();
did_process_full_trace_ = true;
- PERFETTO_ILOG("Wrote %" PRIu64 " bytes into %s", bytes_written_,
- trace_out_path_ == "-" ? "stdout" : trace_out_path_.c_str());
+ if (trace_config_->write_into_file()) {
+ PERFETTO_ILOG("Streamed output to %s", trace_out_path_ == "-"
+ ? "stdout"
+ : trace_out_path_.c_str());
+ } else {
+ PERFETTO_ILOG(
+ "Wrote %" PRIu64 " bytes into %s", bytes_written_,
+ trace_out_path_ == "-" ? "stdout" : trace_out_path_.c_str());
+ }
} else {
#if PERFETTO_BUILDFLAG(PERFETTO_ANDROID_BUILD)
android::sp<android::os::DropBoxManager> dropbox =
diff --git a/src/perfetto_cmd/perfetto_config.descriptor.h b/src/perfetto_cmd/perfetto_config.descriptor.h
new file mode 100644
index 0000000..211e57c
--- /dev/null
+++ b/src/perfetto_cmd/perfetto_config.descriptor.h
@@ -0,0 +1,735 @@
+
+#ifndef SRC_PERFETTO_CMD_PERFETTO_CONFIG_DESCRIPTOR_H_
+#define SRC_PERFETTO_CMD_PERFETTO_CONFIG_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)
+// 39b24672017b75f5e5ac590c4dc03b2c41bf3eea
+// SHA1(protos/perfetto/config/perfetto_config.proto)
+// 5df0ef2a9ce882bdf0bda51d19c9fbd77fabc107
+
+// This is the proto {proto_name} encoded as a ProtoFileDescriptor to allow
+// for reflection without libprotobuf full/non-lite protos.
+
+namespace perfetto {
+
+constexpr std::array<uint8_t, 8501> kPerfettoConfigDescriptor{
+ {0x0a, 0xb2, 0x42, 0x0a, 0x25, 0x70, 0x65, 0x72, 0x66, 0x65, 0x74, 0x74,
+ 0x6f, 0x2f, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x2f, 0x70, 0x65, 0x72,
+ 0x66, 0x65, 0x74, 0x74, 0x6f, 0x5f, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67,
+ 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x0f, 0x70, 0x65, 0x72, 0x66,
+ 0x65, 0x74, 0x74, 0x6f, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x22,
+ 0x31, 0x0a, 0x0c, 0x43, 0x68, 0x72, 0x6f, 0x6d, 0x65, 0x43, 0x6f, 0x6e,
+ 0x66, 0x69, 0x67, 0x12, 0x21, 0x0a, 0x0c, 0x74, 0x72, 0x61, 0x63, 0x65,
+ 0x5f, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x18, 0x01, 0x20, 0x01, 0x28,
+ 0x09, 0x52, 0x0b, 0x74, 0x72, 0x61, 0x63, 0x65, 0x43, 0x6f, 0x6e, 0x66,
+ 0x69, 0x67, 0x22, 0xd1, 0x05, 0x0a, 0x10, 0x44, 0x61, 0x74, 0x61, 0x53,
+ 0x6f, 0x75, 0x72, 0x63, 0x65, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12,
+ 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28,
+ 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x23, 0x0a, 0x0d, 0x74,
+ 0x61, 0x72, 0x67, 0x65, 0x74, 0x5f, 0x62, 0x75, 0x66, 0x66, 0x65, 0x72,
+ 0x18, 0x02, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x0c, 0x74, 0x61, 0x72, 0x67,
+ 0x65, 0x74, 0x42, 0x75, 0x66, 0x66, 0x65, 0x72, 0x12, 0x2a, 0x0a, 0x11,
+ 0x74, 0x72, 0x61, 0x63, 0x65, 0x5f, 0x64, 0x75, 0x72, 0x61, 0x74, 0x69,
+ 0x6f, 0x6e, 0x5f, 0x6d, 0x73, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0d, 0x52,
+ 0x0f, 0x74, 0x72, 0x61, 0x63, 0x65, 0x44, 0x75, 0x72, 0x61, 0x74, 0x69,
+ 0x6f, 0x6e, 0x4d, 0x73, 0x12, 0x2c, 0x0a, 0x12, 0x74, 0x72, 0x61, 0x63,
+ 0x69, 0x6e, 0x67, 0x5f, 0x73, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x5f,
+ 0x69, 0x64, 0x18, 0x04, 0x20, 0x01, 0x28, 0x04, 0x52, 0x10, 0x74, 0x72,
+ 0x61, 0x63, 0x69, 0x6e, 0x67, 0x53, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e,
+ 0x49, 0x64, 0x12, 0x42, 0x0a, 0x0d, 0x66, 0x74, 0x72, 0x61, 0x63, 0x65,
+ 0x5f, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x18, 0x64, 0x20, 0x01, 0x28,
+ 0x0b, 0x32, 0x1d, 0x2e, 0x70, 0x65, 0x72, 0x66, 0x65, 0x74, 0x74, 0x6f,
+ 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2e, 0x46, 0x74, 0x72, 0x61,
+ 0x63, 0x65, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x52, 0x0c, 0x66, 0x74,
+ 0x72, 0x61, 0x63, 0x65, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x42,
+ 0x0a, 0x0d, 0x63, 0x68, 0x72, 0x6f, 0x6d, 0x65, 0x5f, 0x63, 0x6f, 0x6e,
+ 0x66, 0x69, 0x67, 0x18, 0x65, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1d, 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,
+ 0x6e, 0x66, 0x69, 0x67, 0x52, 0x0c, 0x63, 0x68, 0x72, 0x6f, 0x6d, 0x65,
+ 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x4c, 0x0a, 0x11, 0x69, 0x6e,
+ 0x6f, 0x64, 0x65, 0x5f, 0x66, 0x69, 0x6c, 0x65, 0x5f, 0x63, 0x6f, 0x6e,
+ 0x66, 0x69, 0x67, 0x18, 0x66, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x20, 0x2e,
+ 0x70, 0x65, 0x72, 0x66, 0x65, 0x74, 0x74, 0x6f, 0x2e, 0x70, 0x72, 0x6f,
+ 0x74, 0x6f, 0x73, 0x2e, 0x49, 0x6e, 0x6f, 0x64, 0x65, 0x46, 0x69, 0x6c,
+ 0x65, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x52, 0x0f, 0x69, 0x6e, 0x6f,
+ 0x64, 0x65, 0x46, 0x69, 0x6c, 0x65, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67,
+ 0x12, 0x55, 0x0a, 0x14, 0x70, 0x72, 0x6f, 0x63, 0x65, 0x73, 0x73, 0x5f,
+ 0x73, 0x74, 0x61, 0x74, 0x73, 0x5f, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67,
+ 0x18, 0x67, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x23, 0x2e, 0x70, 0x65, 0x72,
+ 0x66, 0x65, 0x74, 0x74, 0x6f, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73,
+ 0x2e, 0x50, 0x72, 0x6f, 0x63, 0x65, 0x73, 0x73, 0x53, 0x74, 0x61, 0x74,
+ 0x73, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x52, 0x12, 0x70, 0x72, 0x6f,
+ 0x63, 0x65, 0x73, 0x73, 0x53, 0x74, 0x61, 0x74, 0x73, 0x43, 0x6f, 0x6e,
+ 0x66, 0x69, 0x67, 0x12, 0x49, 0x0a, 0x10, 0x73, 0x79, 0x73, 0x5f, 0x73,
+ 0x74, 0x61, 0x74, 0x73, 0x5f, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x18,
+ 0x68, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1f, 0x2e, 0x70, 0x65, 0x72, 0x66,
+ 0x65, 0x74, 0x74, 0x6f, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2e,
+ 0x53, 0x79, 0x73, 0x53, 0x74, 0x61, 0x74, 0x73, 0x43, 0x6f, 0x6e, 0x66,
+ 0x69, 0x67, 0x52, 0x0e, 0x73, 0x79, 0x73, 0x53, 0x74, 0x61, 0x74, 0x73,
+ 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x4b, 0x0a, 0x10, 0x68, 0x65,
+ 0x61, 0x70, 0x70, 0x72, 0x6f, 0x66, 0x64, 0x5f, 0x63, 0x6f, 0x6e, 0x66,
+ 0x69, 0x67, 0x18, 0x69, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x20, 0x2e, 0x70,
+ 0x65, 0x72, 0x66, 0x65, 0x74, 0x74, 0x6f, 0x2e, 0x70, 0x72, 0x6f, 0x74,
+ 0x6f, 0x73, 0x2e, 0x48, 0x65, 0x61, 0x70, 0x70, 0x72, 0x6f, 0x66, 0x64,
+ 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x52, 0x0f, 0x68, 0x65, 0x61, 0x70,
+ 0x70, 0x72, 0x6f, 0x66, 0x64, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12,
+ 0x24, 0x0a, 0x0d, 0x6c, 0x65, 0x67, 0x61, 0x63, 0x79, 0x5f, 0x63, 0x6f,
+ 0x6e, 0x66, 0x69, 0x67, 0x18, 0xe8, 0x07, 0x20, 0x01, 0x28, 0x09, 0x52,
+ 0x0c, 0x6c, 0x65, 0x67, 0x61, 0x63, 0x79, 0x43, 0x6f, 0x6e, 0x66, 0x69,
+ 0x67, 0x12, 0x3f, 0x0a, 0x0b, 0x66, 0x6f, 0x72, 0x5f, 0x74, 0x65, 0x73,
+ 0x74, 0x69, 0x6e, 0x67, 0x18, 0xff, 0xff, 0xff, 0x7f, 0x20, 0x01, 0x28,
+ 0x0b, 0x32, 0x1b, 0x2e, 0x70, 0x65, 0x72, 0x66, 0x65, 0x74, 0x74, 0x6f,
+ 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2e, 0x54, 0x65, 0x73, 0x74,
+ 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x52, 0x0a, 0x66, 0x6f, 0x72, 0x54,
+ 0x65, 0x73, 0x74, 0x69, 0x6e, 0x67, 0x22, 0xcf, 0x01, 0x0a, 0x0c, 0x46,
+ 0x74, 0x72, 0x61, 0x63, 0x65, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12,
+ 0x23, 0x0a, 0x0d, 0x66, 0x74, 0x72, 0x61, 0x63, 0x65, 0x5f, 0x65, 0x76,
+ 0x65, 0x6e, 0x74, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x09, 0x52, 0x0c,
+ 0x66, 0x74, 0x72, 0x61, 0x63, 0x65, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x73,
+ 0x12, 0x2b, 0x0a, 0x11, 0x61, 0x74, 0x72, 0x61, 0x63, 0x65, 0x5f, 0x63,
+ 0x61, 0x74, 0x65, 0x67, 0x6f, 0x72, 0x69, 0x65, 0x73, 0x18, 0x02, 0x20,
+ 0x03, 0x28, 0x09, 0x52, 0x10, 0x61, 0x74, 0x72, 0x61, 0x63, 0x65, 0x43,
+ 0x61, 0x74, 0x65, 0x67, 0x6f, 0x72, 0x69, 0x65, 0x73, 0x12, 0x1f, 0x0a,
+ 0x0b, 0x61, 0x74, 0x72, 0x61, 0x63, 0x65, 0x5f, 0x61, 0x70, 0x70, 0x73,
+ 0x18, 0x03, 0x20, 0x03, 0x28, 0x09, 0x52, 0x0a, 0x61, 0x74, 0x72, 0x61,
+ 0x63, 0x65, 0x41, 0x70, 0x70, 0x73, 0x12, 0x24, 0x0a, 0x0e, 0x62, 0x75,
+ 0x66, 0x66, 0x65, 0x72, 0x5f, 0x73, 0x69, 0x7a, 0x65, 0x5f, 0x6b, 0x62,
+ 0x18, 0x0a, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x0c, 0x62, 0x75, 0x66, 0x66,
+ 0x65, 0x72, 0x53, 0x69, 0x7a, 0x65, 0x4b, 0x62, 0x12, 0x26, 0x0a, 0x0f,
+ 0x64, 0x72, 0x61, 0x69, 0x6e, 0x5f, 0x70, 0x65, 0x72, 0x69, 0x6f, 0x64,
+ 0x5f, 0x6d, 0x73, 0x18, 0x0b, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x0d, 0x64,
+ 0x72, 0x61, 0x69, 0x6e, 0x50, 0x65, 0x72, 0x69, 0x6f, 0x64, 0x4d, 0x73,
+ 0x22, 0x95, 0x03, 0x0a, 0x0f, 0x49, 0x6e, 0x6f, 0x64, 0x65, 0x46, 0x69,
+ 0x6c, 0x65, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x28, 0x0a, 0x10,
+ 0x73, 0x63, 0x61, 0x6e, 0x5f, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x76, 0x61,
+ 0x6c, 0x5f, 0x6d, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x0e,
+ 0x73, 0x63, 0x61, 0x6e, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x76, 0x61, 0x6c,
+ 0x4d, 0x73, 0x12, 0x22, 0x0a, 0x0d, 0x73, 0x63, 0x61, 0x6e, 0x5f, 0x64,
+ 0x65, 0x6c, 0x61, 0x79, 0x5f, 0x6d, 0x73, 0x18, 0x02, 0x20, 0x01, 0x28,
+ 0x0d, 0x52, 0x0b, 0x73, 0x63, 0x61, 0x6e, 0x44, 0x65, 0x6c, 0x61, 0x79,
+ 0x4d, 0x73, 0x12, 0x26, 0x0a, 0x0f, 0x73, 0x63, 0x61, 0x6e, 0x5f, 0x62,
+ 0x61, 0x74, 0x63, 0x68, 0x5f, 0x73, 0x69, 0x7a, 0x65, 0x18, 0x03, 0x20,
+ 0x01, 0x28, 0x0d, 0x52, 0x0d, 0x73, 0x63, 0x61, 0x6e, 0x42, 0x61, 0x74,
+ 0x63, 0x68, 0x53, 0x69, 0x7a, 0x65, 0x12, 0x1e, 0x0a, 0x0b, 0x64, 0x6f,
+ 0x5f, 0x6e, 0x6f, 0x74, 0x5f, 0x73, 0x63, 0x61, 0x6e, 0x18, 0x04, 0x20,
+ 0x01, 0x28, 0x08, 0x52, 0x09, 0x64, 0x6f, 0x4e, 0x6f, 0x74, 0x53, 0x63,
+ 0x61, 0x6e, 0x12, 0x2a, 0x0a, 0x11, 0x73, 0x63, 0x61, 0x6e, 0x5f, 0x6d,
+ 0x6f, 0x75, 0x6e, 0x74, 0x5f, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x73, 0x18,
+ 0x05, 0x20, 0x03, 0x28, 0x09, 0x52, 0x0f, 0x73, 0x63, 0x61, 0x6e, 0x4d,
+ 0x6f, 0x75, 0x6e, 0x74, 0x50, 0x6f, 0x69, 0x6e, 0x74, 0x73, 0x12, 0x67,
+ 0x0a, 0x13, 0x6d, 0x6f, 0x75, 0x6e, 0x74, 0x5f, 0x70, 0x6f, 0x69, 0x6e,
+ 0x74, 0x5f, 0x6d, 0x61, 0x70, 0x70, 0x69, 0x6e, 0x67, 0x18, 0x06, 0x20,
+ 0x03, 0x28, 0x0b, 0x32, 0x37, 0x2e, 0x70, 0x65, 0x72, 0x66, 0x65, 0x74,
+ 0x74, 0x6f, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2e, 0x49, 0x6e,
+ 0x6f, 0x64, 0x65, 0x46, 0x69, 0x6c, 0x65, 0x43, 0x6f, 0x6e, 0x66, 0x69,
+ 0x67, 0x2e, 0x4d, 0x6f, 0x75, 0x6e, 0x74, 0x50, 0x6f, 0x69, 0x6e, 0x74,
+ 0x4d, 0x61, 0x70, 0x70, 0x69, 0x6e, 0x67, 0x45, 0x6e, 0x74, 0x72, 0x79,
+ 0x52, 0x11, 0x6d, 0x6f, 0x75, 0x6e, 0x74, 0x50, 0x6f, 0x69, 0x6e, 0x74,
+ 0x4d, 0x61, 0x70, 0x70, 0x69, 0x6e, 0x67, 0x1a, 0x57, 0x0a, 0x16, 0x4d,
+ 0x6f, 0x75, 0x6e, 0x74, 0x50, 0x6f, 0x69, 0x6e, 0x74, 0x4d, 0x61, 0x70,
+ 0x70, 0x69, 0x6e, 0x67, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x1e, 0x0a,
+ 0x0a, 0x6d, 0x6f, 0x75, 0x6e, 0x74, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x18,
+ 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, 0x6d, 0x6f, 0x75, 0x6e, 0x74,
+ 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x12, 0x1d, 0x0a, 0x0a, 0x73, 0x63, 0x61,
+ 0x6e, 0x5f, 0x72, 0x6f, 0x6f, 0x74, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28,
+ 0x09, 0x52, 0x09, 0x73, 0x63, 0x61, 0x6e, 0x52, 0x6f, 0x6f, 0x74, 0x73,
+ 0x22, 0xca, 0x02, 0x0a, 0x12, 0x50, 0x72, 0x6f, 0x63, 0x65, 0x73, 0x73,
+ 0x53, 0x74, 0x61, 0x74, 0x73, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12,
+ 0x42, 0x0a, 0x06, 0x71, 0x75, 0x69, 0x72, 0x6b, 0x73, 0x18, 0x01, 0x20,
+ 0x03, 0x28, 0x0e, 0x32, 0x2a, 0x2e, 0x70, 0x65, 0x72, 0x66, 0x65, 0x74,
+ 0x74, 0x6f, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2e, 0x50, 0x72,
+ 0x6f, 0x63, 0x65, 0x73, 0x73, 0x53, 0x74, 0x61, 0x74, 0x73, 0x43, 0x6f,
+ 0x6e, 0x66, 0x69, 0x67, 0x2e, 0x51, 0x75, 0x69, 0x72, 0x6b, 0x73, 0x52,
+ 0x06, 0x71, 0x75, 0x69, 0x72, 0x6b, 0x73, 0x12, 0x3c, 0x0a, 0x1b, 0x73,
+ 0x63, 0x61, 0x6e, 0x5f, 0x61, 0x6c, 0x6c, 0x5f, 0x70, 0x72, 0x6f, 0x63,
+ 0x65, 0x73, 0x73, 0x65, 0x73, 0x5f, 0x6f, 0x6e, 0x5f, 0x73, 0x74, 0x61,
+ 0x72, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x08, 0x52, 0x17, 0x73, 0x63,
+ 0x61, 0x6e, 0x41, 0x6c, 0x6c, 0x50, 0x72, 0x6f, 0x63, 0x65, 0x73, 0x73,
+ 0x65, 0x73, 0x4f, 0x6e, 0x53, 0x74, 0x61, 0x72, 0x74, 0x12, 0x2e, 0x0a,
+ 0x13, 0x72, 0x65, 0x63, 0x6f, 0x72, 0x64, 0x5f, 0x74, 0x68, 0x72, 0x65,
+ 0x61, 0x64, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x73, 0x18, 0x03, 0x20, 0x01,
+ 0x28, 0x08, 0x52, 0x11, 0x72, 0x65, 0x63, 0x6f, 0x72, 0x64, 0x54, 0x68,
+ 0x72, 0x65, 0x61, 0x64, 0x4e, 0x61, 0x6d, 0x65, 0x73, 0x12, 0x2b, 0x0a,
+ 0x12, 0x70, 0x72, 0x6f, 0x63, 0x5f, 0x73, 0x74, 0x61, 0x74, 0x73, 0x5f,
+ 0x70, 0x6f, 0x6c, 0x6c, 0x5f, 0x6d, 0x73, 0x18, 0x04, 0x20, 0x01, 0x28,
+ 0x0d, 0x52, 0x0f, 0x70, 0x72, 0x6f, 0x63, 0x53, 0x74, 0x61, 0x74, 0x73,
+ 0x50, 0x6f, 0x6c, 0x6c, 0x4d, 0x73, 0x22, 0x55, 0x0a, 0x06, 0x51, 0x75,
+ 0x69, 0x72, 0x6b, 0x73, 0x12, 0x16, 0x0a, 0x12, 0x51, 0x55, 0x49, 0x52,
+ 0x4b, 0x53, 0x5f, 0x55, 0x4e, 0x53, 0x50, 0x45, 0x43, 0x49, 0x46, 0x49,
+ 0x45, 0x44, 0x10, 0x00, 0x12, 0x1c, 0x0a, 0x14, 0x44, 0x49, 0x53, 0x41,
+ 0x42, 0x4c, 0x45, 0x5f, 0x49, 0x4e, 0x49, 0x54, 0x49, 0x41, 0x4c, 0x5f,
+ 0x44, 0x55, 0x4d, 0x50, 0x10, 0x01, 0x1a, 0x02, 0x08, 0x01, 0x12, 0x15,
+ 0x0a, 0x11, 0x44, 0x49, 0x53, 0x41, 0x42, 0x4c, 0x45, 0x5f, 0x4f, 0x4e,
+ 0x5f, 0x44, 0x45, 0x4d, 0x41, 0x4e, 0x44, 0x10, 0x02, 0x22, 0xf3, 0x03,
+ 0x0a, 0x0e, 0x53, 0x79, 0x73, 0x53, 0x74, 0x61, 0x74, 0x73, 0x43, 0x6f,
+ 0x6e, 0x66, 0x69, 0x67, 0x12, 0x2a, 0x0a, 0x11, 0x6d, 0x65, 0x6d, 0x69,
+ 0x6e, 0x66, 0x6f, 0x5f, 0x70, 0x65, 0x72, 0x69, 0x6f, 0x64, 0x5f, 0x6d,
+ 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x0f, 0x6d, 0x65, 0x6d,
+ 0x69, 0x6e, 0x66, 0x6f, 0x50, 0x65, 0x72, 0x69, 0x6f, 0x64, 0x4d, 0x73,
+ 0x12, 0x4b, 0x0a, 0x10, 0x6d, 0x65, 0x6d, 0x69, 0x6e, 0x66, 0x6f, 0x5f,
+ 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x65, 0x72, 0x73, 0x18, 0x02, 0x20, 0x03,
+ 0x28, 0x0e, 0x32, 0x20, 0x2e, 0x70, 0x65, 0x72, 0x66, 0x65, 0x74, 0x74,
+ 0x6f, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2e, 0x4d, 0x65, 0x6d,
+ 0x69, 0x6e, 0x66, 0x6f, 0x43, 0x6f, 0x75, 0x6e, 0x74, 0x65, 0x72, 0x73,
+ 0x52, 0x0f, 0x6d, 0x65, 0x6d, 0x69, 0x6e, 0x66, 0x6f, 0x43, 0x6f, 0x75,
+ 0x6e, 0x74, 0x65, 0x72, 0x73, 0x12, 0x28, 0x0a, 0x10, 0x76, 0x6d, 0x73,
+ 0x74, 0x61, 0x74, 0x5f, 0x70, 0x65, 0x72, 0x69, 0x6f, 0x64, 0x5f, 0x6d,
+ 0x73, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x0e, 0x76, 0x6d, 0x73,
+ 0x74, 0x61, 0x74, 0x50, 0x65, 0x72, 0x69, 0x6f, 0x64, 0x4d, 0x73, 0x12,
+ 0x48, 0x0a, 0x0f, 0x76, 0x6d, 0x73, 0x74, 0x61, 0x74, 0x5f, 0x63, 0x6f,
+ 0x75, 0x6e, 0x74, 0x65, 0x72, 0x73, 0x18, 0x04, 0x20, 0x03, 0x28, 0x0e,
+ 0x32, 0x1f, 0x2e, 0x70, 0x65, 0x72, 0x66, 0x65, 0x74, 0x74, 0x6f, 0x2e,
+ 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2e, 0x56, 0x6d, 0x73, 0x74, 0x61,
+ 0x74, 0x43, 0x6f, 0x75, 0x6e, 0x74, 0x65, 0x72, 0x73, 0x52, 0x0e, 0x76,
+ 0x6d, 0x73, 0x74, 0x61, 0x74, 0x43, 0x6f, 0x75, 0x6e, 0x74, 0x65, 0x72,
+ 0x73, 0x12, 0x24, 0x0a, 0x0e, 0x73, 0x74, 0x61, 0x74, 0x5f, 0x70, 0x65,
+ 0x72, 0x69, 0x6f, 0x64, 0x5f, 0x6d, 0x73, 0x18, 0x05, 0x20, 0x01, 0x28,
+ 0x0d, 0x52, 0x0c, 0x73, 0x74, 0x61, 0x74, 0x50, 0x65, 0x72, 0x69, 0x6f,
+ 0x64, 0x4d, 0x73, 0x12, 0x51, 0x0a, 0x0d, 0x73, 0x74, 0x61, 0x74, 0x5f,
+ 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x65, 0x72, 0x73, 0x18, 0x06, 0x20, 0x03,
+ 0x28, 0x0e, 0x32, 0x2c, 0x2e, 0x70, 0x65, 0x72, 0x66, 0x65, 0x74, 0x74,
+ 0x6f, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2e, 0x53, 0x79, 0x73,
+ 0x53, 0x74, 0x61, 0x74, 0x73, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x2e,
+ 0x53, 0x74, 0x61, 0x74, 0x43, 0x6f, 0x75, 0x6e, 0x74, 0x65, 0x72, 0x73,
+ 0x52, 0x0c, 0x73, 0x74, 0x61, 0x74, 0x43, 0x6f, 0x75, 0x6e, 0x74, 0x65,
+ 0x72, 0x73, 0x22, 0x7b, 0x0a, 0x0c, 0x53, 0x74, 0x61, 0x74, 0x43, 0x6f,
+ 0x75, 0x6e, 0x74, 0x65, 0x72, 0x73, 0x12, 0x14, 0x0a, 0x10, 0x53, 0x54,
+ 0x41, 0x54, 0x5f, 0x55, 0x4e, 0x53, 0x50, 0x45, 0x43, 0x49, 0x46, 0x49,
+ 0x45, 0x44, 0x10, 0x00, 0x12, 0x12, 0x0a, 0x0e, 0x53, 0x54, 0x41, 0x54,
+ 0x5f, 0x43, 0x50, 0x55, 0x5f, 0x54, 0x49, 0x4d, 0x45, 0x53, 0x10, 0x01,
+ 0x12, 0x13, 0x0a, 0x0f, 0x53, 0x54, 0x41, 0x54, 0x5f, 0x49, 0x52, 0x51,
+ 0x5f, 0x43, 0x4f, 0x55, 0x4e, 0x54, 0x53, 0x10, 0x02, 0x12, 0x17, 0x0a,
+ 0x13, 0x53, 0x54, 0x41, 0x54, 0x5f, 0x53, 0x4f, 0x46, 0x54, 0x49, 0x52,
+ 0x51, 0x5f, 0x43, 0x4f, 0x55, 0x4e, 0x54, 0x53, 0x10, 0x03, 0x12, 0x13,
+ 0x0a, 0x0f, 0x53, 0x54, 0x41, 0x54, 0x5f, 0x46, 0x4f, 0x52, 0x4b, 0x5f,
+ 0x43, 0x4f, 0x55, 0x4e, 0x54, 0x10, 0x04, 0x22, 0x9e, 0x06, 0x0a, 0x0a,
+ 0x54, 0x65, 0x73, 0x74, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x23,
+ 0x0a, 0x0d, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x5f, 0x63, 0x6f,
+ 0x75, 0x6e, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x0c, 0x6d,
+ 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x43, 0x6f, 0x75, 0x6e, 0x74, 0x12,
+ 0x35, 0x0a, 0x17, 0x6d, 0x61, 0x78, 0x5f, 0x6d, 0x65, 0x73, 0x73, 0x61,
+ 0x67, 0x65, 0x73, 0x5f, 0x70, 0x65, 0x72, 0x5f, 0x73, 0x65, 0x63, 0x6f,
+ 0x6e, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x14, 0x6d, 0x61,
+ 0x78, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x73, 0x50, 0x65, 0x72,
+ 0x53, 0x65, 0x63, 0x6f, 0x6e, 0x64, 0x12, 0x12, 0x0a, 0x04, 0x73, 0x65,
+ 0x65, 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x04, 0x73, 0x65,
+ 0x65, 0x64, 0x12, 0x21, 0x0a, 0x0c, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67,
+ 0x65, 0x5f, 0x73, 0x69, 0x7a, 0x65, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0d,
+ 0x52, 0x0b, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x53, 0x69, 0x7a,
+ 0x65, 0x12, 0x33, 0x0a, 0x16, 0x73, 0x65, 0x6e, 0x64, 0x5f, 0x62, 0x61,
+ 0x74, 0x63, 0x68, 0x5f, 0x6f, 0x6e, 0x5f, 0x72, 0x65, 0x67, 0x69, 0x73,
+ 0x74, 0x65, 0x72, 0x18, 0x05, 0x20, 0x01, 0x28, 0x08, 0x52, 0x13, 0x73,
+ 0x65, 0x6e, 0x64, 0x42, 0x61, 0x74, 0x63, 0x68, 0x4f, 0x6e, 0x52, 0x65,
+ 0x67, 0x69, 0x73, 0x74, 0x65, 0x72, 0x12, 0x4a, 0x0a, 0x0c, 0x64, 0x75,
+ 0x6d, 0x6d, 0x79, 0x5f, 0x66, 0x69, 0x65, 0x6c, 0x64, 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, 0x54,
+ 0x65, 0x73, 0x74, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x2e, 0x44, 0x75,
+ 0x6d, 0x6d, 0x79, 0x46, 0x69, 0x65, 0x6c, 0x64, 0x73, 0x52, 0x0b, 0x64,
+ 0x75, 0x6d, 0x6d, 0x79, 0x46, 0x69, 0x65, 0x6c, 0x64, 0x73, 0x1a, 0xfb,
+ 0x03, 0x0a, 0x0b, 0x44, 0x75, 0x6d, 0x6d, 0x79, 0x46, 0x69, 0x65, 0x6c,
+ 0x64, 0x73, 0x12, 0x21, 0x0a, 0x0c, 0x66, 0x69, 0x65, 0x6c, 0x64, 0x5f,
+ 0x75, 0x69, 0x6e, 0x74, 0x33, 0x32, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0d,
+ 0x52, 0x0b, 0x66, 0x69, 0x65, 0x6c, 0x64, 0x55, 0x69, 0x6e, 0x74, 0x33,
+ 0x32, 0x12, 0x1f, 0x0a, 0x0b, 0x66, 0x69, 0x65, 0x6c, 0x64, 0x5f, 0x69,
+ 0x6e, 0x74, 0x33, 0x32, 0x18, 0x02, 0x20, 0x01, 0x28, 0x05, 0x52, 0x0a,
+ 0x66, 0x69, 0x65, 0x6c, 0x64, 0x49, 0x6e, 0x74, 0x33, 0x32, 0x12, 0x21,
+ 0x0a, 0x0c, 0x66, 0x69, 0x65, 0x6c, 0x64, 0x5f, 0x75, 0x69, 0x6e, 0x74,
+ 0x36, 0x34, 0x18, 0x03, 0x20, 0x01, 0x28, 0x04, 0x52, 0x0b, 0x66, 0x69,
+ 0x65, 0x6c, 0x64, 0x55, 0x69, 0x6e, 0x74, 0x36, 0x34, 0x12, 0x1f, 0x0a,
+ 0x0b, 0x66, 0x69, 0x65, 0x6c, 0x64, 0x5f, 0x69, 0x6e, 0x74, 0x36, 0x34,
+ 0x18, 0x04, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0a, 0x66, 0x69, 0x65, 0x6c,
+ 0x64, 0x49, 0x6e, 0x74, 0x36, 0x34, 0x12, 0x23, 0x0a, 0x0d, 0x66, 0x69,
+ 0x65, 0x6c, 0x64, 0x5f, 0x66, 0x69, 0x78, 0x65, 0x64, 0x36, 0x34, 0x18,
+ 0x05, 0x20, 0x01, 0x28, 0x06, 0x52, 0x0c, 0x66, 0x69, 0x65, 0x6c, 0x64,
+ 0x46, 0x69, 0x78, 0x65, 0x64, 0x36, 0x34, 0x12, 0x25, 0x0a, 0x0e, 0x66,
+ 0x69, 0x65, 0x6c, 0x64, 0x5f, 0x73, 0x66, 0x69, 0x78, 0x65, 0x64, 0x36,
+ 0x34, 0x18, 0x06, 0x20, 0x01, 0x28, 0x10, 0x52, 0x0d, 0x66, 0x69, 0x65,
+ 0x6c, 0x64, 0x53, 0x66, 0x69, 0x78, 0x65, 0x64, 0x36, 0x34, 0x12, 0x23,
+ 0x0a, 0x0d, 0x66, 0x69, 0x65, 0x6c, 0x64, 0x5f, 0x66, 0x69, 0x78, 0x65,
+ 0x64, 0x33, 0x32, 0x18, 0x07, 0x20, 0x01, 0x28, 0x07, 0x52, 0x0c, 0x66,
+ 0x69, 0x65, 0x6c, 0x64, 0x46, 0x69, 0x78, 0x65, 0x64, 0x33, 0x32, 0x12,
+ 0x25, 0x0a, 0x0e, 0x66, 0x69, 0x65, 0x6c, 0x64, 0x5f, 0x73, 0x66, 0x69,
+ 0x78, 0x65, 0x64, 0x33, 0x32, 0x18, 0x08, 0x20, 0x01, 0x28, 0x0f, 0x52,
+ 0x0d, 0x66, 0x69, 0x65, 0x6c, 0x64, 0x53, 0x66, 0x69, 0x78, 0x65, 0x64,
+ 0x33, 0x32, 0x12, 0x21, 0x0a, 0x0c, 0x66, 0x69, 0x65, 0x6c, 0x64, 0x5f,
+ 0x64, 0x6f, 0x75, 0x62, 0x6c, 0x65, 0x18, 0x09, 0x20, 0x01, 0x28, 0x01,
+ 0x52, 0x0b, 0x66, 0x69, 0x65, 0x6c, 0x64, 0x44, 0x6f, 0x75, 0x62, 0x6c,
+ 0x65, 0x12, 0x1f, 0x0a, 0x0b, 0x66, 0x69, 0x65, 0x6c, 0x64, 0x5f, 0x66,
+ 0x6c, 0x6f, 0x61, 0x74, 0x18, 0x0a, 0x20, 0x01, 0x28, 0x02, 0x52, 0x0a,
+ 0x66, 0x69, 0x65, 0x6c, 0x64, 0x46, 0x6c, 0x6f, 0x61, 0x74, 0x12, 0x21,
+ 0x0a, 0x0c, 0x66, 0x69, 0x65, 0x6c, 0x64, 0x5f, 0x73, 0x69, 0x6e, 0x74,
+ 0x36, 0x34, 0x18, 0x0b, 0x20, 0x01, 0x28, 0x12, 0x52, 0x0b, 0x66, 0x69,
+ 0x65, 0x6c, 0x64, 0x53, 0x69, 0x6e, 0x74, 0x36, 0x34, 0x12, 0x21, 0x0a,
+ 0x0c, 0x66, 0x69, 0x65, 0x6c, 0x64, 0x5f, 0x73, 0x69, 0x6e, 0x74, 0x33,
+ 0x32, 0x18, 0x0c, 0x20, 0x01, 0x28, 0x11, 0x52, 0x0b, 0x66, 0x69, 0x65,
+ 0x6c, 0x64, 0x53, 0x69, 0x6e, 0x74, 0x33, 0x32, 0x12, 0x21, 0x0a, 0x0c,
+ 0x66, 0x69, 0x65, 0x6c, 0x64, 0x5f, 0x73, 0x74, 0x72, 0x69, 0x6e, 0x67,
+ 0x18, 0x0d, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x66, 0x69, 0x65, 0x6c,
+ 0x64, 0x53, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x12, 0x1f, 0x0a, 0x0b, 0x66,
+ 0x69, 0x65, 0x6c, 0x64, 0x5f, 0x62, 0x79, 0x74, 0x65, 0x73, 0x18, 0x0e,
+ 0x20, 0x01, 0x28, 0x0c, 0x52, 0x0a, 0x66, 0x69, 0x65, 0x6c, 0x64, 0x42,
+ 0x79, 0x74, 0x65, 0x73, 0x22, 0x81, 0x0c, 0x0a, 0x0b, 0x54, 0x72, 0x61,
+ 0x63, 0x65, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x43, 0x0a, 0x07,
+ 0x62, 0x75, 0x66, 0x66, 0x65, 0x72, 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, 0x54, 0x72, 0x61, 0x63,
+ 0x65, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x2e, 0x42, 0x75, 0x66, 0x66,
+ 0x65, 0x72, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x52, 0x07, 0x62, 0x75,
+ 0x66, 0x66, 0x65, 0x72, 0x73, 0x12, 0x4a, 0x0a, 0x0c, 0x64, 0x61, 0x74,
+ 0x61, 0x5f, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x73, 0x18, 0x02, 0x20,
+ 0x03, 0x28, 0x0b, 0x32, 0x27, 0x2e, 0x70, 0x65, 0x72, 0x66, 0x65, 0x74,
+ 0x74, 0x6f, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2e, 0x54, 0x72,
+ 0x61, 0x63, 0x65, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x2e, 0x44, 0x61,
+ 0x74, 0x61, 0x53, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x52, 0x0b, 0x64, 0x61,
+ 0x74, 0x61, 0x53, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x73, 0x12, 0x1f, 0x0a,
+ 0x0b, 0x64, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x6d, 0x73,
+ 0x18, 0x03, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x0a, 0x64, 0x75, 0x72, 0x61,
+ 0x74, 0x69, 0x6f, 0x6e, 0x4d, 0x73, 0x12, 0x36, 0x0a, 0x17, 0x65, 0x6e,
+ 0x61, 0x62, 0x6c, 0x65, 0x5f, 0x65, 0x78, 0x74, 0x72, 0x61, 0x5f, 0x67,
+ 0x75, 0x61, 0x72, 0x64, 0x72, 0x61, 0x69, 0x6c, 0x73, 0x18, 0x04, 0x20,
+ 0x01, 0x28, 0x08, 0x52, 0x15, 0x65, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x45,
+ 0x78, 0x74, 0x72, 0x61, 0x47, 0x75, 0x61, 0x72, 0x64, 0x72, 0x61, 0x69,
+ 0x6c, 0x73, 0x12, 0x57, 0x0a, 0x0d, 0x6c, 0x6f, 0x63, 0x6b, 0x64, 0x6f,
+ 0x77, 0x6e, 0x5f, 0x6d, 0x6f, 0x64, 0x65, 0x18, 0x05, 0x20, 0x01, 0x28,
+ 0x0e, 0x32, 0x32, 0x2e, 0x70, 0x65, 0x72, 0x66, 0x65, 0x74, 0x74, 0x6f,
+ 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2e, 0x54, 0x72, 0x61, 0x63,
+ 0x65, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x2e, 0x4c, 0x6f, 0x63, 0x6b,
+ 0x64, 0x6f, 0x77, 0x6e, 0x4d, 0x6f, 0x64, 0x65, 0x4f, 0x70, 0x65, 0x72,
+ 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x0c, 0x6c, 0x6f, 0x63, 0x6b, 0x64,
+ 0x6f, 0x77, 0x6e, 0x4d, 0x6f, 0x64, 0x65, 0x12, 0x49, 0x0a, 0x09, 0x70,
+ 0x72, 0x6f, 0x64, 0x75, 0x63, 0x65, 0x72, 0x73, 0x18, 0x06, 0x20, 0x03,
+ 0x28, 0x0b, 0x32, 0x2b, 0x2e, 0x70, 0x65, 0x72, 0x66, 0x65, 0x74, 0x74,
+ 0x6f, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2e, 0x54, 0x72, 0x61,
+ 0x63, 0x65, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x2e, 0x50, 0x72, 0x6f,
+ 0x64, 0x75, 0x63, 0x65, 0x72, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x52,
+ 0x09, 0x70, 0x72, 0x6f, 0x64, 0x75, 0x63, 0x65, 0x72, 0x73, 0x12, 0x54,
+ 0x0a, 0x0f, 0x73, 0x74, 0x61, 0x74, 0x73, 0x64, 0x5f, 0x6d, 0x65, 0x74,
+ 0x61, 0x64, 0x61, 0x74, 0x61, 0x18, 0x07, 0x20, 0x01, 0x28, 0x0b, 0x32,
+ 0x2b, 0x2e, 0x70, 0x65, 0x72, 0x66, 0x65, 0x74, 0x74, 0x6f, 0x2e, 0x70,
+ 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2e, 0x54, 0x72, 0x61, 0x63, 0x65, 0x43,
+ 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x2e, 0x53, 0x74, 0x61, 0x74, 0x73, 0x64,
+ 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x52, 0x0e, 0x73, 0x74,
+ 0x61, 0x74, 0x73, 0x64, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61,
+ 0x12, 0x26, 0x0a, 0x0f, 0x77, 0x72, 0x69, 0x74, 0x65, 0x5f, 0x69, 0x6e,
+ 0x74, 0x6f, 0x5f, 0x66, 0x69, 0x6c, 0x65, 0x18, 0x08, 0x20, 0x01, 0x28,
+ 0x08, 0x52, 0x0d, 0x77, 0x72, 0x69, 0x74, 0x65, 0x49, 0x6e, 0x74, 0x6f,
+ 0x46, 0x69, 0x6c, 0x65, 0x12, 0x2f, 0x0a, 0x14, 0x66, 0x69, 0x6c, 0x65,
+ 0x5f, 0x77, 0x72, 0x69, 0x74, 0x65, 0x5f, 0x70, 0x65, 0x72, 0x69, 0x6f,
+ 0x64, 0x5f, 0x6d, 0x73, 0x18, 0x09, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x11,
+ 0x66, 0x69, 0x6c, 0x65, 0x57, 0x72, 0x69, 0x74, 0x65, 0x50, 0x65, 0x72,
+ 0x69, 0x6f, 0x64, 0x4d, 0x73, 0x12, 0x2d, 0x0a, 0x13, 0x6d, 0x61, 0x78,
+ 0x5f, 0x66, 0x69, 0x6c, 0x65, 0x5f, 0x73, 0x69, 0x7a, 0x65, 0x5f, 0x62,
+ 0x79, 0x74, 0x65, 0x73, 0x18, 0x0a, 0x20, 0x01, 0x28, 0x04, 0x52, 0x10,
+ 0x6d, 0x61, 0x78, 0x46, 0x69, 0x6c, 0x65, 0x53, 0x69, 0x7a, 0x65, 0x42,
+ 0x79, 0x74, 0x65, 0x73, 0x12, 0x60, 0x0a, 0x13, 0x67, 0x75, 0x61, 0x72,
+ 0x64, 0x72, 0x61, 0x69, 0x6c, 0x5f, 0x6f, 0x76, 0x65, 0x72, 0x72, 0x69,
+ 0x64, 0x65, 0x73, 0x18, 0x0b, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2f, 0x2e,
+ 0x70, 0x65, 0x72, 0x66, 0x65, 0x74, 0x74, 0x6f, 0x2e, 0x70, 0x72, 0x6f,
+ 0x74, 0x6f, 0x73, 0x2e, 0x54, 0x72, 0x61, 0x63, 0x65, 0x43, 0x6f, 0x6e,
+ 0x66, 0x69, 0x67, 0x2e, 0x47, 0x75, 0x61, 0x72, 0x64, 0x72, 0x61, 0x69,
+ 0x6c, 0x4f, 0x76, 0x65, 0x72, 0x72, 0x69, 0x64, 0x65, 0x73, 0x52, 0x12,
+ 0x67, 0x75, 0x61, 0x72, 0x64, 0x72, 0x61, 0x69, 0x6c, 0x4f, 0x76, 0x65,
+ 0x72, 0x72, 0x69, 0x64, 0x65, 0x73, 0x12, 0x25, 0x0a, 0x0e, 0x64, 0x65,
+ 0x66, 0x65, 0x72, 0x72, 0x65, 0x64, 0x5f, 0x73, 0x74, 0x61, 0x72, 0x74,
+ 0x18, 0x0c, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0d, 0x64, 0x65, 0x66, 0x65,
+ 0x72, 0x72, 0x65, 0x64, 0x53, 0x74, 0x61, 0x72, 0x74, 0x1a, 0xba, 0x01,
+ 0x0a, 0x0c, 0x42, 0x75, 0x66, 0x66, 0x65, 0x72, 0x43, 0x6f, 0x6e, 0x66,
+ 0x69, 0x67, 0x12, 0x17, 0x0a, 0x07, 0x73, 0x69, 0x7a, 0x65, 0x5f, 0x6b,
+ 0x62, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x06, 0x73, 0x69, 0x7a,
+ 0x65, 0x4b, 0x62, 0x12, 0x55, 0x0a, 0x0b, 0x66, 0x69, 0x6c, 0x6c, 0x5f,
+ 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0e,
+ 0x32, 0x34, 0x2e, 0x70, 0x65, 0x72, 0x66, 0x65, 0x74, 0x74, 0x6f, 0x2e,
+ 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2e, 0x54, 0x72, 0x61, 0x63, 0x65,
+ 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x2e, 0x42, 0x75, 0x66, 0x66, 0x65,
+ 0x72, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x2e, 0x46, 0x69, 0x6c, 0x6c,
+ 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x52, 0x0a, 0x66, 0x69, 0x6c, 0x6c,
+ 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x22, 0x2e, 0x0a, 0x0a, 0x46, 0x69,
+ 0x6c, 0x6c, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x12, 0x0f, 0x0a, 0x0b,
+ 0x55, 0x4e, 0x53, 0x50, 0x45, 0x43, 0x49, 0x46, 0x49, 0x45, 0x44, 0x10,
+ 0x00, 0x12, 0x0f, 0x0a, 0x0b, 0x52, 0x49, 0x4e, 0x47, 0x5f, 0x42, 0x55,
+ 0x46, 0x46, 0x45, 0x52, 0x10, 0x01, 0x4a, 0x04, 0x08, 0x02, 0x10, 0x03,
+ 0x4a, 0x04, 0x08, 0x03, 0x10, 0x04, 0x1a, 0x79, 0x0a, 0x0a, 0x44, 0x61,
+ 0x74, 0x61, 0x53, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x12, 0x39, 0x0a, 0x06,
+ 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b,
+ 0x32, 0x21, 0x2e, 0x70, 0x65, 0x72, 0x66, 0x65, 0x74, 0x74, 0x6f, 0x2e,
+ 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2e, 0x44, 0x61, 0x74, 0x61, 0x53,
+ 0x6f, 0x75, 0x72, 0x63, 0x65, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x52,
+ 0x06, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x30, 0x0a, 0x14, 0x70,
+ 0x72, 0x6f, 0x64, 0x75, 0x63, 0x65, 0x72, 0x5f, 0x6e, 0x61, 0x6d, 0x65,
+ 0x5f, 0x66, 0x69, 0x6c, 0x74, 0x65, 0x72, 0x18, 0x02, 0x20, 0x03, 0x28,
+ 0x09, 0x52, 0x12, 0x70, 0x72, 0x6f, 0x64, 0x75, 0x63, 0x65, 0x72, 0x4e,
+ 0x61, 0x6d, 0x65, 0x46, 0x69, 0x6c, 0x74, 0x65, 0x72, 0x1a, 0x77, 0x0a,
+ 0x0e, 0x50, 0x72, 0x6f, 0x64, 0x75, 0x63, 0x65, 0x72, 0x43, 0x6f, 0x6e,
+ 0x66, 0x69, 0x67, 0x12, 0x23, 0x0a, 0x0d, 0x70, 0x72, 0x6f, 0x64, 0x75,
+ 0x63, 0x65, 0x72, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01,
+ 0x28, 0x09, 0x52, 0x0c, 0x70, 0x72, 0x6f, 0x64, 0x75, 0x63, 0x65, 0x72,
+ 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x1e, 0x0a, 0x0b, 0x73, 0x68, 0x6d, 0x5f,
+ 0x73, 0x69, 0x7a, 0x65, 0x5f, 0x6b, 0x62, 0x18, 0x02, 0x20, 0x01, 0x28,
+ 0x0d, 0x52, 0x09, 0x73, 0x68, 0x6d, 0x53, 0x69, 0x7a, 0x65, 0x4b, 0x62,
+ 0x12, 0x20, 0x0a, 0x0c, 0x70, 0x61, 0x67, 0x65, 0x5f, 0x73, 0x69, 0x7a,
+ 0x65, 0x5f, 0x6b, 0x62, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x0a,
+ 0x70, 0x61, 0x67, 0x65, 0x53, 0x69, 0x7a, 0x65, 0x4b, 0x62, 0x1a, 0xa6,
+ 0x01, 0x0a, 0x0e, 0x53, 0x74, 0x61, 0x74, 0x73, 0x64, 0x4d, 0x65, 0x74,
+ 0x61, 0x64, 0x61, 0x74, 0x61, 0x12, 0x2e, 0x0a, 0x13, 0x74, 0x72, 0x69,
+ 0x67, 0x67, 0x65, 0x72, 0x69, 0x6e, 0x67, 0x5f, 0x61, 0x6c, 0x65, 0x72,
+ 0x74, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x03, 0x52, 0x11,
+ 0x74, 0x72, 0x69, 0x67, 0x67, 0x65, 0x72, 0x69, 0x6e, 0x67, 0x41, 0x6c,
+ 0x65, 0x72, 0x74, 0x49, 0x64, 0x12, 0x32, 0x0a, 0x15, 0x74, 0x72, 0x69,
+ 0x67, 0x67, 0x65, 0x72, 0x69, 0x6e, 0x67, 0x5f, 0x63, 0x6f, 0x6e, 0x66,
+ 0x69, 0x67, 0x5f, 0x75, 0x69, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x05,
+ 0x52, 0x13, 0x74, 0x72, 0x69, 0x67, 0x67, 0x65, 0x72, 0x69, 0x6e, 0x67,
+ 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x55, 0x69, 0x64, 0x12, 0x30, 0x0a,
+ 0x14, 0x74, 0x72, 0x69, 0x67, 0x67, 0x65, 0x72, 0x69, 0x6e, 0x67, 0x5f,
+ 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x5f, 0x69, 0x64, 0x18, 0x03, 0x20,
+ 0x01, 0x28, 0x03, 0x52, 0x12, 0x74, 0x72, 0x69, 0x67, 0x67, 0x65, 0x72,
+ 0x69, 0x6e, 0x67, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x49, 0x64, 0x1a,
+ 0x4c, 0x0a, 0x12, 0x47, 0x75, 0x61, 0x72, 0x64, 0x72, 0x61, 0x69, 0x6c,
+ 0x4f, 0x76, 0x65, 0x72, 0x72, 0x69, 0x64, 0x65, 0x73, 0x12, 0x36, 0x0a,
+ 0x18, 0x6d, 0x61, 0x78, 0x5f, 0x75, 0x70, 0x6c, 0x6f, 0x61, 0x64, 0x5f,
+ 0x70, 0x65, 0x72, 0x5f, 0x64, 0x61, 0x79, 0x5f, 0x62, 0x79, 0x74, 0x65,
+ 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x04, 0x52, 0x14, 0x6d, 0x61, 0x78,
+ 0x55, 0x70, 0x6c, 0x6f, 0x61, 0x64, 0x50, 0x65, 0x72, 0x44, 0x61, 0x79,
+ 0x42, 0x79, 0x74, 0x65, 0x73, 0x22, 0x55, 0x0a, 0x15, 0x4c, 0x6f, 0x63,
+ 0x6b, 0x64, 0x6f, 0x77, 0x6e, 0x4d, 0x6f, 0x64, 0x65, 0x4f, 0x70, 0x65,
+ 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x16, 0x0a, 0x12, 0x4c, 0x4f,
+ 0x43, 0x4b, 0x44, 0x4f, 0x57, 0x4e, 0x5f, 0x55, 0x4e, 0x43, 0x48, 0x41,
+ 0x4e, 0x47, 0x45, 0x44, 0x10, 0x00, 0x12, 0x12, 0x0a, 0x0e, 0x4c, 0x4f,
+ 0x43, 0x4b, 0x44, 0x4f, 0x57, 0x4e, 0x5f, 0x43, 0x4c, 0x45, 0x41, 0x52,
+ 0x10, 0x01, 0x12, 0x10, 0x0a, 0x0c, 0x4c, 0x4f, 0x43, 0x4b, 0x44, 0x4f,
+ 0x57, 0x4e, 0x5f, 0x53, 0x45, 0x54, 0x10, 0x02, 0x22, 0xda, 0x02, 0x0a,
+ 0x0f, 0x48, 0x65, 0x61, 0x70, 0x70, 0x72, 0x6f, 0x66, 0x64, 0x43, 0x6f,
+ 0x6e, 0x66, 0x69, 0x67, 0x12, 0x36, 0x0a, 0x17, 0x73, 0x61, 0x6d, 0x70,
+ 0x6c, 0x69, 0x6e, 0x67, 0x5f, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x76, 0x61,
+ 0x6c, 0x5f, 0x62, 0x79, 0x74, 0x65, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28,
+ 0x04, 0x52, 0x15, 0x73, 0x61, 0x6d, 0x70, 0x6c, 0x69, 0x6e, 0x67, 0x49,
+ 0x6e, 0x74, 0x65, 0x72, 0x76, 0x61, 0x6c, 0x42, 0x79, 0x74, 0x65, 0x73,
+ 0x12, 0x2c, 0x0a, 0x12, 0x6e, 0x61, 0x74, 0x69, 0x76, 0x65, 0x5f, 0x62,
+ 0x69, 0x6e, 0x61, 0x72, 0x79, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x02,
+ 0x20, 0x03, 0x28, 0x09, 0x52, 0x10, 0x6e, 0x61, 0x74, 0x69, 0x76, 0x65,
+ 0x42, 0x69, 0x6e, 0x61, 0x72, 0x79, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x10,
+ 0x0a, 0x03, 0x70, 0x69, 0x64, 0x18, 0x04, 0x20, 0x03, 0x28, 0x04, 0x52,
+ 0x03, 0x70, 0x69, 0x64, 0x12, 0x6a, 0x0a, 0x16, 0x63, 0x6f, 0x6e, 0x74,
+ 0x69, 0x6e, 0x75, 0x6f, 0x75, 0x73, 0x5f, 0x64, 0x75, 0x6d, 0x70, 0x5f,
+ 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x18, 0x06, 0x20, 0x01, 0x28, 0x0b,
+ 0x32, 0x34, 0x2e, 0x70, 0x65, 0x72, 0x66, 0x65, 0x74, 0x74, 0x6f, 0x2e,
+ 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2e, 0x48, 0x65, 0x61, 0x70, 0x70,
+ 0x72, 0x6f, 0x66, 0x64, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x2e, 0x43,
+ 0x6f, 0x6e, 0x74, 0x69, 0x6e, 0x6f, 0x75, 0x73, 0x44, 0x75, 0x6d, 0x70,
+ 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x52, 0x14, 0x63, 0x6f, 0x6e, 0x74,
+ 0x69, 0x6e, 0x75, 0x6f, 0x75, 0x73, 0x44, 0x75, 0x6d, 0x70, 0x43, 0x6f,
+ 0x6e, 0x66, 0x69, 0x67, 0x1a, 0x63, 0x0a, 0x13, 0x43, 0x6f, 0x6e, 0x74,
+ 0x69, 0x6e, 0x6f, 0x75, 0x73, 0x44, 0x75, 0x6d, 0x70, 0x43, 0x6f, 0x6e,
+ 0x66, 0x69, 0x67, 0x12, 0x22, 0x0a, 0x0d, 0x64, 0x75, 0x6d, 0x70, 0x5f,
+ 0x70, 0x68, 0x61, 0x73, 0x65, 0x5f, 0x6d, 0x73, 0x18, 0x05, 0x20, 0x01,
+ 0x28, 0x0d, 0x52, 0x0b, 0x64, 0x75, 0x6d, 0x70, 0x50, 0x68, 0x61, 0x73,
+ 0x65, 0x4d, 0x73, 0x12, 0x28, 0x0a, 0x10, 0x64, 0x75, 0x6d, 0x70, 0x5f,
+ 0x69, 0x6e, 0x74, 0x65, 0x72, 0x76, 0x61, 0x6c, 0x5f, 0x6d, 0x73, 0x18,
+ 0x06, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x0e, 0x64, 0x75, 0x6d, 0x70, 0x49,
+ 0x6e, 0x74, 0x65, 0x72, 0x76, 0x61, 0x6c, 0x4d, 0x73, 0x2a, 0xbf, 0x06,
+ 0x0a, 0x0f, 0x4d, 0x65, 0x6d, 0x69, 0x6e, 0x66, 0x6f, 0x43, 0x6f, 0x75,
+ 0x6e, 0x74, 0x65, 0x72, 0x73, 0x12, 0x17, 0x0a, 0x13, 0x4d, 0x45, 0x4d,
+ 0x49, 0x4e, 0x46, 0x4f, 0x5f, 0x55, 0x4e, 0x53, 0x50, 0x45, 0x43, 0x49,
+ 0x46, 0x49, 0x45, 0x44, 0x10, 0x00, 0x12, 0x15, 0x0a, 0x11, 0x4d, 0x45,
+ 0x4d, 0x49, 0x4e, 0x46, 0x4f, 0x5f, 0x4d, 0x45, 0x4d, 0x5f, 0x54, 0x4f,
+ 0x54, 0x41, 0x4c, 0x10, 0x01, 0x12, 0x14, 0x0a, 0x10, 0x4d, 0x45, 0x4d,
+ 0x49, 0x4e, 0x46, 0x4f, 0x5f, 0x4d, 0x45, 0x4d, 0x5f, 0x46, 0x52, 0x45,
+ 0x45, 0x10, 0x02, 0x12, 0x19, 0x0a, 0x15, 0x4d, 0x45, 0x4d, 0x49, 0x4e,
+ 0x46, 0x4f, 0x5f, 0x4d, 0x45, 0x4d, 0x5f, 0x41, 0x56, 0x41, 0x49, 0x4c,
+ 0x41, 0x42, 0x4c, 0x45, 0x10, 0x03, 0x12, 0x13, 0x0a, 0x0f, 0x4d, 0x45,
+ 0x4d, 0x49, 0x4e, 0x46, 0x4f, 0x5f, 0x42, 0x55, 0x46, 0x46, 0x45, 0x52,
+ 0x53, 0x10, 0x04, 0x12, 0x12, 0x0a, 0x0e, 0x4d, 0x45, 0x4d, 0x49, 0x4e,
+ 0x46, 0x4f, 0x5f, 0x43, 0x41, 0x43, 0x48, 0x45, 0x44, 0x10, 0x05, 0x12,
+ 0x17, 0x0a, 0x13, 0x4d, 0x45, 0x4d, 0x49, 0x4e, 0x46, 0x4f, 0x5f, 0x53,
+ 0x57, 0x41, 0x50, 0x5f, 0x43, 0x41, 0x43, 0x48, 0x45, 0x44, 0x10, 0x06,
+ 0x12, 0x12, 0x0a, 0x0e, 0x4d, 0x45, 0x4d, 0x49, 0x4e, 0x46, 0x4f, 0x5f,
+ 0x41, 0x43, 0x54, 0x49, 0x56, 0x45, 0x10, 0x07, 0x12, 0x14, 0x0a, 0x10,
+ 0x4d, 0x45, 0x4d, 0x49, 0x4e, 0x46, 0x4f, 0x5f, 0x49, 0x4e, 0x41, 0x43,
+ 0x54, 0x49, 0x56, 0x45, 0x10, 0x08, 0x12, 0x17, 0x0a, 0x13, 0x4d, 0x45,
+ 0x4d, 0x49, 0x4e, 0x46, 0x4f, 0x5f, 0x41, 0x43, 0x54, 0x49, 0x56, 0x45,
+ 0x5f, 0x41, 0x4e, 0x4f, 0x4e, 0x10, 0x09, 0x12, 0x19, 0x0a, 0x15, 0x4d,
+ 0x45, 0x4d, 0x49, 0x4e, 0x46, 0x4f, 0x5f, 0x49, 0x4e, 0x41, 0x43, 0x54,
+ 0x49, 0x56, 0x45, 0x5f, 0x41, 0x4e, 0x4f, 0x4e, 0x10, 0x0a, 0x12, 0x17,
+ 0x0a, 0x13, 0x4d, 0x45, 0x4d, 0x49, 0x4e, 0x46, 0x4f, 0x5f, 0x41, 0x43,
+ 0x54, 0x49, 0x56, 0x45, 0x5f, 0x46, 0x49, 0x4c, 0x45, 0x10, 0x0b, 0x12,
+ 0x19, 0x0a, 0x15, 0x4d, 0x45, 0x4d, 0x49, 0x4e, 0x46, 0x4f, 0x5f, 0x49,
+ 0x4e, 0x41, 0x43, 0x54, 0x49, 0x56, 0x45, 0x5f, 0x46, 0x49, 0x4c, 0x45,
+ 0x10, 0x0c, 0x12, 0x17, 0x0a, 0x13, 0x4d, 0x45, 0x4d, 0x49, 0x4e, 0x46,
+ 0x4f, 0x5f, 0x55, 0x4e, 0x45, 0x56, 0x49, 0x43, 0x54, 0x41, 0x42, 0x4c,
+ 0x45, 0x10, 0x0d, 0x12, 0x13, 0x0a, 0x0f, 0x4d, 0x45, 0x4d, 0x49, 0x4e,
+ 0x46, 0x4f, 0x5f, 0x4d, 0x4c, 0x4f, 0x43, 0x4b, 0x45, 0x44, 0x10, 0x0e,
+ 0x12, 0x16, 0x0a, 0x12, 0x4d, 0x45, 0x4d, 0x49, 0x4e, 0x46, 0x4f, 0x5f,
+ 0x53, 0x57, 0x41, 0x50, 0x5f, 0x54, 0x4f, 0x54, 0x41, 0x4c, 0x10, 0x0f,
+ 0x12, 0x15, 0x0a, 0x11, 0x4d, 0x45, 0x4d, 0x49, 0x4e, 0x46, 0x4f, 0x5f,
+ 0x53, 0x57, 0x41, 0x50, 0x5f, 0x46, 0x52, 0x45, 0x45, 0x10, 0x10, 0x12,
+ 0x11, 0x0a, 0x0d, 0x4d, 0x45, 0x4d, 0x49, 0x4e, 0x46, 0x4f, 0x5f, 0x44,
+ 0x49, 0x52, 0x54, 0x59, 0x10, 0x11, 0x12, 0x15, 0x0a, 0x11, 0x4d, 0x45,
+ 0x4d, 0x49, 0x4e, 0x46, 0x4f, 0x5f, 0x57, 0x52, 0x49, 0x54, 0x45, 0x42,
+ 0x41, 0x43, 0x4b, 0x10, 0x12, 0x12, 0x16, 0x0a, 0x12, 0x4d, 0x45, 0x4d,
+ 0x49, 0x4e, 0x46, 0x4f, 0x5f, 0x41, 0x4e, 0x4f, 0x4e, 0x5f, 0x50, 0x41,
+ 0x47, 0x45, 0x53, 0x10, 0x13, 0x12, 0x12, 0x0a, 0x0e, 0x4d, 0x45, 0x4d,
+ 0x49, 0x4e, 0x46, 0x4f, 0x5f, 0x4d, 0x41, 0x50, 0x50, 0x45, 0x44, 0x10,
+ 0x14, 0x12, 0x11, 0x0a, 0x0d, 0x4d, 0x45, 0x4d, 0x49, 0x4e, 0x46, 0x4f,
+ 0x5f, 0x53, 0x48, 0x4d, 0x45, 0x4d, 0x10, 0x15, 0x12, 0x10, 0x0a, 0x0c,
+ 0x4d, 0x45, 0x4d, 0x49, 0x4e, 0x46, 0x4f, 0x5f, 0x53, 0x4c, 0x41, 0x42,
+ 0x10, 0x16, 0x12, 0x1c, 0x0a, 0x18, 0x4d, 0x45, 0x4d, 0x49, 0x4e, 0x46,
+ 0x4f, 0x5f, 0x53, 0x4c, 0x41, 0x42, 0x5f, 0x52, 0x45, 0x43, 0x4c, 0x41,
+ 0x49, 0x4d, 0x41, 0x42, 0x4c, 0x45, 0x10, 0x17, 0x12, 0x1e, 0x0a, 0x1a,
+ 0x4d, 0x45, 0x4d, 0x49, 0x4e, 0x46, 0x4f, 0x5f, 0x53, 0x4c, 0x41, 0x42,
+ 0x5f, 0x55, 0x4e, 0x52, 0x45, 0x43, 0x4c, 0x41, 0x49, 0x4d, 0x41, 0x42,
+ 0x4c, 0x45, 0x10, 0x18, 0x12, 0x18, 0x0a, 0x14, 0x4d, 0x45, 0x4d, 0x49,
+ 0x4e, 0x46, 0x4f, 0x5f, 0x4b, 0x45, 0x52, 0x4e, 0x45, 0x4c, 0x5f, 0x53,
+ 0x54, 0x41, 0x43, 0x4b, 0x10, 0x19, 0x12, 0x17, 0x0a, 0x13, 0x4d, 0x45,
+ 0x4d, 0x49, 0x4e, 0x46, 0x4f, 0x5f, 0x50, 0x41, 0x47, 0x45, 0x5f, 0x54,
+ 0x41, 0x42, 0x4c, 0x45, 0x53, 0x10, 0x1a, 0x12, 0x18, 0x0a, 0x14, 0x4d,
+ 0x45, 0x4d, 0x49, 0x4e, 0x46, 0x4f, 0x5f, 0x43, 0x4f, 0x4d, 0x4d, 0x49,
+ 0x54, 0x5f, 0x4c, 0x49, 0x4d, 0x49, 0x54, 0x10, 0x1b, 0x12, 0x17, 0x0a,
+ 0x13, 0x4d, 0x45, 0x4d, 0x49, 0x4e, 0x46, 0x4f, 0x5f, 0x43, 0x4f, 0x4d,
+ 0x4d, 0x49, 0x54, 0x45, 0x44, 0x5f, 0x41, 0x53, 0x10, 0x1c, 0x12, 0x19,
+ 0x0a, 0x15, 0x4d, 0x45, 0x4d, 0x49, 0x4e, 0x46, 0x4f, 0x5f, 0x56, 0x4d,
+ 0x41, 0x4c, 0x4c, 0x4f, 0x43, 0x5f, 0x54, 0x4f, 0x54, 0x41, 0x4c, 0x10,
+ 0x1d, 0x12, 0x18, 0x0a, 0x14, 0x4d, 0x45, 0x4d, 0x49, 0x4e, 0x46, 0x4f,
+ 0x5f, 0x56, 0x4d, 0x41, 0x4c, 0x4c, 0x4f, 0x43, 0x5f, 0x55, 0x53, 0x45,
+ 0x44, 0x10, 0x1e, 0x12, 0x19, 0x0a, 0x15, 0x4d, 0x45, 0x4d, 0x49, 0x4e,
+ 0x46, 0x4f, 0x5f, 0x56, 0x4d, 0x41, 0x4c, 0x4c, 0x4f, 0x43, 0x5f, 0x43,
+ 0x48, 0x55, 0x4e, 0x4b, 0x10, 0x1f, 0x12, 0x15, 0x0a, 0x11, 0x4d, 0x45,
+ 0x4d, 0x49, 0x4e, 0x46, 0x4f, 0x5f, 0x43, 0x4d, 0x41, 0x5f, 0x54, 0x4f,
+ 0x54, 0x41, 0x4c, 0x10, 0x20, 0x12, 0x14, 0x0a, 0x10, 0x4d, 0x45, 0x4d,
+ 0x49, 0x4e, 0x46, 0x4f, 0x5f, 0x43, 0x4d, 0x41, 0x5f, 0x46, 0x52, 0x45,
+ 0x45, 0x10, 0x21, 0x2a, 0xff, 0x14, 0x0a, 0x0e, 0x56, 0x6d, 0x73, 0x74,
+ 0x61, 0x74, 0x43, 0x6f, 0x75, 0x6e, 0x74, 0x65, 0x72, 0x73, 0x12, 0x16,
+ 0x0a, 0x12, 0x56, 0x4d, 0x53, 0x54, 0x41, 0x54, 0x5f, 0x55, 0x4e, 0x53,
+ 0x50, 0x45, 0x43, 0x49, 0x46, 0x49, 0x45, 0x44, 0x10, 0x00, 0x12, 0x18,
+ 0x0a, 0x14, 0x56, 0x4d, 0x53, 0x54, 0x41, 0x54, 0x5f, 0x4e, 0x52, 0x5f,
+ 0x46, 0x52, 0x45, 0x45, 0x5f, 0x50, 0x41, 0x47, 0x45, 0x53, 0x10, 0x01,
+ 0x12, 0x19, 0x0a, 0x15, 0x56, 0x4d, 0x53, 0x54, 0x41, 0x54, 0x5f, 0x4e,
+ 0x52, 0x5f, 0x41, 0x4c, 0x4c, 0x4f, 0x43, 0x5f, 0x42, 0x41, 0x54, 0x43,
+ 0x48, 0x10, 0x02, 0x12, 0x1b, 0x0a, 0x17, 0x56, 0x4d, 0x53, 0x54, 0x41,
+ 0x54, 0x5f, 0x4e, 0x52, 0x5f, 0x49, 0x4e, 0x41, 0x43, 0x54, 0x49, 0x56,
+ 0x45, 0x5f, 0x41, 0x4e, 0x4f, 0x4e, 0x10, 0x03, 0x12, 0x19, 0x0a, 0x15,
+ 0x56, 0x4d, 0x53, 0x54, 0x41, 0x54, 0x5f, 0x4e, 0x52, 0x5f, 0x41, 0x43,
+ 0x54, 0x49, 0x56, 0x45, 0x5f, 0x41, 0x4e, 0x4f, 0x4e, 0x10, 0x04, 0x12,
+ 0x1b, 0x0a, 0x17, 0x56, 0x4d, 0x53, 0x54, 0x41, 0x54, 0x5f, 0x4e, 0x52,
+ 0x5f, 0x49, 0x4e, 0x41, 0x43, 0x54, 0x49, 0x56, 0x45, 0x5f, 0x46, 0x49,
+ 0x4c, 0x45, 0x10, 0x05, 0x12, 0x19, 0x0a, 0x15, 0x56, 0x4d, 0x53, 0x54,
+ 0x41, 0x54, 0x5f, 0x4e, 0x52, 0x5f, 0x41, 0x43, 0x54, 0x49, 0x56, 0x45,
+ 0x5f, 0x46, 0x49, 0x4c, 0x45, 0x10, 0x06, 0x12, 0x19, 0x0a, 0x15, 0x56,
+ 0x4d, 0x53, 0x54, 0x41, 0x54, 0x5f, 0x4e, 0x52, 0x5f, 0x55, 0x4e, 0x45,
+ 0x56, 0x49, 0x43, 0x54, 0x41, 0x42, 0x4c, 0x45, 0x10, 0x07, 0x12, 0x13,
+ 0x0a, 0x0f, 0x56, 0x4d, 0x53, 0x54, 0x41, 0x54, 0x5f, 0x4e, 0x52, 0x5f,
+ 0x4d, 0x4c, 0x4f, 0x43, 0x4b, 0x10, 0x08, 0x12, 0x18, 0x0a, 0x14, 0x56,
+ 0x4d, 0x53, 0x54, 0x41, 0x54, 0x5f, 0x4e, 0x52, 0x5f, 0x41, 0x4e, 0x4f,
+ 0x4e, 0x5f, 0x50, 0x41, 0x47, 0x45, 0x53, 0x10, 0x09, 0x12, 0x14, 0x0a,
+ 0x10, 0x56, 0x4d, 0x53, 0x54, 0x41, 0x54, 0x5f, 0x4e, 0x52, 0x5f, 0x4d,
+ 0x41, 0x50, 0x50, 0x45, 0x44, 0x10, 0x0a, 0x12, 0x18, 0x0a, 0x14, 0x56,
+ 0x4d, 0x53, 0x54, 0x41, 0x54, 0x5f, 0x4e, 0x52, 0x5f, 0x46, 0x49, 0x4c,
+ 0x45, 0x5f, 0x50, 0x41, 0x47, 0x45, 0x53, 0x10, 0x0b, 0x12, 0x13, 0x0a,
+ 0x0f, 0x56, 0x4d, 0x53, 0x54, 0x41, 0x54, 0x5f, 0x4e, 0x52, 0x5f, 0x44,
+ 0x49, 0x52, 0x54, 0x59, 0x10, 0x0c, 0x12, 0x17, 0x0a, 0x13, 0x56, 0x4d,
+ 0x53, 0x54, 0x41, 0x54, 0x5f, 0x4e, 0x52, 0x5f, 0x57, 0x52, 0x49, 0x54,
+ 0x45, 0x42, 0x41, 0x43, 0x4b, 0x10, 0x0d, 0x12, 0x1e, 0x0a, 0x1a, 0x56,
+ 0x4d, 0x53, 0x54, 0x41, 0x54, 0x5f, 0x4e, 0x52, 0x5f, 0x53, 0x4c, 0x41,
+ 0x42, 0x5f, 0x52, 0x45, 0x43, 0x4c, 0x41, 0x49, 0x4d, 0x41, 0x42, 0x4c,
+ 0x45, 0x10, 0x0e, 0x12, 0x20, 0x0a, 0x1c, 0x56, 0x4d, 0x53, 0x54, 0x41,
+ 0x54, 0x5f, 0x4e, 0x52, 0x5f, 0x53, 0x4c, 0x41, 0x42, 0x5f, 0x55, 0x4e,
+ 0x52, 0x45, 0x43, 0x4c, 0x41, 0x49, 0x4d, 0x41, 0x42, 0x4c, 0x45, 0x10,
+ 0x0f, 0x12, 0x1e, 0x0a, 0x1a, 0x56, 0x4d, 0x53, 0x54, 0x41, 0x54, 0x5f,
+ 0x4e, 0x52, 0x5f, 0x50, 0x41, 0x47, 0x45, 0x5f, 0x54, 0x41, 0x42, 0x4c,
+ 0x45, 0x5f, 0x50, 0x41, 0x47, 0x45, 0x53, 0x10, 0x10, 0x12, 0x1a, 0x0a,
+ 0x16, 0x56, 0x4d, 0x53, 0x54, 0x41, 0x54, 0x5f, 0x4e, 0x52, 0x5f, 0x4b,
+ 0x45, 0x52, 0x4e, 0x45, 0x4c, 0x5f, 0x53, 0x54, 0x41, 0x43, 0x4b, 0x10,
+ 0x11, 0x12, 0x16, 0x0a, 0x12, 0x56, 0x4d, 0x53, 0x54, 0x41, 0x54, 0x5f,
+ 0x4e, 0x52, 0x5f, 0x4f, 0x56, 0x45, 0x52, 0x48, 0x45, 0x41, 0x44, 0x10,
+ 0x12, 0x12, 0x16, 0x0a, 0x12, 0x56, 0x4d, 0x53, 0x54, 0x41, 0x54, 0x5f,
+ 0x4e, 0x52, 0x5f, 0x55, 0x4e, 0x53, 0x54, 0x41, 0x42, 0x4c, 0x45, 0x10,
+ 0x13, 0x12, 0x14, 0x0a, 0x10, 0x56, 0x4d, 0x53, 0x54, 0x41, 0x54, 0x5f,
+ 0x4e, 0x52, 0x5f, 0x42, 0x4f, 0x55, 0x4e, 0x43, 0x45, 0x10, 0x14, 0x12,
+ 0x1a, 0x0a, 0x16, 0x56, 0x4d, 0x53, 0x54, 0x41, 0x54, 0x5f, 0x4e, 0x52,
+ 0x5f, 0x56, 0x4d, 0x53, 0x43, 0x41, 0x4e, 0x5f, 0x57, 0x52, 0x49, 0x54,
+ 0x45, 0x10, 0x15, 0x12, 0x26, 0x0a, 0x22, 0x56, 0x4d, 0x53, 0x54, 0x41,
+ 0x54, 0x5f, 0x4e, 0x52, 0x5f, 0x56, 0x4d, 0x53, 0x43, 0x41, 0x4e, 0x5f,
+ 0x49, 0x4d, 0x4d, 0x45, 0x44, 0x49, 0x41, 0x54, 0x45, 0x5f, 0x52, 0x45,
+ 0x43, 0x4c, 0x41, 0x49, 0x4d, 0x10, 0x16, 0x12, 0x1c, 0x0a, 0x18, 0x56,
+ 0x4d, 0x53, 0x54, 0x41, 0x54, 0x5f, 0x4e, 0x52, 0x5f, 0x57, 0x52, 0x49,
+ 0x54, 0x45, 0x42, 0x41, 0x43, 0x4b, 0x5f, 0x54, 0x45, 0x4d, 0x50, 0x10,
+ 0x17, 0x12, 0x1b, 0x0a, 0x17, 0x56, 0x4d, 0x53, 0x54, 0x41, 0x54, 0x5f,
+ 0x4e, 0x52, 0x5f, 0x49, 0x53, 0x4f, 0x4c, 0x41, 0x54, 0x45, 0x44, 0x5f,
+ 0x41, 0x4e, 0x4f, 0x4e, 0x10, 0x18, 0x12, 0x1b, 0x0a, 0x17, 0x56, 0x4d,
+ 0x53, 0x54, 0x41, 0x54, 0x5f, 0x4e, 0x52, 0x5f, 0x49, 0x53, 0x4f, 0x4c,
+ 0x41, 0x54, 0x45, 0x44, 0x5f, 0x46, 0x49, 0x4c, 0x45, 0x10, 0x19, 0x12,
+ 0x13, 0x0a, 0x0f, 0x56, 0x4d, 0x53, 0x54, 0x41, 0x54, 0x5f, 0x4e, 0x52,
+ 0x5f, 0x53, 0x48, 0x4d, 0x45, 0x4d, 0x10, 0x1a, 0x12, 0x15, 0x0a, 0x11,
+ 0x56, 0x4d, 0x53, 0x54, 0x41, 0x54, 0x5f, 0x4e, 0x52, 0x5f, 0x44, 0x49,
+ 0x52, 0x54, 0x49, 0x45, 0x44, 0x10, 0x1b, 0x12, 0x15, 0x0a, 0x11, 0x56,
+ 0x4d, 0x53, 0x54, 0x41, 0x54, 0x5f, 0x4e, 0x52, 0x5f, 0x57, 0x52, 0x49,
+ 0x54, 0x54, 0x45, 0x4e, 0x10, 0x1c, 0x12, 0x1b, 0x0a, 0x17, 0x56, 0x4d,
+ 0x53, 0x54, 0x41, 0x54, 0x5f, 0x4e, 0x52, 0x5f, 0x50, 0x41, 0x47, 0x45,
+ 0x53, 0x5f, 0x53, 0x43, 0x41, 0x4e, 0x4e, 0x45, 0x44, 0x10, 0x1d, 0x12,
+ 0x1d, 0x0a, 0x19, 0x56, 0x4d, 0x53, 0x54, 0x41, 0x54, 0x5f, 0x57, 0x4f,
+ 0x52, 0x4b, 0x49, 0x4e, 0x47, 0x53, 0x45, 0x54, 0x5f, 0x52, 0x45, 0x46,
+ 0x41, 0x55, 0x4c, 0x54, 0x10, 0x1e, 0x12, 0x1e, 0x0a, 0x1a, 0x56, 0x4d,
+ 0x53, 0x54, 0x41, 0x54, 0x5f, 0x57, 0x4f, 0x52, 0x4b, 0x49, 0x4e, 0x47,
+ 0x53, 0x45, 0x54, 0x5f, 0x41, 0x43, 0x54, 0x49, 0x56, 0x41, 0x54, 0x45,
+ 0x10, 0x1f, 0x12, 0x21, 0x0a, 0x1d, 0x56, 0x4d, 0x53, 0x54, 0x41, 0x54,
+ 0x5f, 0x57, 0x4f, 0x52, 0x4b, 0x49, 0x4e, 0x47, 0x53, 0x45, 0x54, 0x5f,
+ 0x4e, 0x4f, 0x44, 0x45, 0x52, 0x45, 0x43, 0x4c, 0x41, 0x49, 0x4d, 0x10,
+ 0x20, 0x12, 0x28, 0x0a, 0x24, 0x56, 0x4d, 0x53, 0x54, 0x41, 0x54, 0x5f,
+ 0x4e, 0x52, 0x5f, 0x41, 0x4e, 0x4f, 0x4e, 0x5f, 0x54, 0x52, 0x41, 0x4e,
+ 0x53, 0x50, 0x41, 0x52, 0x45, 0x4e, 0x54, 0x5f, 0x48, 0x55, 0x47, 0x45,
+ 0x50, 0x41, 0x47, 0x45, 0x53, 0x10, 0x21, 0x12, 0x16, 0x0a, 0x12, 0x56,
+ 0x4d, 0x53, 0x54, 0x41, 0x54, 0x5f, 0x4e, 0x52, 0x5f, 0x46, 0x52, 0x45,
+ 0x45, 0x5f, 0x43, 0x4d, 0x41, 0x10, 0x22, 0x12, 0x17, 0x0a, 0x13, 0x56,
+ 0x4d, 0x53, 0x54, 0x41, 0x54, 0x5f, 0x4e, 0x52, 0x5f, 0x53, 0x57, 0x41,
+ 0x50, 0x43, 0x41, 0x43, 0x48, 0x45, 0x10, 0x23, 0x12, 0x1d, 0x0a, 0x19,
+ 0x56, 0x4d, 0x53, 0x54, 0x41, 0x54, 0x5f, 0x4e, 0x52, 0x5f, 0x44, 0x49,
+ 0x52, 0x54, 0x59, 0x5f, 0x54, 0x48, 0x52, 0x45, 0x53, 0x48, 0x4f, 0x4c,
+ 0x44, 0x10, 0x24, 0x12, 0x28, 0x0a, 0x24, 0x56, 0x4d, 0x53, 0x54, 0x41,
+ 0x54, 0x5f, 0x4e, 0x52, 0x5f, 0x44, 0x49, 0x52, 0x54, 0x59, 0x5f, 0x42,
+ 0x41, 0x43, 0x4b, 0x47, 0x52, 0x4f, 0x55, 0x4e, 0x44, 0x5f, 0x54, 0x48,
+ 0x52, 0x45, 0x53, 0x48, 0x4f, 0x4c, 0x44, 0x10, 0x25, 0x12, 0x11, 0x0a,
+ 0x0d, 0x56, 0x4d, 0x53, 0x54, 0x41, 0x54, 0x5f, 0x50, 0x47, 0x50, 0x47,
+ 0x49, 0x4e, 0x10, 0x26, 0x12, 0x12, 0x0a, 0x0e, 0x56, 0x4d, 0x53, 0x54,
+ 0x41, 0x54, 0x5f, 0x50, 0x47, 0x50, 0x47, 0x4f, 0x55, 0x54, 0x10, 0x27,
+ 0x12, 0x17, 0x0a, 0x13, 0x56, 0x4d, 0x53, 0x54, 0x41, 0x54, 0x5f, 0x50,
+ 0x47, 0x50, 0x47, 0x4f, 0x55, 0x54, 0x43, 0x4c, 0x45, 0x41, 0x4e, 0x10,
+ 0x28, 0x12, 0x11, 0x0a, 0x0d, 0x56, 0x4d, 0x53, 0x54, 0x41, 0x54, 0x5f,
+ 0x50, 0x53, 0x57, 0x50, 0x49, 0x4e, 0x10, 0x29, 0x12, 0x12, 0x0a, 0x0e,
+ 0x56, 0x4d, 0x53, 0x54, 0x41, 0x54, 0x5f, 0x50, 0x53, 0x57, 0x50, 0x4f,
+ 0x55, 0x54, 0x10, 0x2a, 0x12, 0x16, 0x0a, 0x12, 0x56, 0x4d, 0x53, 0x54,
+ 0x41, 0x54, 0x5f, 0x50, 0x47, 0x41, 0x4c, 0x4c, 0x4f, 0x43, 0x5f, 0x44,
+ 0x4d, 0x41, 0x10, 0x2b, 0x12, 0x19, 0x0a, 0x15, 0x56, 0x4d, 0x53, 0x54,
+ 0x41, 0x54, 0x5f, 0x50, 0x47, 0x41, 0x4c, 0x4c, 0x4f, 0x43, 0x5f, 0x4e,
+ 0x4f, 0x52, 0x4d, 0x41, 0x4c, 0x10, 0x2c, 0x12, 0x1a, 0x0a, 0x16, 0x56,
+ 0x4d, 0x53, 0x54, 0x41, 0x54, 0x5f, 0x50, 0x47, 0x41, 0x4c, 0x4c, 0x4f,
+ 0x43, 0x5f, 0x4d, 0x4f, 0x56, 0x41, 0x42, 0x4c, 0x45, 0x10, 0x2d, 0x12,
+ 0x11, 0x0a, 0x0d, 0x56, 0x4d, 0x53, 0x54, 0x41, 0x54, 0x5f, 0x50, 0x47,
+ 0x46, 0x52, 0x45, 0x45, 0x10, 0x2e, 0x12, 0x15, 0x0a, 0x11, 0x56, 0x4d,
+ 0x53, 0x54, 0x41, 0x54, 0x5f, 0x50, 0x47, 0x41, 0x43, 0x54, 0x49, 0x56,
+ 0x41, 0x54, 0x45, 0x10, 0x2f, 0x12, 0x17, 0x0a, 0x13, 0x56, 0x4d, 0x53,
+ 0x54, 0x41, 0x54, 0x5f, 0x50, 0x47, 0x44, 0x45, 0x41, 0x43, 0x54, 0x49,
+ 0x56, 0x41, 0x54, 0x45, 0x10, 0x30, 0x12, 0x12, 0x0a, 0x0e, 0x56, 0x4d,
+ 0x53, 0x54, 0x41, 0x54, 0x5f, 0x50, 0x47, 0x46, 0x41, 0x55, 0x4c, 0x54,
+ 0x10, 0x31, 0x12, 0x15, 0x0a, 0x11, 0x56, 0x4d, 0x53, 0x54, 0x41, 0x54,
+ 0x5f, 0x50, 0x47, 0x4d, 0x41, 0x4a, 0x46, 0x41, 0x55, 0x4c, 0x54, 0x10,
+ 0x32, 0x12, 0x17, 0x0a, 0x13, 0x56, 0x4d, 0x53, 0x54, 0x41, 0x54, 0x5f,
+ 0x50, 0x47, 0x52, 0x45, 0x46, 0x49, 0x4c, 0x4c, 0x5f, 0x44, 0x4d, 0x41,
+ 0x10, 0x33, 0x12, 0x1a, 0x0a, 0x16, 0x56, 0x4d, 0x53, 0x54, 0x41, 0x54,
+ 0x5f, 0x50, 0x47, 0x52, 0x45, 0x46, 0x49, 0x4c, 0x4c, 0x5f, 0x4e, 0x4f,
+ 0x52, 0x4d, 0x41, 0x4c, 0x10, 0x34, 0x12, 0x1b, 0x0a, 0x17, 0x56, 0x4d,
+ 0x53, 0x54, 0x41, 0x54, 0x5f, 0x50, 0x47, 0x52, 0x45, 0x46, 0x49, 0x4c,
+ 0x4c, 0x5f, 0x4d, 0x4f, 0x56, 0x41, 0x42, 0x4c, 0x45, 0x10, 0x35, 0x12,
+ 0x1d, 0x0a, 0x19, 0x56, 0x4d, 0x53, 0x54, 0x41, 0x54, 0x5f, 0x50, 0x47,
+ 0x53, 0x54, 0x45, 0x41, 0x4c, 0x5f, 0x4b, 0x53, 0x57, 0x41, 0x50, 0x44,
+ 0x5f, 0x44, 0x4d, 0x41, 0x10, 0x36, 0x12, 0x20, 0x0a, 0x1c, 0x56, 0x4d,
+ 0x53, 0x54, 0x41, 0x54, 0x5f, 0x50, 0x47, 0x53, 0x54, 0x45, 0x41, 0x4c,
+ 0x5f, 0x4b, 0x53, 0x57, 0x41, 0x50, 0x44, 0x5f, 0x4e, 0x4f, 0x52, 0x4d,
+ 0x41, 0x4c, 0x10, 0x37, 0x12, 0x21, 0x0a, 0x1d, 0x56, 0x4d, 0x53, 0x54,
+ 0x41, 0x54, 0x5f, 0x50, 0x47, 0x53, 0x54, 0x45, 0x41, 0x4c, 0x5f, 0x4b,
+ 0x53, 0x57, 0x41, 0x50, 0x44, 0x5f, 0x4d, 0x4f, 0x56, 0x41, 0x42, 0x4c,
+ 0x45, 0x10, 0x38, 0x12, 0x1d, 0x0a, 0x19, 0x56, 0x4d, 0x53, 0x54, 0x41,
+ 0x54, 0x5f, 0x50, 0x47, 0x53, 0x54, 0x45, 0x41, 0x4c, 0x5f, 0x44, 0x49,
+ 0x52, 0x45, 0x43, 0x54, 0x5f, 0x44, 0x4d, 0x41, 0x10, 0x39, 0x12, 0x20,
+ 0x0a, 0x1c, 0x56, 0x4d, 0x53, 0x54, 0x41, 0x54, 0x5f, 0x50, 0x47, 0x53,
+ 0x54, 0x45, 0x41, 0x4c, 0x5f, 0x44, 0x49, 0x52, 0x45, 0x43, 0x54, 0x5f,
+ 0x4e, 0x4f, 0x52, 0x4d, 0x41, 0x4c, 0x10, 0x3a, 0x12, 0x21, 0x0a, 0x1d,
+ 0x56, 0x4d, 0x53, 0x54, 0x41, 0x54, 0x5f, 0x50, 0x47, 0x53, 0x54, 0x45,
+ 0x41, 0x4c, 0x5f, 0x44, 0x49, 0x52, 0x45, 0x43, 0x54, 0x5f, 0x4d, 0x4f,
+ 0x56, 0x41, 0x42, 0x4c, 0x45, 0x10, 0x3b, 0x12, 0x1c, 0x0a, 0x18, 0x56,
+ 0x4d, 0x53, 0x54, 0x41, 0x54, 0x5f, 0x50, 0x47, 0x53, 0x43, 0x41, 0x4e,
+ 0x5f, 0x4b, 0x53, 0x57, 0x41, 0x50, 0x44, 0x5f, 0x44, 0x4d, 0x41, 0x10,
+ 0x3c, 0x12, 0x1f, 0x0a, 0x1b, 0x56, 0x4d, 0x53, 0x54, 0x41, 0x54, 0x5f,
+ 0x50, 0x47, 0x53, 0x43, 0x41, 0x4e, 0x5f, 0x4b, 0x53, 0x57, 0x41, 0x50,
+ 0x44, 0x5f, 0x4e, 0x4f, 0x52, 0x4d, 0x41, 0x4c, 0x10, 0x3d, 0x12, 0x20,
+ 0x0a, 0x1c, 0x56, 0x4d, 0x53, 0x54, 0x41, 0x54, 0x5f, 0x50, 0x47, 0x53,
+ 0x43, 0x41, 0x4e, 0x5f, 0x4b, 0x53, 0x57, 0x41, 0x50, 0x44, 0x5f, 0x4d,
+ 0x4f, 0x56, 0x41, 0x42, 0x4c, 0x45, 0x10, 0x3e, 0x12, 0x1c, 0x0a, 0x18,
+ 0x56, 0x4d, 0x53, 0x54, 0x41, 0x54, 0x5f, 0x50, 0x47, 0x53, 0x43, 0x41,
+ 0x4e, 0x5f, 0x44, 0x49, 0x52, 0x45, 0x43, 0x54, 0x5f, 0x44, 0x4d, 0x41,
+ 0x10, 0x3f, 0x12, 0x1f, 0x0a, 0x1b, 0x56, 0x4d, 0x53, 0x54, 0x41, 0x54,
+ 0x5f, 0x50, 0x47, 0x53, 0x43, 0x41, 0x4e, 0x5f, 0x44, 0x49, 0x52, 0x45,
+ 0x43, 0x54, 0x5f, 0x4e, 0x4f, 0x52, 0x4d, 0x41, 0x4c, 0x10, 0x40, 0x12,
+ 0x20, 0x0a, 0x1c, 0x56, 0x4d, 0x53, 0x54, 0x41, 0x54, 0x5f, 0x50, 0x47,
+ 0x53, 0x43, 0x41, 0x4e, 0x5f, 0x44, 0x49, 0x52, 0x45, 0x43, 0x54, 0x5f,
+ 0x4d, 0x4f, 0x56, 0x41, 0x42, 0x4c, 0x45, 0x10, 0x41, 0x12, 0x21, 0x0a,
+ 0x1d, 0x56, 0x4d, 0x53, 0x54, 0x41, 0x54, 0x5f, 0x50, 0x47, 0x53, 0x43,
+ 0x41, 0x4e, 0x5f, 0x44, 0x49, 0x52, 0x45, 0x43, 0x54, 0x5f, 0x54, 0x48,
+ 0x52, 0x4f, 0x54, 0x54, 0x4c, 0x45, 0x10, 0x42, 0x12, 0x17, 0x0a, 0x13,
+ 0x56, 0x4d, 0x53, 0x54, 0x41, 0x54, 0x5f, 0x50, 0x47, 0x49, 0x4e, 0x4f,
+ 0x44, 0x45, 0x53, 0x54, 0x45, 0x41, 0x4c, 0x10, 0x43, 0x12, 0x18, 0x0a,
+ 0x14, 0x56, 0x4d, 0x53, 0x54, 0x41, 0x54, 0x5f, 0x53, 0x4c, 0x41, 0x42,
+ 0x53, 0x5f, 0x53, 0x43, 0x41, 0x4e, 0x4e, 0x45, 0x44, 0x10, 0x44, 0x12,
+ 0x1c, 0x0a, 0x18, 0x56, 0x4d, 0x53, 0x54, 0x41, 0x54, 0x5f, 0x4b, 0x53,
+ 0x57, 0x41, 0x50, 0x44, 0x5f, 0x49, 0x4e, 0x4f, 0x44, 0x45, 0x53, 0x54,
+ 0x45, 0x41, 0x4c, 0x10, 0x45, 0x12, 0x27, 0x0a, 0x23, 0x56, 0x4d, 0x53,
+ 0x54, 0x41, 0x54, 0x5f, 0x4b, 0x53, 0x57, 0x41, 0x50, 0x44, 0x5f, 0x4c,
+ 0x4f, 0x57, 0x5f, 0x57, 0x4d, 0x41, 0x52, 0x4b, 0x5f, 0x48, 0x49, 0x54,
+ 0x5f, 0x51, 0x55, 0x49, 0x43, 0x4b, 0x4c, 0x59, 0x10, 0x46, 0x12, 0x28,
+ 0x0a, 0x24, 0x56, 0x4d, 0x53, 0x54, 0x41, 0x54, 0x5f, 0x4b, 0x53, 0x57,
+ 0x41, 0x50, 0x44, 0x5f, 0x48, 0x49, 0x47, 0x48, 0x5f, 0x57, 0x4d, 0x41,
+ 0x52, 0x4b, 0x5f, 0x48, 0x49, 0x54, 0x5f, 0x51, 0x55, 0x49, 0x43, 0x4b,
+ 0x4c, 0x59, 0x10, 0x47, 0x12, 0x15, 0x0a, 0x11, 0x56, 0x4d, 0x53, 0x54,
+ 0x41, 0x54, 0x5f, 0x50, 0x41, 0x47, 0x45, 0x4f, 0x55, 0x54, 0x52, 0x55,
+ 0x4e, 0x10, 0x48, 0x12, 0x15, 0x0a, 0x11, 0x56, 0x4d, 0x53, 0x54, 0x41,
+ 0x54, 0x5f, 0x41, 0x4c, 0x4c, 0x4f, 0x43, 0x53, 0x54, 0x41, 0x4c, 0x4c,
+ 0x10, 0x49, 0x12, 0x14, 0x0a, 0x10, 0x56, 0x4d, 0x53, 0x54, 0x41, 0x54,
+ 0x5f, 0x50, 0x47, 0x52, 0x4f, 0x54, 0x41, 0x54, 0x45, 0x44, 0x10, 0x4a,
+ 0x12, 0x19, 0x0a, 0x15, 0x56, 0x4d, 0x53, 0x54, 0x41, 0x54, 0x5f, 0x44,
+ 0x52, 0x4f, 0x50, 0x5f, 0x50, 0x41, 0x47, 0x45, 0x43, 0x41, 0x43, 0x48,
+ 0x45, 0x10, 0x4b, 0x12, 0x14, 0x0a, 0x10, 0x56, 0x4d, 0x53, 0x54, 0x41,
+ 0x54, 0x5f, 0x44, 0x52, 0x4f, 0x50, 0x5f, 0x53, 0x4c, 0x41, 0x42, 0x10,
+ 0x4c, 0x12, 0x1c, 0x0a, 0x18, 0x56, 0x4d, 0x53, 0x54, 0x41, 0x54, 0x5f,
+ 0x50, 0x47, 0x4d, 0x49, 0x47, 0x52, 0x41, 0x54, 0x45, 0x5f, 0x53, 0x55,
+ 0x43, 0x43, 0x45, 0x53, 0x53, 0x10, 0x4d, 0x12, 0x19, 0x0a, 0x15, 0x56,
+ 0x4d, 0x53, 0x54, 0x41, 0x54, 0x5f, 0x50, 0x47, 0x4d, 0x49, 0x47, 0x52,
+ 0x41, 0x54, 0x45, 0x5f, 0x46, 0x41, 0x49, 0x4c, 0x10, 0x4e, 0x12, 0x22,
+ 0x0a, 0x1e, 0x56, 0x4d, 0x53, 0x54, 0x41, 0x54, 0x5f, 0x43, 0x4f, 0x4d,
+ 0x50, 0x41, 0x43, 0x54, 0x5f, 0x4d, 0x49, 0x47, 0x52, 0x41, 0x54, 0x45,
+ 0x5f, 0x53, 0x43, 0x41, 0x4e, 0x4e, 0x45, 0x44, 0x10, 0x4f, 0x12, 0x1f,
+ 0x0a, 0x1b, 0x56, 0x4d, 0x53, 0x54, 0x41, 0x54, 0x5f, 0x43, 0x4f, 0x4d,
+ 0x50, 0x41, 0x43, 0x54, 0x5f, 0x46, 0x52, 0x45, 0x45, 0x5f, 0x53, 0x43,
+ 0x41, 0x4e, 0x4e, 0x45, 0x44, 0x10, 0x50, 0x12, 0x1b, 0x0a, 0x17, 0x56,
+ 0x4d, 0x53, 0x54, 0x41, 0x54, 0x5f, 0x43, 0x4f, 0x4d, 0x50, 0x41, 0x43,
+ 0x54, 0x5f, 0x49, 0x53, 0x4f, 0x4c, 0x41, 0x54, 0x45, 0x44, 0x10, 0x51,
+ 0x12, 0x18, 0x0a, 0x14, 0x56, 0x4d, 0x53, 0x54, 0x41, 0x54, 0x5f, 0x43,
+ 0x4f, 0x4d, 0x50, 0x41, 0x43, 0x54, 0x5f, 0x53, 0x54, 0x41, 0x4c, 0x4c,
+ 0x10, 0x52, 0x12, 0x17, 0x0a, 0x13, 0x56, 0x4d, 0x53, 0x54, 0x41, 0x54,
+ 0x5f, 0x43, 0x4f, 0x4d, 0x50, 0x41, 0x43, 0x54, 0x5f, 0x46, 0x41, 0x49,
+ 0x4c, 0x10, 0x53, 0x12, 0x1a, 0x0a, 0x16, 0x56, 0x4d, 0x53, 0x54, 0x41,
+ 0x54, 0x5f, 0x43, 0x4f, 0x4d, 0x50, 0x41, 0x43, 0x54, 0x5f, 0x53, 0x55,
+ 0x43, 0x43, 0x45, 0x53, 0x53, 0x10, 0x54, 0x12, 0x1e, 0x0a, 0x1a, 0x56,
+ 0x4d, 0x53, 0x54, 0x41, 0x54, 0x5f, 0x43, 0x4f, 0x4d, 0x50, 0x41, 0x43,
+ 0x54, 0x5f, 0x44, 0x41, 0x45, 0x4d, 0x4f, 0x4e, 0x5f, 0x57, 0x41, 0x4b,
+ 0x45, 0x10, 0x55, 0x12, 0x21, 0x0a, 0x1d, 0x56, 0x4d, 0x53, 0x54, 0x41,
+ 0x54, 0x5f, 0x55, 0x4e, 0x45, 0x56, 0x49, 0x43, 0x54, 0x41, 0x42, 0x4c,
+ 0x45, 0x5f, 0x50, 0x47, 0x53, 0x5f, 0x43, 0x55, 0x4c, 0x4c, 0x45, 0x44,
+ 0x10, 0x56, 0x12, 0x22, 0x0a, 0x1e, 0x56, 0x4d, 0x53, 0x54, 0x41, 0x54,
+ 0x5f, 0x55, 0x4e, 0x45, 0x56, 0x49, 0x43, 0x54, 0x41, 0x42, 0x4c, 0x45,
+ 0x5f, 0x50, 0x47, 0x53, 0x5f, 0x53, 0x43, 0x41, 0x4e, 0x4e, 0x45, 0x44,
+ 0x10, 0x57, 0x12, 0x22, 0x0a, 0x1e, 0x56, 0x4d, 0x53, 0x54, 0x41, 0x54,
+ 0x5f, 0x55, 0x4e, 0x45, 0x56, 0x49, 0x43, 0x54, 0x41, 0x42, 0x4c, 0x45,
+ 0x5f, 0x50, 0x47, 0x53, 0x5f, 0x52, 0x45, 0x53, 0x43, 0x55, 0x45, 0x44,
+ 0x10, 0x58, 0x12, 0x22, 0x0a, 0x1e, 0x56, 0x4d, 0x53, 0x54, 0x41, 0x54,
+ 0x5f, 0x55, 0x4e, 0x45, 0x56, 0x49, 0x43, 0x54, 0x41, 0x42, 0x4c, 0x45,
+ 0x5f, 0x50, 0x47, 0x53, 0x5f, 0x4d, 0x4c, 0x4f, 0x43, 0x4b, 0x45, 0x44,
+ 0x10, 0x59, 0x12, 0x24, 0x0a, 0x20, 0x56, 0x4d, 0x53, 0x54, 0x41, 0x54,
+ 0x5f, 0x55, 0x4e, 0x45, 0x56, 0x49, 0x43, 0x54, 0x41, 0x42, 0x4c, 0x45,
+ 0x5f, 0x50, 0x47, 0x53, 0x5f, 0x4d, 0x55, 0x4e, 0x4c, 0x4f, 0x43, 0x4b,
+ 0x45, 0x44, 0x10, 0x5a, 0x12, 0x22, 0x0a, 0x1e, 0x56, 0x4d, 0x53, 0x54,
+ 0x41, 0x54, 0x5f, 0x55, 0x4e, 0x45, 0x56, 0x49, 0x43, 0x54, 0x41, 0x42,
+ 0x4c, 0x45, 0x5f, 0x50, 0x47, 0x53, 0x5f, 0x43, 0x4c, 0x45, 0x41, 0x52,
+ 0x45, 0x44, 0x10, 0x5b, 0x12, 0x23, 0x0a, 0x1f, 0x56, 0x4d, 0x53, 0x54,
+ 0x41, 0x54, 0x5f, 0x55, 0x4e, 0x45, 0x56, 0x49, 0x43, 0x54, 0x41, 0x42,
+ 0x4c, 0x45, 0x5f, 0x50, 0x47, 0x53, 0x5f, 0x53, 0x54, 0x52, 0x41, 0x4e,
+ 0x44, 0x45, 0x44, 0x10, 0x5c}};
+
+} // namespace perfetto
+
+#endif // SRC_PERFETTO_CMD_PERFETTO_CONFIG_DESCRIPTOR_H_
diff --git a/src/protozero/BUILD.gn b/src/protozero/BUILD.gn
index 9b97c73..bfc4fa6 100644
--- a/src/protozero/BUILD.gn
+++ b/src/protozero/BUILD.gn
@@ -31,30 +31,16 @@
"message_handle.cc",
"proto_decoder.cc",
"proto_field_descriptor.cc",
+ "scattered_stream_memory_delegate.cc",
"scattered_stream_null_delegate.cc",
"scattered_stream_writer.cc",
]
}
-source_set("test_support") {
- testonly = true
- deps = [
- "../../gn:default_deps",
- ]
- public_deps = [
- ":protozero",
- ]
- sources = [
- "scattered_stream_delegate_for_testing.cc",
- "scattered_stream_delegate_for_testing.h",
- ]
-}
-
source_set("unittests") {
testonly = true
deps = [
":protozero",
- ":test_support",
":testing_messages_lite",
":testing_messages_zero",
"../../gn:default_deps",
diff --git a/src/protozero/proto_decoder_unittest.cc b/src/protozero/proto_decoder_unittest.cc
index 6f0eda2..12f48dc 100644
--- a/src/protozero/proto_decoder_unittest.cc
+++ b/src/protozero/proto_decoder_unittest.cc
@@ -21,7 +21,7 @@
#include "perfetto/base/utils.h"
#include "perfetto/protozero/message.h"
#include "perfetto/protozero/proto_utils.h"
-#include "src/protozero/scattered_stream_delegate_for_testing.h"
+#include "perfetto/protozero/scattered_stream_memory_delegate.h"
namespace protozero {
namespace {
@@ -33,7 +33,7 @@
TEST(ProtoDecoder, ReadString) {
Message message;
- perfetto::ScatteredStreamDelegateForTesting delegate(512);
+ perfetto::ScatteredStreamMemoryDelegate delegate(512);
ScatteredStreamWriter writer(&delegate);
delegate.set_writer(&writer);
message.Reset(&writer);
diff --git a/src/protozero/scattered_stream_delegate_for_testing.cc b/src/protozero/scattered_stream_memory_delegate.cc
similarity index 78%
rename from src/protozero/scattered_stream_delegate_for_testing.cc
rename to src/protozero/scattered_stream_memory_delegate.cc
index ce474ff..63e078f 100644
--- a/src/protozero/scattered_stream_delegate_for_testing.cc
+++ b/src/protozero/scattered_stream_memory_delegate.cc
@@ -14,18 +14,16 @@
* limitations under the License.
*/
-#include "src/protozero/scattered_stream_delegate_for_testing.h"
+#include "perfetto/protozero/scattered_stream_memory_delegate.h"
namespace perfetto {
-ScatteredStreamDelegateForTesting::ScatteredStreamDelegateForTesting(
- size_t chunk_size)
+ScatteredStreamMemoryDelegate::ScatteredStreamMemoryDelegate(size_t chunk_size)
: chunk_size_(chunk_size) {}
-ScatteredStreamDelegateForTesting::~ScatteredStreamDelegateForTesting() {}
+ScatteredStreamMemoryDelegate::~ScatteredStreamMemoryDelegate() {}
-protozero::ContiguousMemoryRange
-ScatteredStreamDelegateForTesting::GetNewBuffer() {
+protozero::ContiguousMemoryRange ScatteredStreamMemoryDelegate::GetNewBuffer() {
PERFETTO_CHECK(writer_);
if (!chunks_.empty()) {
size_t used = chunk_size_ - writer_->bytes_available();
@@ -38,7 +36,7 @@
return {begin, begin + chunk_size_};
}
-std::vector<uint8_t> ScatteredStreamDelegateForTesting::StitchChunks() {
+std::vector<uint8_t> ScatteredStreamMemoryDelegate::StitchChunks() {
std::vector<uint8_t> buffer;
size_t i = 0;
for (const auto& chunk : chunks_) {
diff --git a/src/trace_processor/BUILD.gn b/src/trace_processor/BUILD.gn
index 497e020..72d22b4 100644
--- a/src/trace_processor/BUILD.gn
+++ b/src/trace_processor/BUILD.gn
@@ -163,6 +163,7 @@
"slice_tracker_unittest.cc",
"span_join_operator_table_unittest.cc",
"thread_table_unittest.cc",
+ "trace_processor_impl_unittest.cc",
"trace_sorter_unittest.cc",
]
deps = [
diff --git a/src/trace_processor/json_trace_parser.cc b/src/trace_processor/json_trace_parser.cc
index e7a8002..245348c 100644
--- a/src/trace_processor/json_trace_parser.cc
+++ b/src/trace_processor/json_trace_parser.cc
@@ -82,9 +82,6 @@
} // namespace
-// static
-constexpr char JsonTraceParser::kPreamble[];
-
JsonTraceParser::JsonTraceParser(TraceProcessorContext* context)
: context_(context) {}
@@ -97,12 +94,19 @@
const char* end = &buffer_[buffer_.size()];
if (offset_ == 0) {
- if (strncmp(buf, kPreamble, strlen(kPreamble))) {
- buf[strlen(kPreamble)] = '\0';
- PERFETTO_FATAL("Invalid trace preamble, expecting '%s' got '%s'",
- kPreamble, buf);
+ // Trace could begin in any of these ways:
+ // {"traceEvents":[{
+ // { "traceEvents": [{
+ // [{
+ // Skip up to the first '['
+ while (next != end && *next != '[') {
+ next++;
}
- next += strlen(kPreamble);
+ if (next == end) {
+ PERFETTO_ELOG("Failed to parse: first chunk missing opening [");
+ return false;
+ }
+ next++;
}
ProcessTracker* procs = context_->process_tracker.get();
@@ -123,8 +127,8 @@
uint32_t tid = value["tid"].asUInt();
uint32_t pid = value["pid"].asUInt();
uint64_t ts = value["ts"].asLargestUInt() * 1000;
- const char* cat = value["cat"].asCString();
- const char* name = value["name"].asCString();
+ const char* cat = value.isMember("cat") ? value["cat"].asCString() : "";
+ const char* name = value.isMember("name") ? value["name"].asCString() : "";
StringId cat_id = storage->InternString(cat);
StringId name_id = storage->InternString(name);
UniqueTid utid = procs->UpdateThread(tid, pid);
diff --git a/src/trace_processor/json_trace_parser.h b/src/trace_processor/json_trace_parser.h
index b0e39ec..bdd9378 100644
--- a/src/trace_processor/json_trace_parser.h
+++ b/src/trace_processor/json_trace_parser.h
@@ -35,8 +35,6 @@
// and supports only explicit TRACE_EVENT_BEGIN/END events.
class JsonTraceParser : public ChunkedTraceReader {
public:
- static constexpr char kPreamble[] = "{\"traceEvents\":[";
-
explicit JsonTraceParser(TraceProcessorContext*);
~JsonTraceParser() override;
diff --git a/src/trace_processor/proto_trace_parser.cc b/src/trace_processor/proto_trace_parser.cc
index 815deb1..f7e6a12 100644
--- a/src/trace_processor/proto_trace_parser.cc
+++ b/src/trace_processor/proto_trace_parser.cc
@@ -442,7 +442,14 @@
}
}
- UniquePid upid = context_->process_tracker->UpdateProcess(pid);
+ UniqueTid utid = context_->process_tracker->UpdateThread(ts, pid, 0);
+ UniquePid upid = context_->storage->GetThread(utid).upid;
+ if (upid == 0) {
+ PERFETTO_DLOG("Could not find process associated with utid %" PRIu32
+ " when parsing mem counters.",
+ utid);
+ return;
+ }
// Skip field_id 0 (invalid) and 1 (pid).
for (size_t field_id = 2; field_id < counter_values.size(); field_id++) {
@@ -658,8 +665,16 @@
return;
}
UniqueTid utid = context_->process_tracker->UpdateThread(timestamp, pid, 0);
+ UniquePid upid = context_->storage->GetThread(utid).upid;
+ if (upid == 0) {
+ PERFETTO_DLOG("Could not find process associated with utid %" PRIu32
+ " when parsing rss stat.",
+ utid);
+ return;
+ }
+
context_->event_tracker->PushCounter(timestamp, size, rss_members_[member],
- utid, RefType::kUtid);
+ upid, RefType::kUpid);
PERFETTO_DCHECK(decoder.IsEndOfBuffer());
}
diff --git a/src/trace_processor/trace_database_integrationtest.cc b/src/trace_processor/trace_database_integrationtest.cc
index f799748..6f16140 100644
--- a/src/trace_processor/trace_database_integrationtest.cc
+++ b/src/trace_processor/trace_database_integrationtest.cc
@@ -78,7 +78,7 @@
}
TEST_F(TraceProcessorIntegrationTest, Sfgate) {
- ASSERT_TRUE(LoadTrace("sfgate.json", strlen(JsonTraceParser::kPreamble)));
+ ASSERT_TRUE(LoadTrace("sfgate.json", strlen("{\"traceEvents\":[")));
protos::RawQueryResult res;
Query("select count(*), max(ts) - min(ts) from slices where utid != 0", &res);
ASSERT_EQ(res.num_records(), 1);
@@ -86,6 +86,11 @@
ASSERT_EQ(res.columns(1).long_values(0), 40532506000);
}
+// TODO(hjd): Add trace to test_data.
+TEST_F(TraceProcessorIntegrationTest, DISABLED_AndroidBuildTrace) {
+ ASSERT_TRUE(LoadTrace("android_build_trace.json", strlen("[\n{")));
+}
+
} // namespace
} // namespace trace_processor
} // namespace perfetto
diff --git a/src/trace_processor/trace_processor_impl.cc b/src/trace_processor/trace_processor_impl.cc
index 0cc58e4..7189c1b 100644
--- a/src/trace_processor/trace_processor_impl.cc
+++ b/src/trace_processor/trace_processor_impl.cc
@@ -17,6 +17,7 @@
#include "src/trace_processor/trace_processor_impl.h"
#include <sqlite3.h>
+#include <algorithm>
#include <functional>
#include "perfetto/base/time.h"
@@ -58,6 +59,32 @@
namespace perfetto {
namespace trace_processor {
+namespace {
+
+bool IsPrefix(const std::string& a, const std::string& b) {
+ return a.size() <= b.size() && b.substr(0, a.size()) == a;
+}
+
+std::string RemoveWhitespace(const std::string& input) {
+ std::string str(input);
+ str.erase(std::remove_if(str.begin(), str.end(), ::isspace), str.end());
+ return str;
+}
+
+} // namespace
+
+TraceType GuessTraceType(const uint8_t* data, size_t size) {
+ if (size == 0)
+ return kUnknownTraceType;
+ std::string start(reinterpret_cast<const char*>(data),
+ std::min<size_t>(size, 20));
+ std::string start_minus_white_space = RemoveWhitespace(start);
+ if (IsPrefix("{\"traceEvents\":[", start_minus_white_space))
+ return kJsonTraceType;
+ if (IsPrefix("[{", start_minus_white_space))
+ return kJsonTraceType;
+ return kProtoTraceType;
+}
TraceProcessorImpl::TraceProcessorImpl(const Config& cfg) {
sqlite3* db = nullptr;
@@ -96,15 +123,17 @@
// If this is the first Parse() call, guess the trace type and create the
// appropriate parser.
if (!context_.chunk_reader) {
- char buf[32];
- memcpy(buf, &data[0], std::min(size, sizeof(buf)));
- buf[sizeof(buf) - 1] = '\0';
- const size_t kPreambleLen = strlen(JsonTraceParser::kPreamble);
- if (strncmp(buf, JsonTraceParser::kPreamble, kPreambleLen) == 0) {
- PERFETTO_DLOG("Legacy JSON trace detected");
- context_.chunk_reader.reset(new JsonTraceParser(&context_));
- } else {
- context_.chunk_reader.reset(new ProtoTraceTokenizer(&context_));
+ TraceType trace_type = GuessTraceType(data.get(), size);
+ switch (trace_type) {
+ case kJsonTraceType:
+ PERFETTO_DLOG("Legacy JSON trace detected");
+ context_.chunk_reader.reset(new JsonTraceParser(&context_));
+ break;
+ case kProtoTraceType:
+ context_.chunk_reader.reset(new ProtoTraceTokenizer(&context_));
+ break;
+ case kUnknownTraceType:
+ return false;
}
}
diff --git a/src/trace_processor/trace_processor_impl.h b/src/trace_processor/trace_processor_impl.h
index 74ccb97..25eba7e 100644
--- a/src/trace_processor/trace_processor_impl.h
+++ b/src/trace_processor/trace_processor_impl.h
@@ -35,6 +35,14 @@
namespace trace_processor {
+enum TraceType {
+ kUnknownTraceType,
+ kProtoTraceType,
+ kJsonTraceType,
+};
+
+TraceType GuessTraceType(const uint8_t* data, size_t size);
+
// Coordinates the loading of traces from an arbitrary source and allows
// execution of SQL queries on the events in these traces.
class TraceProcessorImpl : public TraceProcessor {
diff --git a/src/trace_processor/trace_processor_impl_unittest.cc b/src/trace_processor/trace_processor_impl_unittest.cc
new file mode 100644
index 0000000..a901de6
--- /dev/null
+++ b/src/trace_processor/trace_processor_impl_unittest.cc
@@ -0,0 +1,53 @@
+/*
+ * 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/trace_processor_impl.h"
+
+#include "gmock/gmock.h"
+#include "gtest/gtest.h"
+
+namespace perfetto {
+namespace trace_processor {
+namespace {
+
+TEST(TraceProcessorImpl, GuessTraceType_Empty) {
+ const uint8_t prefix[] = "";
+ EXPECT_EQ(kUnknownTraceType, GuessTraceType(prefix, 0));
+}
+
+TEST(TraceProcessorImpl, GuessTraceType_Json) {
+ const uint8_t prefix[] = "{\"traceEvents\":[";
+ EXPECT_EQ(kJsonTraceType, GuessTraceType(prefix, sizeof(prefix)));
+}
+
+TEST(TraceProcessorImpl, GuessTraceType_JsonWithSpaces) {
+ const uint8_t prefix[] = "\n{ \"traceEvents\": [";
+ EXPECT_EQ(kJsonTraceType, GuessTraceType(prefix, sizeof(prefix)));
+}
+
+TEST(TraceProcessorImpl, GuessTraceType_JsonMissingTraceEvents) {
+ const uint8_t prefix[] = "[{";
+ EXPECT_EQ(kJsonTraceType, GuessTraceType(prefix, sizeof(prefix)));
+}
+
+TEST(TraceProcessorImpl, GuessTraceType_Proto) {
+ const uint8_t prefix[] = {0x0a, 0x65, 0x18, 0x8f, 0x4e, 0x32, 0x60, 0x0a};
+ EXPECT_EQ(kProtoTraceType, GuessTraceType(prefix, sizeof(prefix)));
+}
+
+} // namespace
+} // namespace trace_processor
+} // namespace perfetto
diff --git a/src/traced/probes/ftrace/BUILD.gn b/src/traced/probes/ftrace/BUILD.gn
index 5569a56..8cddd4c 100644
--- a/src/traced/probes/ftrace/BUILD.gn
+++ b/src/traced/probes/ftrace/BUILD.gn
@@ -32,7 +32,7 @@
"../../../protozero",
]
public_deps = [
- "../../../protozero:test_support",
+ "../../../protozero",
]
sources = [
diff --git a/src/traced/probes/ftrace/cpu_reader_unittest.cc b/src/traced/probes/ftrace/cpu_reader_unittest.cc
index 048eb41..c60c123 100644
--- a/src/traced/probes/ftrace/cpu_reader_unittest.cc
+++ b/src/traced/probes/ftrace/cpu_reader_unittest.cc
@@ -25,8 +25,8 @@
#include "perfetto/base/build_config.h"
#include "perfetto/base/utils.h"
+#include "perfetto/protozero/scattered_stream_memory_delegate.h"
#include "perfetto/protozero/scattered_stream_writer.h"
-#include "src/protozero/scattered_stream_delegate_for_testing.h"
#include "perfetto/trace/ftrace/ftrace_event.pb.h"
#include "perfetto/trace/ftrace/ftrace_event.pbzero.h"
@@ -99,7 +99,7 @@
ProtoProvider& operator=(const ProtoProvider&) = delete;
size_t chunk_size_;
- ScatteredStreamDelegateForTesting delegate_;
+ ScatteredStreamMemoryDelegate delegate_;
protozero::ScatteredStreamWriter stream_;
ZeroT writer_;
};
diff --git a/src/traced/probes/ftrace/format_parser.cc b/src/traced/probes/ftrace/format_parser.cc
index 92a9e55..6cb1ee3 100644
--- a/src/traced/probes/ftrace/format_parser.cc
+++ b/src/traced/probes/ftrace/format_parser.cc
@@ -21,7 +21,6 @@
#include <iosfwd>
#include <iostream>
#include <memory>
-#include <regex>
#include <string>
#include <vector>
diff --git a/src/tracing/BUILD.gn b/src/tracing/BUILD.gn
index ac15a35..5e622ab 100644
--- a/src/tracing/BUILD.gn
+++ b/src/tracing/BUILD.gn
@@ -125,7 +125,7 @@
"../../include/perfetto/tracing/core",
"../../protos/perfetto/trace:lite",
"../../protos/perfetto/trace:zero",
- "../protozero:test_support",
+ "../protozero",
]
sources = [
"core/trace_writer_for_testing.cc",
diff --git a/src/tracing/core/trace_writer_for_testing.h b/src/tracing/core/trace_writer_for_testing.h
index 2025963..f667e31 100644
--- a/src/tracing/core/trace_writer_for_testing.h
+++ b/src/tracing/core/trace_writer_for_testing.h
@@ -17,18 +17,18 @@
#define SRC_TRACING_CORE_TRACE_WRITER_FOR_TESTING_H_
#include "perfetto/protozero/message_handle.h"
+#include "perfetto/protozero/scattered_stream_memory_delegate.h"
#include "perfetto/trace/trace_packet.pb.h"
#include "perfetto/tracing/core/trace_writer.h"
-#include "src/protozero/scattered_stream_delegate_for_testing.h"
namespace perfetto {
// A specialization of TraceWriter for testing which writes into memory
-// allocated by the ScatteredStreamDelegateForTesting.
+// allocated by the ScatteredStreamMemoryDelegate.
// See //include/perfetto/tracing/core/trace_writer.h for docs.
class TraceWriterForTesting : public TraceWriter {
public:
- // TraceWriterForTesting(const ScatteredStreamDelegateForTesting& delegate);
+ // TraceWriterForTesting(const ScatteredStreamMemoryDelegate& delegate);
TraceWriterForTesting();
~TraceWriterForTesting() override;
@@ -45,7 +45,7 @@
TraceWriterForTesting(const TraceWriterForTesting&) = delete;
TraceWriterForTesting& operator=(const TraceWriterForTesting&) = delete;
- ScatteredStreamDelegateForTesting delegate_;
+ ScatteredStreamMemoryDelegate delegate_;
protozero::ScatteredStreamWriter stream_;
// The packet returned via NewTracePacket(). Its owned by this class,
diff --git a/tools/ftrace_proto_gen/ftrace_proto_gen.cc b/tools/ftrace_proto_gen/ftrace_proto_gen.cc
index 8b47cf4..484e0ad 100644
--- a/tools/ftrace_proto_gen/ftrace_proto_gen.cc
+++ b/tools/ftrace_proto_gen/ftrace_proto_gen.cc
@@ -406,6 +406,7 @@
// TODO: Figure out a story for reconciling the various clocks.
optional uint64 timestamp = 1;
+ // Kernel pid (do not confuse with userspace pid aka tgid)
optional uint32 pid = 2;
oneof event {
diff --git a/tools/gen_binary_descriptors b/tools/gen_binary_descriptors
new file mode 100755
index 0000000..513ef95
--- /dev/null
+++ b/tools/gen_binary_descriptors
@@ -0,0 +1,135 @@
+#!/usr/bin/env python
+# 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.
+
+from __future__ import absolute_import
+from __future__ import division
+from __future__ import print_function
+import os
+import re
+import sys
+import argparse
+import tempfile
+import subprocess
+import hashlib
+import textwrap
+
+SOURCE_TARGET = {
+ 'protos/perfetto/config/perfetto_config.proto':
+ 'src/perfetto_cmd/perfetto_config.descriptor.h',
+}
+
+ROOT_DIR = os.path.dirname(os.path.dirname(os.path.realpath(__file__)))
+
+SCRIPT_PATH = 'tools/gen_binary_descriptors'
+
+def hash_path(path):
+ hash = hashlib.sha1()
+ with open(os.path.join(ROOT_DIR, path)) as f:
+ hash.update(f.read())
+ return hash.hexdigest()
+
+
+def check(source, target):
+ assert os.path.exists(os.path.join(ROOT_DIR, target))
+
+ with open(target, 'rb') as f:
+ s = f.read()
+
+ hashes = re.findall(r'// SHA1\((.*)\)\n// (.*)\n', s)
+ assert sorted([SCRIPT_PATH, source]) == sorted([key for key, _ in hashes])
+ for path, expected_sha1 in hashes:
+ actual_sha1 = hash_path(os.path.join(ROOT_DIR, path))
+ assert actual_sha1 == expected_sha1, \
+ 'Hash for path {} did not match'.format(path)
+
+
+def generate(source, target, protoc_path):
+ _, source_name = os.path.split(source)
+ _, target_name = os.path.split(target)
+ assert source_name.replace('.proto', '.descriptor.h') == target_name
+
+ with tempfile.NamedTemporaryFile() as fdescriptor:
+ subprocess.check_call([
+ protoc_path,
+ '--proto_path=protos',
+ '-o{}'.format(fdescriptor.name),
+ source,
+ ], cwd=ROOT_DIR)
+
+ s = fdescriptor.read()
+ constant_name = 'k' + target_name.title()[:-2].translate(None, '._')
+ binary = '{' + ', '.join('{0:#04x}'.format(ord(c)) for c in s) + '}'
+ binary = textwrap.fill(binary,
+ width=80,
+ initial_indent=' ',
+ subsequent_indent=' ')
+ include_guard = target.replace('/', '_').replace('.', '_').upper() + '_'
+
+ with open(os.path.join(ROOT_DIR, target), 'wb') as f:
+ f.write("""
+#ifndef {include_guard}
+#define {include_guard}
+
+#include <stddef.h>
+#include <stdint.h>
+
+#include <array>
+
+// This file was autogenerated by tools/gen_binary_descriptors. Do not edit.
+
+// SHA1({script_path})
+// {script_hash}
+// SHA1({source_path})
+// {source_hash}
+
+// This is the proto {{proto_name}} encoded as a ProtoFileDescriptor to allow
+// for reflection without libprotobuf full/non-lite protos.
+
+namespace perfetto {{
+
+constexpr std::array<uint8_t, {size}> {constant_name}{{
+{binary}}};
+
+}} // namespace perfetto
+
+#endif // {include_guard}
+""".format(**{
+ 'size': len(s),
+ 'constant_name': constant_name,
+ 'binary': binary,
+ 'include_guard': include_guard,
+ 'script_path': SCRIPT_PATH,
+ 'script_hash': hash_path(__file__),
+ 'source_path': source,
+ 'source_hash': hash_path(os.path.join(source)),
+ }))
+
+
+def main():
+ parser = argparse.ArgumentParser()
+ parser.add_argument('--check-only', action='store_true')
+ parser.add_argument('--protoc')
+ args = parser.parse_args()
+
+ for source, target in SOURCE_TARGET.iteritems():
+ if args.check_only:
+ check(source, target)
+ else:
+ protoc = args.protoc
+ assert os.path.exists(protoc)
+ generate(source, target, args.protoc)
+
+if __name__ == '__main__':
+ exit(main())
diff --git a/tools/gen_merged_protos b/tools/gen_merged_protos
index c99f845..b2a1ad11 100755
--- a/tools/gen_merged_protos
+++ b/tools/gen_merged_protos
@@ -18,7 +18,6 @@
from __future__ import print_function
import os
import re
-import subprocess
import sys
CONFIG_PROTOS = (
@@ -155,7 +154,6 @@
used_type = use.group(2)
field_number = use.group(3)
if used_type not in types:
- # replacement = '{}reserved {};'.format(indentation, field_number)
replacement = '{}// removed field with id {}'.format(
indentation, field_number)
substitutions.append((everything, replacement))
diff --git a/tools/tmux b/tools/tmux
index 3afdb0c..ff12b42 100755
--- a/tools/tmux
+++ b/tools/tmux
@@ -116,7 +116,8 @@
fi
CONFIG_DEVICE_PATH=$CONFIG
-if [[ "$CONFIG" != ":test" ]]; then
+CMD_OPTS=""
+if [[ "$CONFIG" == *.protobuf ]]; then
CONFIG_DEVICE_PATH=$DIR/$CONFIG.protobuf
CONFIG_PATH=$OUT/$CONFIG.protobuf;
if [[ ! -f $CONFIG_PATH ]]; then
@@ -124,6 +125,15 @@
exit 1
fi
push $CONFIG_PATH
+elif [[ "$CONFIG" != ":test" ]]; then
+ CONFIG_DEVICE_PATH=$DIR/$CONFIG
+ CONFIG_PATH=test/configs/$CONFIG;
+ if [[ ! -f $CONFIG_PATH ]]; then
+ echo 'Config "'$CONFIG_PATH'" not known.'
+ exit 1
+ fi
+ CMD_OPTS="--txt $CMD_OPTS"
+ push $CONFIG_PATH
fi
POSTFIX=""
@@ -179,7 +189,7 @@
tmux send-keys "$PREFIX PERFETTO_METATRACE_FILE=$DIR/mtrace $DIR/traced_probes $POSTFIX" Enter
tmux select-pane -t 2
-tmux send-keys "$PREFIX $DIR/perfetto -c $CONFIG_DEVICE_PATH -o $DIR/trace $POSTFIX"
+tmux send-keys "$PREFIX $DIR/perfetto $CMD_OPTS -c $CONFIG_DEVICE_PATH -o $DIR/trace $POSTFIX"
# Select consumer pane.
tmux select-pane -t 2
diff --git a/ui/src/controller/engine.ts b/ui/src/controller/engine.ts
index e3b2c5e..8a61936 100644
--- a/ui/src/controller/engine.ts
+++ b/ui/src/controller/engine.ts
@@ -77,10 +77,16 @@
}
async getTraceTimeBounds(): Promise<TimeSpan> {
- const maxQuery = 'select max(ts) from (select max(ts) as ts from sched ' +
- 'union all select max(ts) as ts from slices)';
- const minQuery = 'select min(ts) from (select min(ts) as ts from sched ' +
- 'union all select min(ts) as ts from slices)';
+ const maxQuery = `select max(ts) from (
+ select max(ts) as ts from sched
+ union all select max(ts) as ts from slices
+ union all select max(ts) as ts from counters
+ )`;
+ const minQuery = `select min(ts) from (
+ select min(ts) as ts from sched
+ union all select min(ts) as ts from slices
+ union all select min(ts) as ts from counters
+ )`;
const start = (await this.queryOneRow(minQuery))[0];
const end = (await this.queryOneRow(maxQuery))[0];
return new TimeSpan(start / 1e9, end / 1e9);