Hi Jason,

I was out of this discussion for quite some time, but during this time I was
able to make my large application's design work with dynamic messages using
the protobuf::Importer. However, I am now stuck with the issue of
indexing/sorting and searching messages.

I understand that the code generated messages could be sorted with
stl::sort(itor:begin, itoe::end, functor), but, that's because there is a
RepeatedPtrField iterator and RepeatedPtrField list available through the
message class.

I have to sort/search on a repeated nested message declared in my main
message depending upon the fields of the nested message, like so:

message nested_msg
{
required uint64 indx =1; //sort on this field
optional uint64 classId =2; //sort on this field
optional string network_name = 3; //search on this field

}

message coverMessage
{
required uint64 nested_msg_count =1;
repeated nested_msg  msg_instance =2;
}

Could this be achieved with dynamic messages through polymorphic message
pointers? My current work on protobuf serialization will remain an
experimentation otherwise.

P.S.: I hear you people are thinking on the design of protobuf maps. Will it
be possible that protobufs parent level messages be sorted/searched at
nested message levels through maps of nested message fields? Will '[key]'
and '[value]' operators be available for the maps?


Regards,
Himanshu

On Fri, Sep 24, 2010 at 6:02 PM, Himanshu Srivastava <him.s...@gmail.com>wrote:

