Commit 39f7c8f7 authored by Giorgio Azzinnaro's avatar Giorgio Azzinnaro

renamed ParseMessage, moving .proto parsing at boot

parent f931fdcf
......@@ -36,7 +36,7 @@ profanedb::protobuf::GetResp profanedb::storage::Db::Get(const profanedb::protob
profanedb::protobuf::PutResp profanedb::storage::Db::Put(const profanedb::protobuf::PutReq & request)
{
auto map = parser.ParseMessage(request.serializable());
auto map = parser.NormalizeMessage(request.serializable());
for (auto const & obj: map) {
std::cout << obj.first << ":" << std::endl << obj.second.SerializeAsString() << std::endl;
......
......@@ -49,8 +49,14 @@ profanedb::storage::Parser::Parser()
for (auto const & file: boost::filesystem::recursive_directory_iterator(path, boost::filesystem::symlink_option::recurse)) {
if (file.path().extension() == ".proto") {
// For the pool every file is relative to the mapping provided before (kDbSchema)
pool->FindFileByName(file.path().lexically_relative(kDbSchema).native());
const FileDescriptor * fileD = pool->FindFileByName(file.path().lexically_relative(kDbSchema).native());
for (int i = 0; i < fileD->message_type_count(); i++) {
const Descriptor * message = fileD->message_type(i);
ParseMessageDescriptor(*message);
}
// TODO Here should load all the messages, find the keys and nested messages, and generate Descriptors with references to save in DB
}
}
......@@ -60,7 +66,39 @@ profanedb::storage::Parser::~Parser()
{
}
map< std::string, const google::protobuf::Message & > profanedb::storage::Parser::ParseMessage(const google::protobuf::Any & serializable)
bool profanedb::storage::Parser::ParseMessageDescriptor(const google::protobuf::Descriptor & descriptor)
{
// A DescriptorProto is needed to generate the message the way it will be serialized,
// with keys replacing
auto * descriptorProto = new google::protobuf::DescriptorProto();
descriptor.CopyTo(descriptorProto);
bool hasKey = false;
for (int k = 0; k < descriptor.field_count(); k++) {
const FieldDescriptor * field = descriptor.field(k);
// Recursively call this function to add all nested messages
const google::protobuf::Descriptor * nested = field->message_type();
if (nested != NULL) {
if (ParseMessageDescriptor(*nested)) {
// If the nested message has a primary key, set the field to string to hold a reference
std::cout << descriptorProto->mutable_field(k)->DebugString() << std::endl;
descriptorProto->mutable_field(k)->set_type(FieldDescriptorProto_Type_TYPE_STRING);
}
}
profanedb::protobuf::FieldOptions options = field->options().GetExtension(profanedb::protobuf::options);
if (options.key()) {
hasKey = true;
}
}
return hasKey;
}
map< std::string, const google::protobuf::Message & > profanedb::storage::Parser::NormalizeMessage(const google::protobuf::Any & serializable)
{
// The Descriptor is manually extracted from the pool,
// removing the prepending `type.googleapis.com/` in the Any message
......@@ -70,10 +108,10 @@ map< std::string, const google::protobuf::Message & > profanedb::storage::Parser
Message * container = messageFactory.GetPrototype(definition)->New();
serializable.UnpackTo(container);
return ParseMessage(*container);
return NormalizeMessage(*container);
}
map< std::string, const google::protobuf::Message & > profanedb::storage::Parser::ParseMessage(const google::protobuf::Message & message)
map< std::string, const google::protobuf::Message & > profanedb::storage::Parser::NormalizeMessage(const google::protobuf::Message & message)
{
auto dependencies = new map<std::string, const google::protobuf::Message &>();
......@@ -88,9 +126,9 @@ map< std::string, const google::protobuf::Message & > profanedb::storage::Parser
for (auto const & fd: *fields) {
if (fd->message_type() != NULL) {
auto nested = ParseMessage(message.GetReflection()->GetMessage(message, fd, &messageFactory));
auto nested = NormalizeMessage(message.GetReflection()->GetMessage(message, fd, &messageFactory));
// TODO If nested has primary key set a reference
// TODO If first nested message has primary key set a reference
if (nested.size() > 0) {
// The nested message might contain other messages, all of them are stored in the dependency map
......@@ -101,7 +139,7 @@ map< std::string, const google::protobuf::Message & > profanedb::storage::Parser
// TODO This only uses a single key, one could set multiple keys
if (options.key()) {
key = fd->full_name() + '$' + FieldToString(&message, fd);
key = FieldToKey(&message, fd);
}
}
}
......@@ -111,42 +149,46 @@ map< std::string, const google::protobuf::Message & > profanedb::storage::Parser
return *dependencies;
}
std::string profanedb::storage::Parser::FieldToString(const google::protobuf::Message * container, const google::protobuf::FieldDescriptor * fd)
std::string profanedb::storage::Parser::FieldToKey(const google::protobuf::Message * container, const google::protobuf::FieldDescriptor * fd)
{
const Reflection * reflection = container->GetReflection();
std::string key_value;
switch (fd->cpp_type()) {
case FieldDescriptor::CPPTYPE_INT32:
return std::to_string(reflection->GetInt32(*container, fd));
key_value = std::to_string(reflection->GetInt32(*container, fd));
break;
case FieldDescriptor::CPPTYPE_INT64:
return std::to_string(reflection->GetInt64(*container, fd));
key_value = std::to_string(reflection->GetInt64(*container, fd));
break;
case FieldDescriptor::CPPTYPE_UINT32:
return std::to_string(reflection->GetUInt32(*container, fd));
key_value = std::to_string(reflection->GetUInt32(*container, fd));
break;
case FieldDescriptor::CPPTYPE_UINT64:
return std::to_string(reflection->GetUInt64(*container, fd));
key_value = std::to_string(reflection->GetUInt64(*container, fd));
break;
case FieldDescriptor::CPPTYPE_DOUBLE:
return std::to_string(reflection->GetDouble(*container, fd));
key_value = std::to_string(reflection->GetDouble(*container, fd));
break;
case FieldDescriptor::CPPTYPE_FLOAT:
return std::to_string(reflection->GetFloat(*container, fd));
key_value = std::to_string(reflection->GetFloat(*container, fd));
break;
case FieldDescriptor::CPPTYPE_BOOL:
return std::to_string(reflection->GetBool(*container, fd));
key_value = std::to_string(reflection->GetBool(*container, fd));
break;
case FieldDescriptor::CPPTYPE_ENUM:
return std::to_string(reflection->GetEnum(*container, fd)->index());
key_value = std::to_string(reflection->GetEnum(*container, fd)->index());
break;
case FieldDescriptor::CPPTYPE_STRING:
return reflection->GetString(*container, fd);
key_value = reflection->GetString(*container, fd);
break;
case FieldDescriptor::CPPTYPE_MESSAGE:
return reflection->GetMessage(*container, fd, &messageFactory).SerializeAsString();
key_value = reflection->GetMessage(*container, fd, &messageFactory).SerializeAsString();
break;
}
return fd->full_name() + '$' + key_value;
}
profanedb::storage::Parser::ErrorCollector::ErrorCollector()
......
......@@ -36,7 +36,7 @@ using namespace google::protobuf;
namespace profanedb {
namespace storage {
// Given a Any message, Parser looks for the corresponding definition in .proto files,
// and generates a map with keys of nested messages
class Parser
......@@ -44,12 +44,10 @@ class Parser
public:
Parser();
~Parser();
// Generate a Dynamic Message out of an Any object, and return a set of dependent objects
map<std::string, const Message &> ParseMessage(const Any & serializable);
// Parse and object and return a set of dependent messages
map<std::string, const Message &> ParseMessage(const Message & message);
// Using the provided schema, get a map with all nested messages and their unique key
map<std::string, const Message &> NormalizeMessage(const Any & serializable);
map<std::string, const Message &> NormalizeMessage(const Message & message);
private:
io::ZeroCopyInputStream * inputStream;
......@@ -57,11 +55,17 @@ private:
compiler::MultiFileErrorCollector * errCollector = new ErrorCollector();
compiler::SourceTreeDescriptorDatabase * descriptorDb;
DescriptorPool * pool;
DynamicMessageFactory messageFactory;
std::string FieldToString(const Message * container, const FieldDescriptor * fd);
// Given a Field
std::string FieldToKey(const Message * container, const FieldDescriptor * fd);
// Given a descriptor, find information about the key and nested objects,
// return true if the message has a key
bool ParseMessageDescriptor(const Descriptor & descriptor);
// A simple ErrorCollector for debug, write to stderr
class ErrorCollector : public compiler::MultiFileErrorCollector {
public:
ErrorCollector();
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment