mirror of https://github.com/grpc/grpc.git
commit
43db6265c9
440 changed files with 26650 additions and 20362 deletions
@ -0,0 +1,57 @@ |
||||
--- |
||||
Language: Cpp |
||||
# BasedOnStyle: Google |
||||
AccessModifierOffset: -1 |
||||
ConstructorInitializerIndentWidth: 4 |
||||
AlignEscapedNewlinesLeft: true |
||||
AlignTrailingComments: true |
||||
AllowAllParametersOfDeclarationOnNextLine: true |
||||
AllowShortBlocksOnASingleLine: false |
||||
AllowShortIfStatementsOnASingleLine: true |
||||
AllowShortLoopsOnASingleLine: true |
||||
AllowShortFunctionsOnASingleLine: All |
||||
AlwaysBreakTemplateDeclarations: true |
||||
AlwaysBreakBeforeMultilineStrings: true |
||||
BreakBeforeBinaryOperators: false |
||||
BreakBeforeTernaryOperators: true |
||||
BreakConstructorInitializersBeforeComma: false |
||||
BinPackParameters: true |
||||
ColumnLimit: 80 |
||||
ConstructorInitializerAllOnOneLineOrOnePerLine: true |
||||
DerivePointerAlignment: true |
||||
ExperimentalAutoDetectBinPacking: false |
||||
IndentCaseLabels: true |
||||
IndentWrappedFunctionNames: false |
||||
IndentFunctionDeclarationAfterType: false |
||||
MaxEmptyLinesToKeep: 1 |
||||
KeepEmptyLinesAtTheStartOfBlocks: false |
||||
NamespaceIndentation: None |
||||
ObjCSpaceAfterProperty: false |
||||
ObjCSpaceBeforeProtocolList: false |
||||
PenaltyBreakBeforeFirstCallParameter: 1 |
||||
PenaltyBreakComment: 300 |
||||
PenaltyBreakString: 1000 |
||||
PenaltyBreakFirstLessLess: 120 |
||||
PenaltyExcessCharacter: 1000000 |
||||
PenaltyReturnTypeOnItsOwnLine: 200 |
||||
PointerAlignment: Left |
||||
SpacesBeforeTrailingComments: 2 |
||||
Cpp11BracedListStyle: true |
||||
Standard: Auto |
||||
IndentWidth: 2 |
||||
TabWidth: 8 |
||||
UseTab: Never |
||||
BreakBeforeBraces: Attach |
||||
SpacesInParentheses: false |
||||
SpacesInAngles: false |
||||
SpaceInEmptyParentheses: false |
||||
SpacesInCStyleCastParentheses: false |
||||
SpacesInContainerLiterals: true |
||||
SpaceBeforeAssignmentOperators: true |
||||
ContinuationIndentWidth: 4 |
||||
CommentPragmas: '^ IWYU pragma:' |
||||
ForEachMacros: [ foreach, Q_FOREACH, BOOST_FOREACH ] |
||||
SpaceBeforeParens: ControlStatements |
||||
DisableFormat: false |
||||
... |
||||
|
@ -1,6 +1,19 @@ |
||||
# C/C++ build outputs |
||||
bins |
||||
deps |
||||
gens |
||||
libs |
||||
objs |
||||
|
||||
# gcov coverage data |
||||
coverage |
||||
*.gcno |
||||
|
||||
# profiler output |
||||
*.prof |
||||
|
||||
# python compiled objects |
||||
*.pyc |
||||
|
||||
# cache for run_tests.py |
||||
.run_tests_cache |
||||
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -1,520 +0,0 @@ |
||||
/*
|
||||
* |
||||
* Copyright 2014, Google Inc. |
||||
* All rights reserved. |
||||
* |
||||
* Redistribution and use in source and binary forms, with or without |
||||
* modification, are permitted provided that the following conditions are |
||||
* met: |
||||
* |
||||
* * Redistributions of source code must retain the above copyright |
||||
* notice, this list of conditions and the following disclaimer. |
||||
* * Redistributions in binary form must reproduce the above |
||||
* copyright notice, this list of conditions and the following disclaimer |
||||
* in the documentation and/or other materials provided with the |
||||
* distribution. |
||||
* * Neither the name of Google Inc. nor the names of its |
||||
* contributors may be used to endorse or promote products derived from |
||||
* this software without specific prior written permission. |
||||
* |
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS |
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT |
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR |
||||
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT |
||||
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, |
||||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT |
||||
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE |
||||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
||||
* |
||||
*/ |
||||
|
||||
using namespace std; |
||||
|
||||
#include "src/compiler/go_generator.h" |
||||
|
||||
#include <cctype> |
||||
|
||||
#include <google/protobuf/io/printer.h> |
||||
#include <google/protobuf/io/zero_copy_stream_impl_lite.h> |
||||
#include <google/protobuf/descriptor.pb.h> |
||||
#include <google/protobuf/descriptor.h> |
||||
|
||||
namespace grpc_go_generator { |
||||
|
||||
bool NoStreaming(const google::protobuf::MethodDescriptor* method) { |
||||
return !method->client_streaming() && |
||||
!method->server_streaming(); |
||||
} |
||||
|
||||
bool ClientOnlyStreaming(const google::protobuf::MethodDescriptor* method) { |
||||
return method->client_streaming() && |
||||
!method->server_streaming(); |
||||
} |
||||
|
||||
bool ServerOnlyStreaming(const google::protobuf::MethodDescriptor* method) { |
||||
return !method->client_streaming() && |
||||
method->server_streaming(); |
||||
} |
||||
|
||||
bool BidiStreaming(const google::protobuf::MethodDescriptor* method) { |
||||
return method->client_streaming() && |
||||
method->server_streaming(); |
||||
} |
||||
|
||||
bool HasClientOnlyStreaming(const google::protobuf::FileDescriptor* file) { |
||||
for (int i = 0; i < file->service_count(); i++) { |
||||
for (int j = 0; j < file->service(i)->method_count(); j++) { |
||||
if (ClientOnlyStreaming(file->service(i)->method(j))) { |
||||
return true; |
||||
} |
||||
} |
||||
} |
||||
return false; |
||||
} |
||||
|
||||
string LowerCaseService(const string& service) { |
||||
string ret = service; |
||||
if (!ret.empty() && ret[0] >= 'A' && ret[0] <= 'Z') { |
||||
ret[0] = ret[0] - 'A' + 'a'; |
||||
} |
||||
return ret; |
||||
} |
||||
|
||||
void PrintClientMethodDef(google::protobuf::io::Printer* printer, |
||||
const google::protobuf::MethodDescriptor* method, |
||||
map<string, string>* vars) { |
||||
(*vars)["Method"] = method->name(); |
||||
(*vars)["Request"] = method->input_type()->name(); |
||||
(*vars)["Response"] = method->output_type()->name(); |
||||
if (NoStreaming(method)) { |
||||
printer->Print(*vars, |
||||
"\t$Method$(ctx context.Context, in *$Request$, opts ...rpc.CallOption) " |
||||
"(*$Response$, error)\n"); |
||||
} else if (BidiStreaming(method)) { |
||||
printer->Print(*vars, |
||||
"\t$Method$(ctx context.Context, opts ...rpc.CallOption) " |
||||
"($Service$_$Method$Client, error)\n"); |
||||
} else if (ServerOnlyStreaming(method)) { |
||||
printer->Print(*vars, |
||||
"\t$Method$(ctx context.Context, m *$Request$, opts ...rpc.CallOption) " |
||||
"($Service$_$Method$Client, error)\n"); |
||||
} else if (ClientOnlyStreaming(method)) { |
||||
printer->Print(*vars, |
||||
"\t$Method$(ctx context.Context, opts ...rpc.CallOption) " |
||||
"($Service$_$Method$Client, error)\n"); |
||||
} |
||||
} |
||||
|
||||
void PrintClientMethodImpl(google::protobuf::io::Printer* printer, |
||||
const google::protobuf::MethodDescriptor* method, |
||||
map<string, string>* vars) { |
||||
(*vars)["Method"] = method->name(); |
||||
(*vars)["Request"] = method->input_type()->name(); |
||||
(*vars)["Response"] = method->output_type()->name(); |
||||
|
||||
if (NoStreaming(method)) { |
||||
printer->Print(*vars, |
||||
"func (c *$ServiceStruct$Client) $Method$(ctx context.Context, " |
||||
"in *$Request$, opts ...rpc.CallOption) (*$Response$, error) {\n"); |
||||
printer->Print(*vars, |
||||
"\tout := new($Response$)\n"); |
||||
printer->Print(*vars, |
||||
"\terr := rpc.Invoke(ctx, \"/$Package$$Service$/$Method$\", " |
||||
"in, out, c.cc, opts...)\n"); |
||||
printer->Print("\tif err != nil {\n"); |
||||
printer->Print("\t\treturn nil, err\n"); |
||||
printer->Print("\t}\n"); |
||||
printer->Print("\treturn out, nil\n"); |
||||
printer->Print("}\n\n"); |
||||
} else if (BidiStreaming(method)) { |
||||
printer->Print( |
||||
*vars, |
||||
"func (c *$ServiceStruct$Client) $Method$(ctx context.Context, opts " |
||||
"...rpc.CallOption) ($Service$_$Method$Client, error) {\n" |
||||
"\tstream, err := rpc.NewClientStream(ctx, c.cc, " |
||||
"\"/$Package$$Service$/$Method$\", opts...)\n" |
||||
"\tif err != nil {\n" |
||||
"\t\treturn nil, err\n" |
||||
"\t}\n" |
||||
"\treturn &$ServiceStruct$$Method$Client{stream}, nil\n" |
||||
"}\n\n"); |
||||
printer->Print(*vars, |
||||
"type $Service$_$Method$Client interface {\n" |
||||
"\tSend(*$Request$) error\n" |
||||
"\tRecv() (*$Response$, error)\n" |
||||
"\trpc.ClientStream\n" |
||||
"}\n\n"); |
||||
printer->Print(*vars, |
||||
"type $ServiceStruct$$Method$Client struct {\n" |
||||
"\trpc.ClientStream\n" |
||||
"}\n\n"); |
||||
printer->Print(*vars, |
||||
"func (x *$ServiceStruct$$Method$Client) Send(m *$Request$) error {\n" |
||||
"\treturn x.ClientStream.SendProto(m)\n" |
||||
"}\n\n"); |
||||
printer->Print(*vars, |
||||
"func (x *$ServiceStruct$$Method$Client) Recv() (*$Response$, error) " |
||||
"{\n" |
||||
"\tm := new($Response$)\n" |
||||
"\tif err := x.ClientStream.RecvProto(m); err != nil {\n" |
||||
"\t\treturn nil, err\n" |
||||
"\t}\n" |
||||
"\treturn m, nil\n" |
||||
"}\n\n"); |
||||
} else if (ServerOnlyStreaming(method)) { |
||||
printer->Print( |
||||
*vars, |
||||
"func (c *$ServiceStruct$Client) $Method$(ctx context.Context, m " |
||||
"*$Request$, " |
||||
"opts ...rpc.CallOption) ($Service$_$Method$Client, error) {\n" |
||||
"\tstream, err := rpc.NewClientStream(ctx, c.cc, " |
||||
"\"/$Package$$Service$/$Method$\", opts...)\n" |
||||
"\tif err != nil {\n" |
||||
"\t\treturn nil, err\n" |
||||
"\t}\n" |
||||
"\tx := &$ServiceStruct$$Method$Client{stream}\n" |
||||
"\tif err := x.ClientStream.SendProto(m); err != nil {\n" |
||||
"\t\treturn nil, err\n" |
||||
"\t}\n" |
||||
"\tif err := x.ClientStream.CloseSend(); err != nil {\n" |
||||
"\t\treturn nil, err\n" |
||||
"\t}\n" |
||||
"\treturn x, nil\n" |
||||
"}\n\n"); |
||||
printer->Print(*vars, |
||||
"type $Service$_$Method$Client interface {\n" |
||||
"\tRecv() (*$Response$, error)\n" |
||||
"\trpc.ClientStream\n" |
||||
"}\n\n"); |
||||
printer->Print(*vars, |
||||
"type $ServiceStruct$$Method$Client struct {\n" |
||||
"\trpc.ClientStream\n" |
||||
"}\n\n"); |
||||
printer->Print(*vars, |
||||
"func (x *$ServiceStruct$$Method$Client) Recv() (*$Response$, error) " |
||||
"{\n" |
||||
"\tm := new($Response$)\n" |
||||
"\tif err := x.ClientStream.RecvProto(m); err != nil {\n" |
||||
"\t\treturn nil, err\n" |
||||
"\t}\n" |
||||
"\treturn m, nil\n" |
||||
"}\n\n"); |
||||
} else if (ClientOnlyStreaming(method)) { |
||||
printer->Print( |
||||
*vars, |
||||
"func (c *$ServiceStruct$Client) $Method$(ctx context.Context, opts " |
||||
"...rpc.CallOption) ($Service$_$Method$Client, error) {\n" |
||||
"\tstream, err := rpc.NewClientStream(ctx, c.cc, " |
||||
"\"/$Package$$Service$/$Method$\", opts...)\n" |
||||
"\tif err != nil {\n" |
||||
"\t\treturn nil, err\n" |
||||
"\t}\n" |
||||
"\treturn &$ServiceStruct$$Method$Client{stream}, nil\n" |
||||
"}\n\n"); |
||||
printer->Print(*vars, |
||||
"type $Service$_$Method$Client interface {\n" |
||||
"\tSend(*$Request$) error\n" |
||||
"\tCloseAndRecv() (*$Response$, error)\n" |
||||
"\trpc.ClientStream\n" |
||||
"}\n\n"); |
||||
printer->Print(*vars, |
||||
"type $ServiceStruct$$Method$Client struct {\n" |
||||
"\trpc.ClientStream\n" |
||||
"}\n\n"); |
||||
printer->Print(*vars, |
||||
"func (x *$ServiceStruct$$Method$Client) Send(m *$Request$) error {\n" |
||||
"\treturn x.ClientStream.SendProto(m)\n" |
||||
"}\n\n"); |
||||
printer->Print(*vars, |
||||
"func (x *$ServiceStruct$$Method$Client) CloseAndRecv() (*$Response$, " |
||||
"error) {\n" |
||||
"\tif err := x.ClientStream.CloseSend(); err != nil {\n" |
||||
"\t\treturn nil, err\n" |
||||
"\t}\n" |
||||
"\tm := new($Response$)\n" |
||||
"\tif err := x.ClientStream.RecvProto(m); err != nil {\n" |
||||
"\t\treturn nil, err\n" |
||||
"\t}\n" |
||||
"\t// Read EOF.\n" |
||||
"\tif err := x.ClientStream.RecvProto(m); err == io.EOF {\n" |
||||
"\t\treturn m, io.EOF\n" |
||||
"\t}\n" |
||||
"\t// gRPC protocol violation.\n" |
||||
"\treturn m, fmt.Errorf(\"Violate gRPC client streaming protocol: no " |
||||
"EOF after the response.\")\n" |
||||
"}\n\n"); |
||||
} |
||||
} |
||||
|
||||
void PrintClient(google::protobuf::io::Printer* printer, |
||||
const google::protobuf::ServiceDescriptor* service, |
||||
map<string, string>* vars) { |
||||
(*vars)["Service"] = service->name(); |
||||
(*vars)["ServiceStruct"] = LowerCaseService(service->name()); |
||||
printer->Print(*vars, "type $Service$Client interface {\n"); |
||||
for (int i = 0; i < service->method_count(); ++i) { |
||||
PrintClientMethodDef(printer, service->method(i), vars); |
||||
} |
||||
printer->Print("}\n\n"); |
||||
|
||||
printer->Print(*vars, |
||||
"type $ServiceStruct$Client struct {\n" |
||||
"\tcc *rpc.ClientConn\n" |
||||
"}\n\n"); |
||||
printer->Print(*vars, |
||||
"func New$Service$Client(cc *rpc.ClientConn) $Service$Client {\n" |
||||
"\treturn &$ServiceStruct$Client{cc}\n" |
||||
"}\n\n"); |
||||
for (int i = 0; i < service->method_count(); ++i) { |
||||
PrintClientMethodImpl(printer, service->method(i), vars); |
||||
} |
||||
} |
||||
|
||||
void PrintServerMethodDef(google::protobuf::io::Printer* printer, |
||||
const google::protobuf::MethodDescriptor* method, |
||||
map<string, string>* vars) { |
||||
(*vars)["Method"] = method->name(); |
||||
(*vars)["Request"] = method->input_type()->name(); |
||||
(*vars)["Response"] = method->output_type()->name(); |
||||
if (NoStreaming(method)) { |
||||
printer->Print(*vars, |
||||
"\t$Method$(context.Context, *$Request$) (*$Response$, error)\n"); |
||||
} else if (BidiStreaming(method)) { |
||||
printer->Print(*vars, |
||||
"\t$Method$($Service$_$Method$Server) error\n"); |
||||
} else if (ServerOnlyStreaming(method)) { |
||||
printer->Print(*vars, |
||||
"\t$Method$(*$Request$, $Service$_$Method$Server) error\n"); |
||||
} else if (ClientOnlyStreaming(method)) { |
||||
printer->Print(*vars, |
||||
"\t$Method$($Service$_$Method$Server) error\n"); |
||||
} |
||||
} |
||||
|
||||
void PrintServerHandler(google::protobuf::io::Printer* printer, |
||||
const google::protobuf::MethodDescriptor* method, |
||||
map<string, string>* vars) { |
||||
(*vars)["Method"] = method->name(); |
||||
(*vars)["Request"] = method->input_type()->name(); |
||||
(*vars)["Response"] = method->output_type()->name(); |
||||
if (NoStreaming(method)) { |
||||
printer->Print(*vars, |
||||
"func _$Service$_$Method$_Handler(srv interface{}, ctx context.Context," |
||||
" buf []byte) (proto.Message, error) {\n"); |
||||
printer->Print(*vars, |
||||
"\tin := new($Request$)\n"); |
||||
printer->Print("\tif err := proto.Unmarshal(buf, in); err != nil {\n"); |
||||
printer->Print("\t\treturn nil, err\n"); |
||||
printer->Print("\t}\n"); |
||||
printer->Print(*vars, |
||||
"\tout, err := srv.($Service$Server).$Method$(ctx, in)\n"); |
||||
printer->Print("\tif err != nil {\n"); |
||||
printer->Print("\t\treturn nil, err\n"); |
||||
printer->Print("\t}\n"); |
||||
printer->Print("\treturn out, nil\n"); |
||||
printer->Print("}\n\n"); |
||||
} else if (BidiStreaming(method)) { |
||||
printer->Print(*vars, |
||||
"func _$Service$_$Method$_Handler(srv interface{}, stream rpc.Stream) " |
||||
"error {\n" |
||||
"\treturn srv.($Service$Server).$Method$(&$ServiceStruct$$Method$Server" |
||||
"{stream})\n" |
||||
"}\n\n"); |
||||
printer->Print(*vars, |
||||
"type $Service$_$Method$Server interface {\n" |
||||
"\tSend(*$Response$) error\n" |
||||
"\tRecv() (*$Request$, error)\n" |
||||
"\trpc.Stream\n" |
||||
"}\n\n"); |
||||
printer->Print(*vars, |
||||
"type $ServiceStruct$$Method$Server struct {\n" |
||||
"\trpc.Stream\n" |
||||
"}\n\n"); |
||||
printer->Print(*vars, |
||||
"func (x *$ServiceStruct$$Method$Server) Send(m *$Response$) error {\n" |
||||
"\treturn x.Stream.SendProto(m)\n" |
||||
"}\n\n"); |
||||
printer->Print(*vars, |
||||
"func (x *$ServiceStruct$$Method$Server) Recv() (*$Request$, error) " |
||||
"{\n" |
||||
"\tm := new($Request$)\n" |
||||
"\tif err := x.Stream.RecvProto(m); err != nil {\n" |
||||
"\t\treturn nil, err\n" |
||||
"\t}\n" |
||||
"\treturn m, nil\n" |
||||
"}\n\n"); |
||||
} else if (ServerOnlyStreaming(method)) { |
||||
printer->Print(*vars, |
||||
"func _$Service$_$Method$_Handler(srv interface{}, stream rpc.Stream) " |
||||
"error {\n" |
||||
"\tm := new($Request$)\n" |
||||
"\tif err := stream.RecvProto(m); err != nil {\n" |
||||
"\t\treturn err\n" |
||||
"\t}\n" |
||||
"\treturn srv.($Service$Server).$Method$(m, " |
||||
"&$ServiceStruct$$Method$Server{stream})\n" |
||||
"}\n\n"); |
||||
printer->Print(*vars, |
||||
"type $Service$_$Method$Server interface {\n" |
||||
"\tSend(*$Response$) error\n" |
||||
"\trpc.Stream\n" |
||||
"}\n\n"); |
||||
printer->Print(*vars, |
||||
"type $ServiceStruct$$Method$Server struct {\n" |
||||
"\trpc.Stream\n" |
||||
"}\n\n"); |
||||
printer->Print(*vars, |
||||
"func (x *$ServiceStruct$$Method$Server) Send(m *$Response$) error {\n" |
||||
"\treturn x.Stream.SendProto(m)\n" |
||||
"}\n\n"); |
||||
} else if (ClientOnlyStreaming(method)) { |
||||
printer->Print(*vars, |
||||
"func _$Service$_$Method$_Handler(srv interface{}, stream rpc.Stream) " |
||||
"error {\n" |
||||
"\treturn srv.($Service$Server).$Method$(&$ServiceStruct$$Method$Server" |
||||
"{stream})\n" |
||||
"}\n\n"); |
||||
printer->Print(*vars, |
||||
"type $Service$_$Method$Server interface {\n" |
||||
"\tSendAndClose(*$Response$) error\n" |
||||
"\tRecv() (*$Request$, error)\n" |
||||
"\trpc.Stream\n" |
||||
"}\n\n"); |
||||
printer->Print(*vars, |
||||
"type $ServiceStruct$$Method$Server struct {\n" |
||||
"\trpc.Stream\n" |
||||
"}\n\n"); |
||||
printer->Print(*vars, |
||||
"func (x *$ServiceStruct$$Method$Server) SendAndClose(m *$Response$) " |
||||
"error {\n" |
||||
"\tif err := x.Stream.SendProto(m); err != nil {\n" |
||||
"\t\treturn err\n" |
||||
"\t}\n" |
||||
"\treturn nil\n" |
||||
"}\n\n"); |
||||
printer->Print(*vars, |
||||
"func (x *$ServiceStruct$$Method$Server) Recv() (*$Request$, error) {\n" |
||||
"\tm := new($Request$)\n" |
||||
"\tif err := x.Stream.RecvProto(m); err != nil {\n" |
||||
"\t\treturn nil, err\n" |
||||
"\t}\n" |
||||
"\treturn m, nil\n" |
||||
"}\n\n"); |
||||
} |
||||
} |
||||
|
||||
void PrintServerMethodDesc(google::protobuf::io::Printer* printer, |
||||
const google::protobuf::MethodDescriptor* method, |
||||
map<string, string>* vars) { |
||||
(*vars)["Method"] = method->name(); |
||||
printer->Print("\t\t{\n"); |
||||
printer->Print(*vars, |
||||
"\t\t\tMethodName:\t\"$Method$\",\n"); |
||||
printer->Print(*vars, |
||||
"\t\t\tHandler:\t_$Service$_$Method$_Handler,\n"); |
||||
printer->Print("\t\t},\n"); |
||||
} |
||||
|
||||
void PrintServerStreamingMethodDesc(google::protobuf::io::Printer* printer, |
||||
const google::protobuf::MethodDescriptor* method, |
||||
map<string, string>* vars) { |
||||
(*vars)["Method"] = method->name(); |
||||
printer->Print("\t\t{\n"); |
||||
printer->Print(*vars, |
||||
"\t\t\tStreamName:\t\"$Method$\",\n"); |
||||
printer->Print(*vars, |
||||
"\t\t\tHandler:\t_$Service$_$Method$_Handler,\n"); |
||||
printer->Print("\t\t},\n"); |
||||
} |
||||
|
||||
void PrintServer(google::protobuf::io::Printer* printer, |
||||
const google::protobuf::ServiceDescriptor* service, |
||||
map<string, string>* vars) { |
||||
(*vars)["Service"] = service->name(); |
||||
printer->Print(*vars, "type $Service$Server interface {\n"); |
||||
for (int i = 0; i < service->method_count(); ++i) { |
||||
PrintServerMethodDef(printer, service->method(i), vars); |
||||
} |
||||
printer->Print("}\n\n"); |
||||
|
||||
printer->Print(*vars, |
||||
"func RegisterService(s *rpc.Server, srv $Service$Server) {\n" |
||||
"\ts.RegisterService(&_$Service$_serviceDesc, srv)\n" |
||||
"}\n\n"); |
||||
|
||||
for (int i = 0; i < service->method_count(); ++i) { |
||||
PrintServerHandler(printer, service->method(i), vars); |
||||
} |
||||
|
||||
printer->Print(*vars, |
||||
"var _$Service$_serviceDesc = rpc.ServiceDesc{\n" |
||||
"\tServiceName: \"$Package$$Service$\",\n" |
||||
"\tHandlerType: (*$Service$Server)(nil),\n" |
||||
"\tMethods: []rpc.MethodDesc{\n"); |
||||
for (int i = 0; i < service->method_count(); ++i) { |
||||
if (NoStreaming(service->method(i))) { |
||||
PrintServerMethodDesc(printer, service->method(i), vars); |
||||
} |
||||
} |
||||
printer->Print("\t},\n"); |
||||
|
||||
printer->Print("\tStreams: []rpc.StreamDesc{\n"); |
||||
for (int i = 0; i < service->method_count(); ++i) { |
||||
if (!NoStreaming(service->method(i))) { |
||||
PrintServerStreamingMethodDesc(printer, service->method(i), vars); |
||||
} |
||||
} |
||||
printer->Print("\t},\n" |
||||
"}\n\n"); |
||||
} |
||||
|
||||
std::string BadToUnderscore(std::string str) { |
||||
for (unsigned i = 0; i < str.size(); ++i) { |
||||
if (!std::isalnum(str[i])) { |
||||
str[i] = '_'; |
||||
} |
||||
} |
||||
return str; |
||||
} |
||||
|
||||
string GetServices(const google::protobuf::FileDescriptor* file) { |
||||
string output; |
||||
google::protobuf::io::StringOutputStream output_stream(&output); |
||||
google::protobuf::io::Printer printer(&output_stream, '$'); |
||||
map<string, string> vars; |
||||
|
||||
string package_name = !file->options().go_package().empty() |
||||
? file->options().go_package() |
||||
: file->package(); |
||||
vars["PackageName"] = BadToUnderscore(package_name); |
||||
printer.Print(vars, "package $PackageName$\n\n"); |
||||
printer.Print("import (\n"); |
||||
if (HasClientOnlyStreaming(file)) { |
||||
printer.Print("\t\"fmt\"\n" |
||||
"\t\"io\"\n"); |
||||
} |
||||
printer.Print( |
||||
"\t\"google/net/grpc/go/rpc\"\n" |
||||
"\tcontext \"google/third_party/golang/go_net/context/context\"\n" |
||||
"\tproto \"google/net/proto2/go/proto\"\n" |
||||
")\n\n"); |
||||
|
||||
// $Package$ is used to fully qualify method names.
|
||||
vars["Package"] = file->package(); |
||||
if (!file->package().empty()) { |
||||
vars["Package"].append("."); |
||||
} |
||||
|
||||
for (int i = 0; i < file->service_count(); ++i) { |
||||
PrintClient(&printer, file->service(0), &vars); |
||||
printer.Print("\n"); |
||||
PrintServer(&printer, file->service(0), &vars); |
||||
printer.Print("\n"); |
||||
} |
||||
return output; |
||||
} |
||||
|
||||
} // namespace grpc_go_generator
|
@ -1,83 +0,0 @@ |
||||
/*
|
||||
* |
||||
* Copyright 2014, Google Inc. |
||||
* All rights reserved. |
||||
* |
||||
* Redistribution and use in source and binary forms, with or without |
||||
* modification, are permitted provided that the following conditions are |
||||
* met: |
||||
* |
||||
* * Redistributions of source code must retain the above copyright |
||||
* notice, this list of conditions and the following disclaimer. |
||||
* * Redistributions in binary form must reproduce the above |
||||
* copyright notice, this list of conditions and the following disclaimer |
||||
* in the documentation and/or other materials provided with the |
||||
* distribution. |
||||
* * Neither the name of Google Inc. nor the names of its |
||||
* contributors may be used to endorse or promote products derived from |
||||
* this software without specific prior written permission. |
||||
* |
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS |
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT |
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR |
||||
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT |
||||
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, |
||||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT |
||||
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE |
||||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
||||
* |
||||
*/ |
||||
|
||||
// Generates go gRPC service interface out of Protobuf IDL.
|
||||
//
|
||||
// This is a Proto2 compiler plugin. See net/proto2/compiler/proto/plugin.proto
|
||||
// and net/proto2/compiler/public/plugin.h for more information on plugins.
|
||||
|
||||
#include <fstream> |
||||
#include <memory> |
||||
|
||||
using namespace std; |
||||
|
||||
#include "src/compiler/go_generator.h" |
||||
#include <google/protobuf/compiler/code_generator.h> |
||||
#include <google/protobuf/compiler/plugin.h> |
||||
#include <google/protobuf/io/coded_stream.h> |
||||
#include <google/protobuf/io/zero_copy_stream.h> |
||||
#include <google/protobuf/descriptor.h> |
||||
|
||||
class GoGrpcGenerator : public google::protobuf::compiler::CodeGenerator { |
||||
public: |
||||
GoGrpcGenerator() {} |
||||
virtual ~GoGrpcGenerator() {} |
||||
|
||||
virtual bool Generate(const google::protobuf::FileDescriptor* file, |
||||
const string& parameter, |
||||
google::protobuf::compiler::GeneratorContext* context, |
||||
string* error) const { |
||||
// Get output file name.
|
||||
string file_name; |
||||
if (file->name().size() > 6 && |
||||
file->name().find_last_of(".proto") == file->name().size() - 1) { |
||||
file_name = file->name().substr(0, file->name().size() - 6) + |
||||
"_grpc.pb.go"; |
||||
} else { |
||||
*error = "Invalid proto file name. Proto file must end with .proto"; |
||||
return false; |
||||
} |
||||
|
||||
std::unique_ptr<google::protobuf::io::ZeroCopyOutputStream> output( |
||||
context->Open(file_name)); |
||||
google::protobuf::io::CodedOutputStream coded_out(output.get()); |
||||
string code = grpc_go_generator::GetServices(file); |
||||
coded_out.WriteRaw(code.data(), code.size()); |
||||
return true; |
||||
} |
||||
}; |
||||
|
||||
int main(int argc, char* argv[]) { |
||||
GoGrpcGenerator generator; |
||||
return google::protobuf::compiler::PluginMain(argc, argv, &generator); |
||||
} |
@ -0,0 +1,68 @@ |
||||
/*
|
||||
* |
||||
* Copyright 2015, Google Inc. |
||||
* All rights reserved. |
||||
* |
||||
* Redistribution and use in source and binary forms, with or without |
||||
* modification, are permitted provided that the following conditions are |
||||
* met: |
||||
* |
||||
* * Redistributions of source code must retain the above copyright |
||||
* notice, this list of conditions and the following disclaimer. |
||||
* * Redistributions in binary form must reproduce the above |
||||
* copyright notice, this list of conditions and the following disclaimer |
||||
* in the documentation and/or other materials provided with the |
||||
* distribution. |
||||
* * Neither the name of Google Inc. nor the names of its |
||||
* contributors may be used to endorse or promote products derived from |
||||
* this software without specific prior written permission. |
||||
* |
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS |
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT |
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR |
||||
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT |
||||
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, |
||||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT |
||||
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE |
||||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
||||
* |
||||
*/ |
||||
|
||||
#ifndef __GRPC_INTERNAL_IOMGR_POLLSET_KICK_H_ |
||||
#define __GRPC_INTERNAL_IOMGR_POLLSET_KICK_H_ |
||||
|
||||
#include <grpc/support/port_platform.h> |
||||
|
||||
/* This is an abstraction around the typical pipe mechanism for waking up a
|
||||
thread sitting in a poll() style call. */ |
||||
|
||||
#ifdef GPR_POSIX_SOCKET |
||||
#include "src/core/iomgr/pollset_kick_posix.h" |
||||
#else |
||||
#error "No pollset kick support on platform" |
||||
#endif |
||||
|
||||
void grpc_pollset_kick_global_init(void); |
||||
void grpc_pollset_kick_global_destroy(void); |
||||
|
||||
void grpc_pollset_kick_init(grpc_pollset_kick_state *kick_state); |
||||
void grpc_pollset_kick_destroy(grpc_pollset_kick_state *kick_state); |
||||
|
||||
/* Must be called before entering poll(). If return value is -1, this consumed
|
||||
an existing kick. Otherwise the return value is an FD to add to the poll set. |
||||
*/ |
||||
int grpc_pollset_kick_pre_poll(grpc_pollset_kick_state *kick_state); |
||||
|
||||
/* Consume an existing kick. Must be called after poll returns that the fd was
|
||||
readable, and before calling kick_post_poll. */ |
||||
void grpc_pollset_kick_consume(grpc_pollset_kick_state *kick_state); |
||||
|
||||
/* Must be called after pre_poll, and after consume if applicable */ |
||||
void grpc_pollset_kick_post_poll(grpc_pollset_kick_state *kick_state); |
||||
|
||||
void grpc_pollset_kick_kick(grpc_pollset_kick_state *kick_state); |
||||
|
||||
#endif /* __GRPC_INTERNAL_IOMGR_POLLSET_KICK_H_ */ |
@ -0,0 +1,161 @@ |
||||
/*
|
||||
* |
||||
* Copyright 2015, Google Inc. |
||||
* All rights reserved. |
||||
* |
||||
* Redistribution and use in source and binary forms, with or without |
||||
* modification, are permitted provided that the following conditions are |
||||
* met: |
||||
* |
||||
* * Redistributions of source code must retain the above copyright |
||||
* notice, this list of conditions and the following disclaimer. |
||||
* * Redistributions in binary form must reproduce the above |
||||
* copyright notice, this list of conditions and the following disclaimer |
||||
* in the documentation and/or other materials provided with the |
||||
* distribution. |
||||
* * Neither the name of Google Inc. nor the names of its |
||||
* contributors may be used to endorse or promote products derived from |
||||
* this software without specific prior written permission. |
||||
* |
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS |
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT |
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR |
||||
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT |
||||
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, |
||||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT |
||||
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE |
||||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
||||
* |
||||
*/ |
||||
|
||||
#include "src/core/iomgr/pollset_kick_posix.h" |
||||
|
||||
#include <errno.h> |
||||
#include <string.h> |
||||
#include <unistd.h> |
||||
|
||||
#include "src/core/iomgr/socket_utils_posix.h" |
||||
#include <grpc/support/alloc.h> |
||||
#include <grpc/support/log.h> |
||||
|
||||
/* This implementation is based on a freelist of pipes. */ |
||||
|
||||
typedef struct grpc_kick_pipe_info { |
||||
int pipe_read_fd; |
||||
int pipe_write_fd; |
||||
struct grpc_kick_pipe_info *next; |
||||
} grpc_kick_pipe_info; |
||||
|
||||
static grpc_kick_pipe_info *pipe_freelist = NULL; |
||||
static gpr_mu pipe_freelist_mu; |
||||
|
||||
static grpc_kick_pipe_info *allocate_pipe() { |
||||
grpc_kick_pipe_info *info; |
||||
gpr_mu_lock(&pipe_freelist_mu); |
||||
if (pipe_freelist != NULL) { |
||||
info = pipe_freelist; |
||||
pipe_freelist = pipe_freelist->next; |
||||
} else { |
||||
int pipefd[2]; |
||||
/* TODO(klempner): Make this nonfatal */ |
||||
GPR_ASSERT(0 == pipe(pipefd)); |
||||
GPR_ASSERT(grpc_set_socket_nonblocking(pipefd[0], 1)); |
||||
GPR_ASSERT(grpc_set_socket_nonblocking(pipefd[1], 1)); |
||||
info = gpr_malloc(sizeof(*info)); |
||||
info->pipe_read_fd = pipefd[0]; |
||||
info->pipe_write_fd = pipefd[1]; |
||||
info->next = NULL; |
||||
} |
||||
gpr_mu_unlock(&pipe_freelist_mu); |
||||
return info; |
||||
} |
||||
|
||||
static void free_pipe(grpc_kick_pipe_info *pipe_info) { |
||||
/* TODO(klempner): Start closing pipes if the free list gets too large */ |
||||
gpr_mu_lock(&pipe_freelist_mu); |
||||
pipe_info->next = pipe_freelist; |
||||
pipe_freelist = pipe_info; |
||||
gpr_mu_unlock(&pipe_freelist_mu); |
||||
} |
||||
|
||||
void grpc_pollset_kick_global_init() { |
||||
pipe_freelist = NULL; |
||||
gpr_mu_init(&pipe_freelist_mu); |
||||
} |
||||
|
||||
void grpc_pollset_kick_global_destroy() { |
||||
while (pipe_freelist != NULL) { |
||||
grpc_kick_pipe_info *current = pipe_freelist; |
||||
pipe_freelist = pipe_freelist->next; |
||||
close(current->pipe_read_fd); |
||||
close(current->pipe_write_fd); |
||||
gpr_free(current); |
||||
} |
||||
gpr_mu_destroy(&pipe_freelist_mu); |
||||
} |
||||
|
||||
void grpc_pollset_kick_init(grpc_pollset_kick_state *kick_state) { |
||||
gpr_mu_init(&kick_state->mu); |
||||
kick_state->kicked = 0; |
||||
kick_state->pipe_info = NULL; |
||||
} |
||||
|
||||
void grpc_pollset_kick_destroy(grpc_pollset_kick_state *kick_state) { |
||||
gpr_mu_destroy(&kick_state->mu); |
||||
GPR_ASSERT(kick_state->pipe_info == NULL); |
||||
} |
||||
|
||||
int grpc_pollset_kick_pre_poll(grpc_pollset_kick_state *kick_state) { |
||||
gpr_mu_lock(&kick_state->mu); |
||||
if (kick_state->kicked) { |
||||
kick_state->kicked = 0; |
||||
gpr_mu_unlock(&kick_state->mu); |
||||
return -1; |
||||
} |
||||
kick_state->pipe_info = allocate_pipe(); |
||||
gpr_mu_unlock(&kick_state->mu); |
||||
return kick_state->pipe_info->pipe_read_fd; |
||||
} |
||||
|
||||
void grpc_pollset_kick_consume(grpc_pollset_kick_state *kick_state) { |
||||
char buf[128]; |
||||
int r; |
||||
|
||||
for (;;) { |
||||
r = read(kick_state->pipe_info->pipe_read_fd, buf, sizeof(buf)); |
||||
if (r > 0) continue; |
||||
if (r == 0) return; |
||||
switch (errno) { |
||||
case EAGAIN: |
||||
return; |
||||
case EINTR: |
||||
continue; |
||||
default: |
||||
gpr_log(GPR_ERROR, "error reading pipe: %s", strerror(errno)); |
||||
return; |
||||
} |
||||
} |
||||
} |
||||
|
||||
void grpc_pollset_kick_post_poll(grpc_pollset_kick_state *kick_state) { |
||||
gpr_mu_lock(&kick_state->mu); |
||||
free_pipe(kick_state->pipe_info); |
||||
kick_state->pipe_info = NULL; |
||||
gpr_mu_unlock(&kick_state->mu); |
||||
} |
||||
|
||||
void grpc_pollset_kick_kick(grpc_pollset_kick_state *kick_state) { |
||||
gpr_mu_lock(&kick_state->mu); |
||||
if (kick_state->pipe_info != NULL) { |
||||
char c = 0; |
||||
while (write(kick_state->pipe_info->pipe_write_fd, &c, 1) != 1 && |
||||
errno == EINTR) |
||||
; |
||||
} else { |
||||
kick_state->kicked = 1; |
||||
} |
||||
gpr_mu_unlock(&kick_state->mu); |
||||
} |
@ -0,0 +1,47 @@ |
||||
/*
|
||||
* |
||||
* Copyright 2015, Google Inc. |
||||
* All rights reserved. |
||||
* |
||||
* Redistribution and use in source and binary forms, with or without |
||||
* modification, are permitted provided that the following conditions are |
||||
* met: |
||||
* |
||||
* * Redistributions of source code must retain the above copyright |
||||
* notice, this list of conditions and the following disclaimer. |
||||
* * Redistributions in binary form must reproduce the above |
||||
* copyright notice, this list of conditions and the following disclaimer |
||||
* in the documentation and/or other materials provided with the |
||||
* distribution. |
||||
* * Neither the name of Google Inc. nor the names of its |
||||
* contributors may be used to endorse or promote products derived from |
||||
* this software without specific prior written permission. |
||||
* |
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS |
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT |
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR |
||||
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT |
||||
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, |
||||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT |
||||
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE |
||||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
||||
* |
||||
*/ |
||||
|
||||
#ifndef __GRPC_INTERNAL_IOMGR_POLLSET_KICK_POSIX_H_ |
||||
#define __GRPC_INTERNAL_IOMGR_POLLSET_KICK_POSIX_H_ |
||||
|
||||
#include <grpc/support/sync.h> |
||||
|
||||
struct grpc_kick_pipe_info; |
||||
|
||||
typedef struct grpc_pollset_kick_state { |
||||
gpr_mu mu; |
||||
int kicked; |
||||
struct grpc_kick_pipe_info *pipe_info; |
||||
} grpc_pollset_kick_state; |
||||
|
||||
#endif /* __GRPC_INTERNAL_IOMGR_POLLSET_KICK_POSIX_H_ */ |
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in new issue