>  >>Gotcha. If you run protoc on the file produced by your generator class,
> does it succeed?
>
> protoc.exe succeeds parsing my proto file. I have emailed the file to you
> and you can verify that.
>
> >>>>descriptor_pool is of course NULL.
>
> >>I meant that you should check the return value of BuildFile(). If it
> returns NULL, then it could not build the file. The ErrorCollector  >>would
> tell you why
> I meant the same, Build_File() returns Null.
>
> However, I will get back to this issue. It will take some time to verify
> issues in my implementation.
>
> Thanks & Regards,
> Himanshu
>
>   On Thu, Sep 23, 2010 at 10:37 PM, Jason Hsueh <jas...@google.com> wrote:
>
>>
>>
>>  On Thu, Sep 23, 2010 at 9:52 AM, Himanshu Srivastava <him.s...@gmail.com
>> > wrote:
>>
>>> Hi Jason,
>>>
>>> In code:
>>> //********************************************//
>>>  DescriptorPool descriptor_pool;
>>>
>>>         for (int i = 0; i < f.file_size(); ++i) {
>>>
>>>             descriptor_pool.BuildFile(f.file(i));
>>> //********************************************//
>>> descriptor_pool is of course NULL.
>>>
>>
>> I meant that you should check the return value of BuildFile(). If it
>> returns NULL, then it could not build the file. The ErrorCollector would
>> tell you why.
>>
>>
>>> And for the Importer approach my code does SEG-FAULT.
>>>
>>> Further I do need conversion from proto file directly and also a static
>>> FileDescriptor so that it can be passed around for construction of my new
>>> messages in a recursive tree algorithm in  another distinct class object.
>>>
>>
>> That's up to you: you'll need to ensure that the DescriptorPool has the
>> lifetime you want.
>>
>> Previously, you mentioned that the importer approach returned NULL. That
>> would be indicative of a problem in the .proto file: the file could not be
>> built. Even if you were to successfully build the file, your code would
>> segfault, because the FileDescriptor is no longer valid, as the Importer,
>> and thus the DescriptorPool containing the FileDescriptor, have been
>> deleted.
>>
>>
>>>
>>> I do not want the descriptor set approach, since that is only available
>>> when protoc exe is present.
>>> ---------------------
>>>  >>I doubt that your code will work, as Importer should be looking for a
>>> file named "dynamicProtoMessages.proto", which probably >>does not exist.
>>> ------------------------
>>> I create the proto file "dynamicProtoMessages.proto" parmanently on disk
>>> and read it from disk to Parser after it is generated from my
>>> CXMLToProtoFileGenerator class.
>>>
>>
>> Gotcha. If you run protoc on the file produced by your generator class,
>> does it succeed?
>>
>>
>>>
>>> Thanks & Regards,
>>> Himanshu
>>>
>>>
>>> On Thu, Sep 23, 2010 at 9:39 PM, Jason Hsueh <jas...@google.com> wrote:
>>>
>>>>
>>>>
>>>>  On Thu, Sep 23, 2010 at 2:40 AM, Himanshu Srivastava <
>>>> him.s...@gmail.com> wrote:
>>>>
>>>>> Kenton:
>>>>>
>>>>>
>>>>> I really sent you a only a part of the complete RecordHeader message,
>>>>> since I was focusing on "nested message not getting parsed" issue for this
>>>>> particular message. Indeed my complete proto file is a large one. I
>>>>> have attached the truncated proto file containing this complete message 
>>>>> only
>>>>> for reference with this mail (plese see attachment
>>>>> 'dynamicProtoMessages.proto '.
>>>>>
>>>>> I had used Parser and Importer earlier and generated the FileDescriptor
>>>>> in a class “CMessageParser” member function as below:
>>>>>
>>>>>
>>>>>
>>>>> //***********************************************************//
>>>>>
>>>>> class PacketTracerErrorFileErrorCollector: 
>>>>> publicgoogle::protobuf::compiler::MultiFileErrorCollector
>>>>>
>>>>> {
>>>>>
>>>>> ...
>>>>>
>>>>> };
>>>>>
>>>>>
>>>>>
>>>>>
>>>>>
>>>>> const google::protobuf::FileDescriptor* CMessageParser
>>>>> ::generateMessageFileDescriptor()
>>>>>
>>>>> {
>>>>>
>>>>>     std::pair<std::string, std::string> filePair;
>>>>>
>>>>>     google::protobuf::compiler::DiskSourceTree source_tree;
>>>>>
>>>>>     source_tree.MapPath(/*filePair.first*/"", "."/*filePair.second*/);
>>>>>
>>>>>     PacketTracerErrorFileErrorCollector error_collector;//Defined
>>>>> above
>>>>>
>>>>>     google::protobuf::compiler::Importer importer(&source_tree,
>>>>> &error_collector);
>>>>>
>>>>>     std::string outFileNameString = “dynamicProtoMessages.proto”;
>>>>>     const google::protobuf::FileDescriptor* file_desc =
>>>>> importer.Import(outFileNameString);
>>>>>     return file_desc;
>>>>>
>>>>> }
>>>>>
>>>>> //***********************************************************//
>>>>>
>>>>>
>>>>> However, the problem with that approach was, as soon as I returned the
>>>>> pointer from the FileDescriptor to a client class object of
>>>>> CMessageParser, the FileDescriptor* becomes NULL  or invalid  once out
>>>>> of the class and it becomes useless.
>>>>>
>>>>  //***********************************************************//
>>>>>
>>>>> CMessageParser myParser;
>>>>>
>>>>>  const google::protobuf::FileDescriptor *file_desc = 
>>>>> myParser.generateMessageFileDescriptor();
>>>>> //file_desc is NULL
>>>>>
>>>>> //***********************************************************//
>>>>>
>>>>>
>>>>>  So, I thought, I was following some wrong approach and to retain the
>>>>> File Descriptors for a long enough period across scopes, I may need the
>>>>> DescriptorPool, which might have the permanent lifetime for the period of
>>>>> the application.
>>>>>
>>>>
>>>> Importer just wraps DescriptorPool and a database of proto files.
>>>> Neither of these guarantee static duration for the descriptors - any
>>>> descriptors that you build will only remain alive while the
>>>> DescriptorPool/Importer remains alive.
>>>>
>>>> Of course, that means your code should seg-fault, not return NULL,
>>>> assuming that you successfully built the file. You should look at the error
>>>> collector to see what went wrong. I doubt that your code will work, as
>>>> Importer should be looking for a file named "dynamicProtoMessages.proto",
>>>> which probably does not exist.
>>>>
>>>> But it sounds like you don't actually need to read .proto files, and
>>>> instead you are generating the *DescriptorProto representations directly. 
>>>> If
>>>> that's the case, you don't need Importer, you should directly use a
>>>> DescriptorPool as you did in the code snippet below.
>>>>
>>>>
>>>>>
>>>>>
>>>>> Hi Jason:
>>>>>
>>>>> I am always able to generate the FileDescriptorSet easily, although the
>>>>> FileDescriptor was never showing completely populated fields when 
>>>>> debugging
>>>>> with Visual studio 2008 Express edition.
>>>>>
>>>>> I have attached the generated FileDescriptorSet 'dynProtoMessage.dsc'
>>>>> file along with the proto file containing the above messages with this 
>>>>> mail.
>>>>> You can see even this dsc file (made with simple messages as in the 
>>>>> attached
>>>>> proto file) does not load through DescriptorPool::BuildFile().
>>>>>
>>>>>
>>>>>
>>>>> This is the function I used to load DescriptorSet:
>>>>>
>>>>>
>>>>>
>>>>> void CMessageParser 
>>>>> ::getMessagesFromDescriptorSet(constgoogle::protobuf::FileDescriptor** 
>>>>> new_file_desc)
>>>>>
>>>>> {
>>>>>
>>>>>     using namespace google::protobuf;
>>>>>
>>>>>     using namespace google::protobuf::io;
>>>>>
>>>>>     using namespace google::protobuf::compiler;
>>>>>
>>>>>     ifstream desc_file("dynProtoMessage.dsc",ios::in);
>>>>>
>>>>>         if (desc_file.bad()) {
>>>>>
>>>>>                       std::cout << "desc file not read...exiting" <<
>>>>> std::endl;
>>>>>
>>>>>                      return;
>>>>>
>>>>>         }
>>>>>
>>>>>
>>>>>
>>>>>         FileDescriptorSet f;
>>>>>
>>>>>         f.ParseFromIstream(&desc_file);
>>>>>
>>>>>
>>>>>
>>>>>        // DescriptorPoolErrorCollector errorCol;
>>>>>         //google::protobuf::SimpleDescriptorDatabase desc_database;
>>>>>        //DescriptorPool descriptor_pool(&errorCol, &desc_database);
>>>>>
>>>>>         DescriptorPool descriptor_pool;
>>>>>
>>>>>         for (int i = 0; i < f.file_size(); ++i) {
>>>>>
>>>>>             descriptor_pool.BuildFile(f.file(i));
>>>>>
>>>>
>>>> Did you check that these return non-null and don't have any errors?
>>>>
>>>>
>>>>>         }
>>>>>
>>>>>
>>>>>         const Descriptor* descriptor =
>>>>> descriptor_pool.FindMessageTypeByName("RecordHeader");
>>>>> // descriptor =>NULL here
>>>>>
>>>>
>>>> You need to use the fully-qualified name to find the message type:
>>>> descriptor_pool.FindMessageTypeByName("traceFileMessagesProto.RecordHeader");
>>>>
>>>>
>>>>>         //const FileDescriptor* new_file_desc =
>>>>> descriptor_pool.FindFileByName("dynMessage.dsc");
>>>>>         /*
>>>>>         DynamicMessageFactory factory;
>>>>>
>>>>>         Message* my_message = factory.GetPrototype(descriptor)->New();
>>>>>         delete my_message;
>>>>>        */
>>>>>
>>>>>
>>>>>
>>>>> }
>>>>>
>>>>>
>>>>> Finally,  the point raised by Kenton and you that the proto file did
>>>>> not parse correctly to yield the valid FileDescriptor might be correct,
>>>>> since, I am generating the .proto file containing the messages on the fly 
>>>>> by
>>>>> converting corresponding tags from my XML file.
>>>>> When earlier I used a handmade proto file for the messages, which
>>>>> parsed correctly to provide the descriptors, I was able to stream data 
>>>>> into
>>>>> protocol buffers and use the buffers correctly. I will be inspecting this
>>>>> file at my end for any typing errors.
>>>>>
>>>>> Thanks for the answer and for opening this protobuf library on public
>>>>> domain, though.
>>>>>
>>>>>
>>>>> Thanks and Regards,
>>>>>
>>>>> Himanshu
>>>>>
>>>>>
>>>>>
>>>>>
>>>>>
>>>>>
>>>>> On Thu, Sep 23, 2010 at 7:53 AM, Jason Hsueh <jas...@google.com>wrote:
>>>>>
>>>>>> It occurred to me that protoc shouldn't accept your file either. Did
>>>>>> it really compile successfully? What do you actually get in your
>>>>>> FileDescriptorSet?
>>>>>>
>>>>>> On Wednesday, September 22, 2010, Jason Hsueh <jas...@google.com>
>>>>>> wrote:
>>>>>> > 1) I would guess the problem is that the "action" message type
>>>>>> refers to undefined types eaction_type and ereason. There are probably 
>>>>>> error
>>>>>> messages farther up indicating that action could not be built. Because
>>>>>> action isn't a valid type, RecordHeader can't refer to it, and thinks 
>>>>>> that
>>>>>> action is an undefined_symbol as well. The DescriptorBuilder will read in
>>>>>> all inputs, and cross-link the types once everything has been processed. 
>>>>>> It
>>>>>> doesn't matter what order they are defined in.
>>>>>> > 2) You can manually build the FileDescriptorProto representation
>>>>>> yourself, or use the classes used by the compiler: see
>>>>>> google::protobuf::compiler::Parser or 
>>>>>> google::protobuf::compiler::Importer.
>>>>>> >
>>>>>> > On Wed, Sep 22, 2010 at 4:42 AM, Himanshu Srivastava <
>>>>>> him.s...@gmail.com> wrote:
>>>>>> >
>>>>>> > Hi Kenton,
>>>>>> > I have the following message in my .proto file:
>>>>>> > //************************************************/
>>>>>> > package traceFileMessagesProto;
>>>>>> > message RecordHeader {
>>>>>> > message  myqueue{
>>>>>> >  optional uint32 id = 1;
>>>>>> >  optional uint32 Priority = 2;
>>>>>> > }
>>>>>> >
>>>>>> > message  action{
>>>>>> >  optional eactiontype    eactiontype_instance = 1;
>>>>>> >  optional ereason ereason_instance = 2;
>>>>>> >  optional myqueue myqueue_instance = 3;
>>>>>> > }
>>>>>> > optional action action_instance =1;
>>>>>> > } //end RecordHeader
>>>>>> > /***************************************************/
>>>>>> > Thus, "action" is nested message in "RecordHeader" and has "queue"
>>>>>> submessage in it.
>>>>>> > I used the protoc compiler -o <desc-file> option to generate the
>>>>>> descriptor set file and loaded it through istream in c++ application,
>>>>>> followed by streaming FileDescriptorSet object with this descriptor set
>>>>>> file:
>>>>>> >
>>>>>> >
>>>>>> > //***************************************************************//
>>>>>> > ifstream desc_file("mydescriptor.dsc",ios::in);
>>>>>> > FileDescriptorSet f;
>>>>>> > f.ParseFromIstream(&desc_file);
>>>>>> > //***************************************************************//
>>>>>> >
>>>>>> >
>>>>>> > However, while parsing through DescriptorPool::BuildFile(f.file(0));
>>>>>> > at the line corresponding to the message file line:
>>>>>> > => optional action action_instance =1;
>>>>>> > the BuildFile() function exits by giving error:
>>>>>> > undefined_symbol "action"
>>>>>> > The code returns through the following function in protoc library:
>>>>>> > //***************************************************************//
>>>>>> > void DescriptorBuilder::AddNotDefinedError(
>>>>>> >     const string& element_name,
>>>>>> >     const Message& descriptor,
>>>>>> >     DescriptorPool::ErrorCollector::ErrorLocation location,
>>>>>> >     const string& undefined_symbol) {
>>>>>> >   if (possible_undeclared_dependency_ == NULL) {
>>>>>> >     AddError(element_name, descriptor, location,
>>>>>> >              "\"" + undefined_symbol + "\" is not defined.");
>>>>>> > //***************************************************************//
>>>>>> > The only possible explanation could be that the message "action" is
>>>>>> not parsed before its instance declaration from my .proto/descriptor_set
>>>>>> file.
>>>>>> > Probably all nested messages should be parsed on their instance
>>>>>> declarations in a recursive manner in the DescriptorPool::Buildfile()
>>>>>> function.
>>>>>> >
>>>>>> >
>>>>>> > Qustion1:
>>>>>> > How do I solve the above issue?
>>>>>> > Question 2:
>>>>>> > Can not I simply load my messages in DescriptorPool through the
>>>>>> .proto file instead of calling the service of protoc compiler to 
>>>>>> generate a
>>>>>> descriptor file? I have to generate .proto file at runtime and I don't 
>>>>>> want
>>>>>> to call another exe (protoc.exe) from my application for dependency 
>>>>>> reasons.
>>>>>> >
>>>>>> >
>>>>>> > Thanks in advance for any solutions /directions.
>>>>>> > Regards,
>>>>>> > Himanshu
>>>>>> >
>>>>>> >
>>>>>> >
>>>>>> >
>>>>>> > --
>>>>>> > You received this message because you are subscribed to the Google
>>>>>> Groups "Protocol Buffers" group.
>>>>>> > To post to this group, send email to proto...@googlegroups.com.
>>>>>> > To unsubscribe from this group, send email to
>>>>>> protobuf+unsubscr...@googlegroups.com<protobuf%2bunsubscr...@googlegroups.com>
>>>>>> .
>>>>>> > For more options, visit this group at
>>>>>> http://groups.google.com/group/protobuf?hl=en.
>>>>>> >
>>>>>> >
>>>>>> >
>>>>>>
>>>>>
>>>>>
>>>>
>>> --
>>>   You received this message because you are subscribed to the Google
>>> Groups "Protocol Buffers" group.
>>> To post to this group, send email to proto...@googlegroups.com.
>>> To unsubscribe from this group, send email to
>>> protobuf+unsubscr...@googlegroups.com<protobuf%2bunsubscr...@googlegroups.com>
>>> .
>>> For more options, visit this group at
>>> http://groups.google.com/group/protobuf?hl=en.
>>>
>>
>>
>

-- 
You received this message because you are subscribed to the Google Groups 
"Protocol Buffers" group.
To post to this group, send email to proto...@googlegroups.com.
To unsubscribe from this group, send email to 
protobuf+unsubscr...@googlegroups.com.
For more options, visit this group at 
http://groups.google.com/group/protobuf?hl=en.

Reply via email to