HDFS-8764. Generate Hadoop RPC stubs from protobuf definitions. Contributed by Haohui Mai.
This commit is contained in:
parent
65b864f341
commit
1bec75a13c
|
@ -18,4 +18,48 @@ protobuf_generate_cpp(PROTO_SRCS PROTO_HDRS
|
||||||
${COMMON_PROTO_DIR}/Security.proto
|
${COMMON_PROTO_DIR}/Security.proto
|
||||||
)
|
)
|
||||||
|
|
||||||
add_library(proto ${PROTO_SRCS} ${PROTO_HDRS})
|
add_executable(protoc-gen-hrpc protoc_gen_hrpc.cc)
|
||||||
|
target_link_libraries(protoc-gen-hrpc ${PROTOBUF_PROTOC_LIBRARY} ${PROTOBUF_LIBRARY})
|
||||||
|
|
||||||
|
function(GEN_HRPC SRCS)
|
||||||
|
if(NOT ARGN)
|
||||||
|
message(SEND_ERROR "Error: GEN_HRPC() called without any proto files")
|
||||||
|
return()
|
||||||
|
endif()
|
||||||
|
|
||||||
|
if(DEFINED PROTOBUF_IMPORT_DIRS)
|
||||||
|
foreach(DIR ${PROTOBUF_IMPORT_DIRS})
|
||||||
|
get_filename_component(ABS_PATH ${DIR} ABSOLUTE)
|
||||||
|
list(FIND _protobuf_include_path ${ABS_PATH} _contains_already)
|
||||||
|
if(${_contains_already} EQUAL -1)
|
||||||
|
list(APPEND _protobuf_include_path -I ${ABS_PATH})
|
||||||
|
endif()
|
||||||
|
endforeach()
|
||||||
|
endif()
|
||||||
|
|
||||||
|
set(${SRCS})
|
||||||
|
|
||||||
|
foreach(FIL ${ARGN})
|
||||||
|
get_filename_component(ABS_FIL ${FIL} ABSOLUTE)
|
||||||
|
get_filename_component(FIL_WE ${FIL} NAME_WE)
|
||||||
|
|
||||||
|
list(APPEND ${SRCS} "${CMAKE_CURRENT_BINARY_DIR}/${FIL_WE}.hrpc.inl")
|
||||||
|
|
||||||
|
add_custom_command(
|
||||||
|
OUTPUT "${CMAKE_CURRENT_BINARY_DIR}/${FIL_WE}.hrpc.inl"
|
||||||
|
COMMAND ${PROTOBUF_PROTOC_EXECUTABLE}
|
||||||
|
ARGS --plugin=protoc-gen-hrpc=${CMAKE_CURRENT_BINARY_DIR}/protoc-gen-hrpc --hrpc_out=${CMAKE_CURRENT_BINARY_DIR} ${_protobuf_include_path} ${ABS_FIL}
|
||||||
|
DEPENDS ${ABS_FIL} ${PROTOBUF_PROTOC_EXECUTABLE} protoc-gen-hrpc
|
||||||
|
COMMENT "Running HRPC protocol buffer compiler on ${FIL}"
|
||||||
|
VERBATIM )
|
||||||
|
endforeach()
|
||||||
|
|
||||||
|
set_source_files_properties(${${SRCS}} PROPERTIES GENERATED TRUE)
|
||||||
|
set(${SRCS} ${${SRCS}} PARENT_SCOPE)
|
||||||
|
endfunction()
|
||||||
|
|
||||||
|
gen_hrpc(HRPC_SRCS
|
||||||
|
${CLIENT_PROTO_DIR}/ClientNamenodeProtocol.proto
|
||||||
|
)
|
||||||
|
|
||||||
|
add_library(proto ${PROTO_SRCS} ${PROTO_HDRS} ${HRPC_SRCS})
|
||||||
|
|
|
@ -0,0 +1,82 @@
|
||||||
|
// Protocol Buffers - Google's data interchange format
|
||||||
|
// Copyright 2008 Google Inc. All rights reserved.
|
||||||
|
// https://developers.google.com/protocol-buffers/
|
||||||
|
//
|
||||||
|
// 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.
|
||||||
|
|
||||||
|
// Author: kenton@google.com (Kenton Varda)
|
||||||
|
// Based on original Protocol Buffers design by
|
||||||
|
// Sanjay Ghemawat, Jeff Dean, and others.
|
||||||
|
|
||||||
|
#ifndef LIBHDFSPP_PROTO_CPP_HELPERS_H_
|
||||||
|
#define LIBHDFSPP_PROTO_CPP_HELPERS_H_
|
||||||
|
|
||||||
|
#include <string>
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The functions in this file are derived from the original implementation of
|
||||||
|
*the protobuf library from Google.
|
||||||
|
**/
|
||||||
|
|
||||||
|
static inline std::string StripProto(const std::string &str) {
|
||||||
|
static const std::string kExtension = ".proto";
|
||||||
|
if (str.size() >= kExtension.size() &&
|
||||||
|
str.compare(str.size() - kExtension.size(), kExtension.size(),
|
||||||
|
kExtension) == 0) {
|
||||||
|
return str.substr(0, str.size() - kExtension.size());
|
||||||
|
} else {
|
||||||
|
return str;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline std::string ToCamelCase(const std::string &input) {
|
||||||
|
bool cap_next_letter = true;
|
||||||
|
std::string result;
|
||||||
|
// Note: I distrust ctype.h due to locales.
|
||||||
|
for (size_t i = 0; i < input.size(); i++) {
|
||||||
|
if ('a' <= input[i] && input[i] <= 'z') {
|
||||||
|
if (cap_next_letter) {
|
||||||
|
result += input[i] + ('A' - 'a');
|
||||||
|
} else {
|
||||||
|
result += input[i];
|
||||||
|
}
|
||||||
|
cap_next_letter = false;
|
||||||
|
} else if ('A' <= input[i] && input[i] <= 'Z') {
|
||||||
|
// Capital letters are left as-is.
|
||||||
|
result += input[i];
|
||||||
|
cap_next_letter = false;
|
||||||
|
} else if ('0' <= input[i] && input[i] <= '9') {
|
||||||
|
result += input[i];
|
||||||
|
cap_next_letter = true;
|
||||||
|
} else {
|
||||||
|
cap_next_letter = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
|
@ -0,0 +1,93 @@
|
||||||
|
/**
|
||||||
|
* Licensed to the Apache Software Foundation (ASF) under one
|
||||||
|
* or more contributor license agreements. See the NOTICE file
|
||||||
|
* distributed with this work for additional information
|
||||||
|
* regarding copyright ownership. The ASF licenses this file
|
||||||
|
* to you under the Apache License, Version 2.0 (the
|
||||||
|
* "License"); you may not use this file except in compliance
|
||||||
|
* with the License. You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "cpp_helpers.h"
|
||||||
|
|
||||||
|
#include <google/protobuf/compiler/code_generator.h>
|
||||||
|
#include <google/protobuf/compiler/plugin.h>
|
||||||
|
#include <google/protobuf/descriptor.h>
|
||||||
|
#include <google/protobuf/io/printer.h>
|
||||||
|
#include <google/protobuf/io/zero_copy_stream.h>
|
||||||
|
#include <google/protobuf/stubs/common.h>
|
||||||
|
|
||||||
|
using ::google::protobuf::FileDescriptor;
|
||||||
|
using ::google::protobuf::MethodDescriptor;
|
||||||
|
using ::google::protobuf::ServiceDescriptor;
|
||||||
|
using ::google::protobuf::compiler::CodeGenerator;
|
||||||
|
using ::google::protobuf::compiler::GeneratorContext;
|
||||||
|
using ::google::protobuf::io::Printer;
|
||||||
|
using ::google::protobuf::io::ZeroCopyOutputStream;
|
||||||
|
|
||||||
|
class StubGenerator : public CodeGenerator {
|
||||||
|
public:
|
||||||
|
virtual bool Generate(const FileDescriptor *file, const std::string &,
|
||||||
|
GeneratorContext *ctx,
|
||||||
|
std::string *error) const override;
|
||||||
|
|
||||||
|
private:
|
||||||
|
void EmitService(const ServiceDescriptor *service, Printer *out) const;
|
||||||
|
void EmitMethod(const MethodDescriptor *method, Printer *out) const;
|
||||||
|
};
|
||||||
|
|
||||||
|
bool StubGenerator::Generate(const FileDescriptor *file, const std::string &,
|
||||||
|
GeneratorContext *ctx, std::string *) const {
|
||||||
|
namespace pb = ::google::protobuf;
|
||||||
|
std::unique_ptr<ZeroCopyOutputStream> os(
|
||||||
|
ctx->Open(StripProto(file->name()) + ".hrpc.inl"));
|
||||||
|
Printer out(os.get(), '$');
|
||||||
|
for (int i = 0; i < file->service_count(); ++i) {
|
||||||
|
const ServiceDescriptor *service = file->service(i);
|
||||||
|
EmitService(service, &out);
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void StubGenerator::EmitService(const ServiceDescriptor *service,
|
||||||
|
Printer *out) const {
|
||||||
|
out->Print("\n// GENERATED AUTOMATICALLY. DO NOT MODIFY.\n"
|
||||||
|
"class $service$ {\n"
|
||||||
|
"private:\n"
|
||||||
|
" ::hdfs::RpcEngine *const engine_;\n"
|
||||||
|
"public:\n"
|
||||||
|
" typedef std::function<void(const ::hdfs::Status &)> Callback;\n"
|
||||||
|
" typedef ::google::protobuf::MessageLite Message;\n"
|
||||||
|
" inline $service$(::hdfs::RpcEngine *engine)\n"
|
||||||
|
" : engine_(engine) {}\n",
|
||||||
|
"service", service->name());
|
||||||
|
for (int i = 0; i < service->method_count(); ++i) {
|
||||||
|
const MethodDescriptor *method = service->method(i);
|
||||||
|
EmitMethod(method, out);
|
||||||
|
}
|
||||||
|
out->Print("};\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
void StubGenerator::EmitMethod(const MethodDescriptor *method,
|
||||||
|
Printer *out) const {
|
||||||
|
out->Print(
|
||||||
|
"\n inline void $camel_method$(const Message *req, "
|
||||||
|
"const std::shared_ptr<Message> &resp, "
|
||||||
|
"Callback &&handler) {\n"
|
||||||
|
" engine_->AsyncRpc(\"$method$\", req, resp, std::move(handler));\n"
|
||||||
|
" }\n",
|
||||||
|
"camel_method", ToCamelCase(method->name()), "method", method->name());
|
||||||
|
}
|
||||||
|
|
||||||
|
int main(int argc, char *argv[]) {
|
||||||
|
StubGenerator generator;
|
||||||
|
return google::protobuf::compiler::PluginMain(argc, argv, &generator);
|
||||||
|
}
|
Loading…
Reference in New Issue