commit
320d56c833
6 changed files with 584 additions and 53 deletions
@ -0,0 +1,105 @@ |
|||||||
|
#include "benchmarks.pb.h" |
||||||
|
#include "datasets/google_message1/proto2/benchmark_message1_proto2.pb.h" |
||||||
|
#include "datasets/google_message1/proto3/benchmark_message1_proto3.pb.h" |
||||||
|
#include "datasets/google_message2/benchmark_message2.pb.h" |
||||||
|
#include "datasets/google_message3/benchmark_message3.pb.h" |
||||||
|
#include "datasets/google_message4/benchmark_message4.pb.h" |
||||||
|
|
||||||
|
#include "google/protobuf/message.h" |
||||||
|
#include "google/protobuf/descriptor.h" |
||||||
|
|
||||||
|
#include <fstream> |
||||||
|
|
||||||
|
using google::protobuf::FieldDescriptor; |
||||||
|
using google::protobuf::Message; |
||||||
|
using google::protobuf::Reflection; |
||||||
|
|
||||||
|
|
||||||
|
class DataGroupStripper { |
||||||
|
public: |
||||||
|
static void StripMessage(Message *message) { |
||||||
|
std::vector<const FieldDescriptor*> set_fields; |
||||||
|
const Reflection* reflection = message->GetReflection(); |
||||||
|
reflection->ListFields(*message, &set_fields); |
||||||
|
|
||||||
|
for (size_t i = 0; i < set_fields.size(); i++) { |
||||||
|
const FieldDescriptor* field = set_fields[i]; |
||||||
|
if (field->type() == FieldDescriptor::TYPE_GROUP) { |
||||||
|
reflection->ClearField(message, field); |
||||||
|
} |
||||||
|
if (field->type() == FieldDescriptor::TYPE_MESSAGE) { |
||||||
|
if (field->is_repeated()) { |
||||||
|
for (int j = 0; j < reflection->FieldSize(*message, field); j++) { |
||||||
|
StripMessage(reflection->MutableRepeatedMessage(message, field, j)); |
||||||
|
} |
||||||
|
} else { |
||||||
|
StripMessage(reflection->MutableMessage(message, field)); |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
reflection->MutableUnknownFields(message)->Clear(); |
||||||
|
} |
||||||
|
}; |
||||||
|
|
||||||
|
std::string ReadFile(const std::string& name) { |
||||||
|
std::ifstream file(name.c_str()); |
||||||
|
GOOGLE_CHECK(file.is_open()) << "Couldn't find file '" |
||||||
|
<< name |
||||||
|
<< "', please make sure you are running this command from the benchmarks" |
||||||
|
<< " directory.\n"; |
||||||
|
return std::string((std::istreambuf_iterator<char>(file)), |
||||||
|
std::istreambuf_iterator<char>()); |
||||||
|
} |
||||||
|
|
||||||
|
int main(int argc, char *argv[]) { |
||||||
|
if (argc % 2 == 0 || argc == 1) { |
||||||
|
std::cerr << "Usage: [input_files] [output_file_names] where " << |
||||||
|
"input_files are one to one mapping to output_file_names." << |
||||||
|
std::endl; |
||||||
|
return 1; |
||||||
|
} |
||||||
|
|
||||||
|
for (int i = argc / 2; i > 0; i--) { |
||||||
|
const std::string &input_file = argv[i]; |
||||||
|
const std::string &output_file = argv[i + argc / 2]; |
||||||
|
|
||||||
|
std::cerr << "Generating " << input_file |
||||||
|
<< " to " << output_file << std::endl; |
||||||
|
benchmarks::BenchmarkDataset dataset; |
||||||
|
Message* message; |
||||||
|
std::string dataset_payload = ReadFile(input_file); |
||||||
|
GOOGLE_CHECK(dataset.ParseFromString(dataset_payload)) |
||||||
|
<< "Can' t parse data file " << input_file; |
||||||
|
|
||||||
|
if (dataset.message_name() == "benchmarks.proto3.GoogleMessage1") { |
||||||
|
message = new benchmarks::proto3::GoogleMessage1; |
||||||
|
} else if (dataset.message_name() == "benchmarks.proto2.GoogleMessage1") { |
||||||
|
message = new benchmarks::proto2::GoogleMessage1; |
||||||
|
} else if (dataset.message_name() == "benchmarks.proto2.GoogleMessage2") { |
||||||
|
message = new benchmarks::proto2::GoogleMessage2; |
||||||
|
} else if (dataset.message_name() == |
||||||
|
"benchmarks.google_message3.GoogleMessage3") { |
||||||
|
message = new benchmarks::google_message3::GoogleMessage3; |
||||||
|
} else if (dataset.message_name() == |
||||||
|
"benchmarks.google_message4.GoogleMessage4") { |
||||||
|
message = new benchmarks::google_message4::GoogleMessage4; |
||||||
|
} else { |
||||||
|
std::cerr << "Unknown message type: " << dataset.message_name(); |
||||||
|
exit(1); |
||||||
|
} |
||||||
|
|
||||||
|
for (int i = 0; i < dataset.payload_size(); i++) { |
||||||
|
message->ParseFromString(dataset.payload(i)); |
||||||
|
DataGroupStripper::StripMessage(message); |
||||||
|
dataset.set_payload(i, message->SerializeAsString()); |
||||||
|
} |
||||||
|
|
||||||
|
std::ofstream ofs(output_file); |
||||||
|
ofs << dataset.SerializeAsString(); |
||||||
|
ofs.close(); |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
return 0; |
||||||
|
} |
@ -0,0 +1,103 @@ |
|||||||
|
#include "google/protobuf/compiler/code_generator.h" |
||||||
|
#include "google/protobuf/io/zero_copy_stream.h" |
||||||
|
#include "google/protobuf/io/printer.h" |
||||||
|
#include "google/protobuf/descriptor.h" |
||||||
|
#include "google/protobuf/descriptor.pb.h" |
||||||
|
#include "schema_proto2_to_proto3_util.h" |
||||||
|
|
||||||
|
#include "google/protobuf/compiler/plugin.h" |
||||||
|
|
||||||
|
using google::protobuf::FileDescriptorProto; |
||||||
|
using google::protobuf::FileDescriptor; |
||||||
|
using google::protobuf::DescriptorPool; |
||||||
|
using google::protobuf::io::Printer; |
||||||
|
using google::protobuf::util::SchemaGroupStripper; |
||||||
|
using google::protobuf::util::SchemaAddZeroEnumValue; |
||||||
|
|
||||||
|
namespace google { |
||||||
|
namespace protobuf { |
||||||
|
namespace compiler { |
||||||
|
|
||||||
|
namespace { |
||||||
|
|
||||||
|
string StripProto(string filename) { |
||||||
|
if (filename.substr(filename.size() - 11) == ".protodevel") { |
||||||
|
// .protodevel
|
||||||
|
return filename.substr(0, filename.size() - 11); |
||||||
|
} else { |
||||||
|
// .proto
|
||||||
|
return filename.substr(0, filename.size() - 6); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
DescriptorPool new_pool_; |
||||||
|
|
||||||
|
} // namespace
|
||||||
|
|
||||||
|
class GoGoProtoGenerator : public CodeGenerator { |
||||||
|
public: |
||||||
|
virtual bool GenerateAll(const std::vector<const FileDescriptor*>& files, |
||||||
|
const string& parameter, |
||||||
|
GeneratorContext* context, |
||||||
|
string* error) const { |
||||||
|
for (int i = 0; i < files.size(); i++) { |
||||||
|
for (auto file : files) { |
||||||
|
bool can_generate = |
||||||
|
(new_pool_.FindFileByName(file->name()) == nullptr); |
||||||
|
for (int j = 0; j < file->dependency_count(); j++) { |
||||||
|
can_generate &= (new_pool_.FindFileByName( |
||||||
|
file->dependency(j)->name()) != nullptr); |
||||||
|
} |
||||||
|
for (int j = 0; j < file->public_dependency_count(); j++) { |
||||||
|
can_generate &= (new_pool_.FindFileByName( |
||||||
|
file->public_dependency(j)->name()) != nullptr); |
||||||
|
} |
||||||
|
for (int j = 0; j < file->weak_dependency_count(); j++) { |
||||||
|
can_generate &= (new_pool_.FindFileByName( |
||||||
|
file->weak_dependency(j)->name()) != nullptr); |
||||||
|
} |
||||||
|
if (can_generate) { |
||||||
|
Generate(file, parameter, context, error); |
||||||
|
break; |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
return true; |
||||||
|
} |
||||||
|
|
||||||
|
virtual bool Generate(const FileDescriptor* file, |
||||||
|
const string& parameter, |
||||||
|
GeneratorContext* context, |
||||||
|
string* error) const { |
||||||
|
FileDescriptorProto new_file; |
||||||
|
file->CopyTo(&new_file); |
||||||
|
SchemaGroupStripper::StripFile(file, &new_file); |
||||||
|
|
||||||
|
SchemaAddZeroEnumValue enum_scrubber; |
||||||
|
enum_scrubber.ScrubFile(&new_file); |
||||||
|
|
||||||
|
string filename = file->name(); |
||||||
|
string basename = StripProto(filename); |
||||||
|
|
||||||
|
std::vector<std::pair<string,string>> option_pairs; |
||||||
|
ParseGeneratorParameter(parameter, &option_pairs); |
||||||
|
|
||||||
|
std::unique_ptr<google::protobuf::io::ZeroCopyOutputStream> output( |
||||||
|
context->Open(basename + ".proto")); |
||||||
|
string content = new_pool_.BuildFile(new_file)->DebugString(); |
||||||
|
Printer printer(output.get(), '$'); |
||||||
|
printer.WriteRaw(content.c_str(), content.size()); |
||||||
|
|
||||||
|
return true; |
||||||
|
} |
||||||
|
}; |
||||||
|
|
||||||
|
} // namespace compiler
|
||||||
|
} // namespace protobuf
|
||||||
|
} // namespace google
|
||||||
|
|
||||||
|
int main(int argc, char* argv[]) { |
||||||
|
google::protobuf::compiler::GoGoProtoGenerator generator; |
||||||
|
return google::protobuf::compiler::PluginMain(argc, argv, &generator); |
||||||
|
} |
@ -0,0 +1,137 @@ |
|||||||
|
#ifndef PROTOBUF_BENCHMARKS_UTIL_SCHEMA_PROTO2_TO_PROTO3_UTIL_H_ |
||||||
|
#define PROTOBUF_BENCHMARKS_UTIL_SCHEMA_PROTO2_TO_PROTO3_UTIL_H_ |
||||||
|
|
||||||
|
#include "google/protobuf/message.h" |
||||||
|
#include "google/protobuf/descriptor.h" |
||||||
|
#include "google/protobuf/descriptor.pb.h" |
||||||
|
|
||||||
|
#include <sstream> |
||||||
|
#include <algorithm> |
||||||
|
|
||||||
|
using google::protobuf::Descriptor; |
||||||
|
using google::protobuf::DescriptorProto; |
||||||
|
using google::protobuf::FileDescriptorProto; |
||||||
|
using google::protobuf::FieldDescriptorProto; |
||||||
|
using google::protobuf::Message; |
||||||
|
using google::protobuf::EnumValueDescriptorProto; |
||||||
|
|
||||||
|
namespace google { |
||||||
|
namespace protobuf { |
||||||
|
namespace util { |
||||||
|
|
||||||
|
class SchemaGroupStripper { |
||||||
|
|
||||||
|
public: |
||||||
|
static void StripFile(const FileDescriptor* old_file, |
||||||
|
FileDescriptorProto *file) { |
||||||
|
for (int i = file->mutable_message_type()->size() - 1; i >= 0; i--) { |
||||||
|
if (IsMessageSet(old_file->message_type(i))) { |
||||||
|
file->mutable_message_type()->DeleteSubrange(i, 1); |
||||||
|
continue; |
||||||
|
} |
||||||
|
StripMessage(old_file->message_type(i), file->mutable_message_type(i)); |
||||||
|
} |
||||||
|
for (int i = file->mutable_extension()->size() - 1; i >= 0; i--) { |
||||||
|
auto field = old_file->extension(i); |
||||||
|
if (field->type() == FieldDescriptor::TYPE_GROUP || |
||||||
|
IsMessageSet(field->message_type()) || |
||||||
|
IsMessageSet(field->containing_type())) { |
||||||
|
file->mutable_extension()->DeleteSubrange(i, 1); |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
private: |
||||||
|
static bool IsMessageSet(const Descriptor *descriptor) { |
||||||
|
if (descriptor != nullptr |
||||||
|
&& descriptor->options().message_set_wire_format()) { |
||||||
|
return true; |
||||||
|
} |
||||||
|
return false; |
||||||
|
} |
||||||
|
|
||||||
|
static void StripMessage(const Descriptor *old_message, |
||||||
|
DescriptorProto *new_message) { |
||||||
|
for (int i = new_message->mutable_field()->size() - 1; i >= 0; i--) { |
||||||
|
if (old_message->field(i)->type() == FieldDescriptor::TYPE_GROUP || |
||||||
|
IsMessageSet(old_message->field(i)->message_type())) { |
||||||
|
new_message->mutable_field()->DeleteSubrange(i, 1); |
||||||
|
} |
||||||
|
} |
||||||
|
for (int i = new_message->mutable_extension()->size() - 1; i >= 0; i--) { |
||||||
|
auto field_type_name = new_message->mutable_extension(i)->type_name(); |
||||||
|
if (old_message->extension(i)->type() == FieldDescriptor::TYPE_GROUP || |
||||||
|
IsMessageSet(old_message->extension(i)->containing_type()) || |
||||||
|
IsMessageSet(old_message->extension(i)->message_type())) { |
||||||
|
new_message->mutable_extension()->DeleteSubrange(i, 1); |
||||||
|
} |
||||||
|
} |
||||||
|
for (int i = 0; i < new_message->mutable_nested_type()->size(); i++) { |
||||||
|
StripMessage(old_message->nested_type(i), |
||||||
|
new_message->mutable_nested_type(i)); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
}; |
||||||
|
|
||||||
|
class SchemaAddZeroEnumValue { |
||||||
|
|
||||||
|
public: |
||||||
|
SchemaAddZeroEnumValue() |
||||||
|
: total_added_(0) { |
||||||
|
} |
||||||
|
|
||||||
|
void ScrubFile(FileDescriptorProto *file) { |
||||||
|
for (int i = 0; i < file->enum_type_size(); i++) { |
||||||
|
ScrubEnum(file->mutable_enum_type(i)); |
||||||
|
} |
||||||
|
for (int i = 0; i < file->mutable_message_type()->size(); i++) { |
||||||
|
ScrubMessage(file->mutable_message_type(i)); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
private: |
||||||
|
void ScrubEnum(EnumDescriptorProto *enum_type) { |
||||||
|
if (enum_type->value(0).number() != 0) { |
||||||
|
bool has_zero = false; |
||||||
|
for (int j = 0; j < enum_type->value().size(); j++) { |
||||||
|
if (enum_type->value(j).number() == 0) { |
||||||
|
EnumValueDescriptorProto temp_enum_value; |
||||||
|
temp_enum_value.CopyFrom(enum_type->value(j)); |
||||||
|
enum_type->mutable_value(j)->CopyFrom(enum_type->value(0)); |
||||||
|
enum_type->mutable_value(0)->CopyFrom(temp_enum_value); |
||||||
|
has_zero = true; |
||||||
|
break; |
||||||
|
} |
||||||
|
} |
||||||
|
if (!has_zero) { |
||||||
|
enum_type->mutable_value()->Add(); |
||||||
|
for (int i = enum_type->mutable_value()->size() - 1; i > 0; i--) { |
||||||
|
enum_type->mutable_value(i)->CopyFrom( |
||||||
|
*enum_type->mutable_value(i - 1)); |
||||||
|
} |
||||||
|
enum_type->mutable_value(0)->set_number(0); |
||||||
|
enum_type->mutable_value(0)->set_name("ADDED_ZERO_VALUE_" + |
||||||
|
std::to_string(total_added_++)); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
} |
||||||
|
|
||||||
|
void ScrubMessage(DescriptorProto *message_type) { |
||||||
|
for (int i = 0; i < message_type->mutable_enum_type()->size(); i++) { |
||||||
|
ScrubEnum(message_type->mutable_enum_type(i)); |
||||||
|
} |
||||||
|
for (int i = 0; i < message_type->mutable_nested_type()->size(); i++) { |
||||||
|
ScrubMessage(message_type->mutable_nested_type(i)); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
int total_added_; |
||||||
|
}; |
||||||
|
|
||||||
|
} // namespace util
|
||||||
|
} // namespace protobuf
|
||||||
|
} // namespace google
|
||||||
|
|
||||||
|
#endif // PROTOBUF_BENCHMARKS_UTIL_SCHEMA_PROTO2_TO_PROTO3_UTIL_H_
|
Loading…
Reference in new issue