void RpcGenerator::generateImplementsMethod(const google::protobuf::ServiceDescriptor *descriptor, google::protobuf::io::Printer &printer) const { printer.PrintRaw(implementsReturnType); printer.Print(" $serviceName$_Dispatcher::$implementsSignature$\n{\n", "serviceName", descriptor->name(), "implementsSignature", implementsSignature); printer.Indent(); printer.Print("// This is NOT thread safe ...\n"); printer.Print("static $implementsReturnType$ methodIds;\n", "implementsReturnType", implementsReturnType); printer.Print("static bool init = true;\n"); printer.Print("if (init) {\n"); printer.Indent(); for(int j=0; j<descriptor->method_count(); j++) { const MethodDescriptor *method = descriptor->method(j); string methodName = method->full_name(); int methodId = RpcPlugin::generateExtensionNumber(methodName); ostringstream methodIdStr; methodIdStr << methodId; printer.Print("methodIds.push_back($methodId$);\n", "methodId", methodIdStr.str()); } printer.Print("init = false;\n"); printer.Outdent(); printer.Print("}\n"); printer.Print("return methodIds;\n"); printer.Outdent(); printer.Print("}\n"); }
void RpcGenerator::generateSentExternalBlock(const string &variableName, const string &channelName, const google::protobuf::Descriptor *descriptor, google::protobuf::io::Printer &printer) const { for(int i=0; i< descriptor->field_count(); i++) { const FieldDescriptor *field = descriptor->field(i); if (field->type() == FieldDescriptor::TYPE_MESSAGE) { string messageTypeName = field->message_type()->full_name(); if (messageTypeName.find("external.") == 0) { string externalClass = externalTypeToClass(messageTypeName); std::ostringstream stream; stream << "obj" << i; string var = stream.str(); printer.Print("if ($variableName$->has_$fieldName$()) {\n", "variableName", variableName, "fieldName", field->lowercase_name()); printer.Indent(); printer.Print("$externalClass$ *$var$ = ", "externalClass", externalClass, "var", var); printer.Print("$variableName$->$fieldName$().get();\n", "variableName", variableName, "fieldName", field->lowercase_name()); printer.Print("if ($var$) {\n", "var", var); printer.Indent(); printer.Print("$externalClass$Serializer serializer($var$);\n", "externalClass", externalClass, "var", var); printer.Print("size_t size = serializer.size();\n"); std::map<string, string> variables; variables["channelName"] = channelName; printer.Print("std::vector<unsigned char> data(size);\n"); this->generateErrorCheck("serializer.serialize(&data[0], size)", variables, printer, "$channelName$->setErrorString(\"Serialization failed\");return;\n"); variables.clear(); variables["channelName"] = channelName; // Send the size first this->generateErrorCheck("$channelName$->send(size)", variables, printer); this->generateErrorCheck("$channelName$->send(&data[0], size)", variables, printer); printer.Outdent(); printer.Print("}\n"); printer.Outdent(); printer.Print("}\n"); } } } }
void RpcGenerator::generateSentVtkBlock(const string &variableName, const string &channelName, const google::protobuf::Descriptor *descriptor, google::protobuf::io::Printer &printer) const { for(int i=0; i< descriptor->field_count(); i++) { const FieldDescriptor *field = descriptor->field(i); if (field->type() == FieldDescriptor::TYPE_MESSAGE) { string messageTypeName = field->message_type()->full_name(); if (messageTypeName.find("vtk.") == 0) { string vtkType = messageTypeName.substr(4); std::ostringstream stream; stream << "obj" << i; string var = stream.str(); printer.Print("if ($variableName$->has_$fieldName$()) {\n", "variableName", variableName, "fieldName", field->lowercase_name()); printer.Indent(); printer.Print("$vtkType$ *$var$ = ", "vtkType", vtkType, "var", var); printer.Print("$variableName$->$fieldName$().get();\n", "variableName", variableName, "fieldName", field->lowercase_name()); printer.Print("if ($var$) {\n", "var", var); printer.Indent(); std::map<string, string> variables; variables["var"] = var; variables["channelName"] = channelName; this->generateErrorCheck("$channelName$->send($var$)", variables, printer); printer.Outdent(); printer.Print("}\n"); printer.Outdent(); printer.Print("}\n"); } } } }
void RpcGenerator::generateRelyMethod( const google::protobuf::ServiceDescriptor *descriptor, google::protobuf::io::Printer &printer) const { printer.Print("void $service$_Dispatcher::$replySignature$\n{\n", "service", descriptor->full_name(), "replySignature", replySignature); printer.Indent(); printer.Print("switch(info.methodId) {\n"); printer.Indent(); for(int j=0; j<descriptor->method_count(); j++) { const MethodDescriptor *method = descriptor->method(j); string methodName = method->full_name(); int methodId = RpcPlugin::generateExtensionNumber(methodName); string inputTypeName = method->input_type()->name(); string outputTypeName = method->output_type()->name(); if (isVoidType(outputTypeName)) continue; ostringstream methodIdStr; methodIdStr << methodId; printer.Print("case $methodId$ : {\n", "methodId", methodIdStr.str()); printer.Indent(); printer.Print("// $methodName$\n", "methodName", methodName); printer.Print("// Prepare the response\n"); printer.Print("rpc::Message msg;\n"); printer.Print("rpc::Response *response = msg.mutable_response();\n"); printer.Print("uint64 requestId = info.requestMessageEnvelope->request().id();\n"); printer.Print("response->set_id(requestId);\n"); string extensionName = toExtensionName(method->full_name()); std::ostringstream var; var << "tmp" << j; printer.Print("$responseType$ *$var$ = static_cast<$responseType$ *>(info.response);\n", "responseType", outputTypeName, "var", var.str()); // Add error info printer.Print("if ($var$->hasError()) {\n", "var", var.str()); printer.Indent(); printer.Print("response->set_errorstring($var$->errorString());\n", "var", var.str()); printer.Print("response->set_errorcode($var$->errorCode());\n", "var", var.str()); printer.Outdent(); printer.Print("}\n"); printer.Print("response->SetAllocatedExtension($extensionName$, $var$);\n", "extensionName", extensionName + "_response", "var", var.str()); printer.Print("// Make sure request is cleaned up\n"); printer.Print("std::auto_ptr<rpc::Message> request;\n"); printer.Print("request.reset(info.requestMessageEnvelope);\n"); this->generateErrorCheck("info.replyChannel->send(&msg)", printer); // send any VTK object we need to. this->generateSentVtkBlock(var.str(), "info.replyChannel", method->output_type(), printer); // send any external objects we need to. this->generateSentExternalBlock(var.str(), "info.replyChannel", method->output_type(), printer); printer.Outdent(); printer.Print("break;\n"); printer.Print("}\n"); } printer.Print("default:\n"); printer.Indent(); printer.Print("// TODO error case\n"); printer.Print("info.replyChannel->setErrorString(\"No reply case for messageId: \" + info.methodId);\n"); printer.Outdent(); printer.Outdent(); printer.Print("}\n"); printer.Outdent(); printer.Print("}\n"); }
void RpcGenerator::generateDispatchMethodBody( const google::protobuf::ServiceDescriptor *descriptor, google::protobuf::io::Printer &printer) const { printer.Indent(); printer.Print("switch(methodId) { \n"); printer.Indent(); for(int j=0; j<descriptor->method_count(); j++) { const MethodDescriptor *method = descriptor->method(j); string methodName = method->full_name(); int methodId = RpcPlugin::generateExtensionNumber(methodName); string inputTypeName = method->input_type()->name(); string outputTypeName = method->output_type()->name(); ostringstream methodIdStr; methodIdStr << methodId; printer.Print("case $methodId$ : {\n", "methodId", methodIdStr.str()); printer.Indent(); printer.Print("// $methodName$\n", "methodName", methodName); if (!isVoidType(inputTypeName)) { printer.Print("const $inputType$ *in = static_cast<const $inputType$ *>(request);\n", "inputType", inputTypeName); // Receive any VTK types that might be on the wire ... generateReceiveVtkBlock("request", "replyChannel", method->input_type(),printer); // Receive any external type that might be on the wire ... generateReceiveExternalBlock("request", "replyChannel", method->input_type(),printer); } if (!isVoidType(outputTypeName)) { printer.Print("$outputType$ *out = new $outputType$();\n", "outputType", outputTypeName); printer.Print("ProtoCall::Runtime::ReplyInfo info;\n"); printer.Print("info.methodId = $methodId$;\n", "methodId", methodIdStr.str()); printer.Print("info.requestMessageEnvelope = requestMessageEnvelope;\n"); printer.Print("info.response = out;\n"); printer.Print("info.replyChannel = replyChannel;\n"); string dispatcherName = descriptor->name() + "_Dispatcher"; printer.Print("::google::protobuf::Closure *done = " "::google::protobuf::NewCallback(this, &$dispatcherName$::reply, info);\n", "dispatcherName", dispatcherName); } else { printer.Print("::google::protobuf::Closure *done = google::protobuf::NewCallback(&google::protobuf::DoNothing);\n"); } printer.Print("static_cast<$service$ *>(m_service)->$methodName$(", "service", descriptor->name(), "methodName", method->name()); if (!isVoidType(inputTypeName)) printer.Print("in"); if (!isVoidType(inputTypeName) && !isVoidType(outputTypeName)) printer.Print(", "); if (!isVoidType(outputTypeName)) printer.Print("out"); if (!isVoidType(inputTypeName) || !isVoidType(outputTypeName)) printer.Print(", "); printer.Print("done);\n"); printer.Outdent(); printer.Print("break;\n"); printer.Print("}\n"); } printer.Print("default:\n"); printer.Indent(); printer.Print("replyChannel->setErrorString(\"No case for messageId: \" + methodId);"); printer.Outdent(); printer.Outdent(); printer.Print("}\n"); printer.Outdent(); }