From cf5b2666e16f7b6ebc1bda4a884045d1ef1a4134 Mon Sep 17 00:00:00 2001 From: ncteisen Date: Tue, 27 Feb 2018 11:55:10 -0800 Subject: [PATCH] Make GrpcProtoBufferReaderWriter public --- BUILD | 5 +- CMakeLists.txt | 15 +- Makefile | 15 +- build.yaml | 5 +- gRPC-C++.podspec | 3 +- grpc.gyp | 2 - include/grpcpp/impl/codegen/byte_buffer.h | 43 +++- include/grpcpp/impl/codegen/core_codegen.h | 3 + .../impl/codegen/core_codegen_interface.h | 5 + .../grpcpp/impl/codegen/proto_buffer_reader.h | 151 ++++++++++++ .../grpcpp/impl/codegen/proto_buffer_writer.h | 168 +++++++++++++ include/grpcpp/impl/codegen/proto_utils.h | 220 +++--------------- include/grpcpp/impl/codegen/slice.h | 39 +++- include/grpcpp/support/proto_buffer_reader.h | 24 ++ include/grpcpp/support/proto_buffer_writer.h | 24 ++ src/cpp/common/core_codegen.cc | 10 + src/cpp/util/byte_buffer_cc.cc | 42 ---- src/cpp/util/slice_cc.cc | 55 ----- test/cpp/codegen/proto_utils_test.cc | 42 ++-- test/cpp/util/byte_buffer_test.cc | 6 +- test/cpp/util/slice_test.cc | 6 +- tools/doxygen/Doxyfile.c++ | 4 + tools/doxygen/Doxyfile.c++.internal | 5 +- .../generated/sources_and_headers.json | 9 +- 24 files changed, 574 insertions(+), 327 deletions(-) create mode 100644 include/grpcpp/impl/codegen/proto_buffer_reader.h create mode 100644 include/grpcpp/impl/codegen/proto_buffer_writer.h create mode 100644 include/grpcpp/support/proto_buffer_reader.h create mode 100644 include/grpcpp/support/proto_buffer_writer.h delete mode 100644 src/cpp/util/slice_cc.cc diff --git a/BUILD b/BUILD index ece6cd182d7..0250eaab7cd 100644 --- a/BUILD +++ b/BUILD @@ -141,7 +141,6 @@ GRPCXX_SRCS = [ "src/cpp/server/server_posix.cc", "src/cpp/thread_manager/thread_manager.cc", "src/cpp/util/byte_buffer_cc.cc", - "src/cpp/util/slice_cc.cc", "src/cpp/util/status.cc", "src/cpp/util/string_ref.cc", "src/cpp/util/time_cc.cc", @@ -245,6 +244,8 @@ GRPCXX_PUBLIC_HDRS = [ "include/grpcpp/support/byte_buffer.h", "include/grpcpp/support/channel_arguments.h", "include/grpcpp/support/config.h", + "include/grpcpp/support/proto_buffer_reader.h", + "include/grpcpp/support/proto_buffer_writer.h", "include/grpcpp/support/slice.h", "include/grpcpp/support/status.h", "include/grpcpp/support/status_code_enum.h", @@ -1871,6 +1872,8 @@ grpc_cc_library( language = "c++", public_hdrs = [ "include/grpc++/impl/codegen/proto_utils.h", + "include/grpcpp/impl/codegen/proto_buffer_reader.h", + "include/grpcpp/impl/codegen/proto_buffer_writer.h", "include/grpcpp/impl/codegen/proto_utils.h", ], deps = [ diff --git a/CMakeLists.txt b/CMakeLists.txt index d94422f741e..18400ea22a3 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -2716,7 +2716,6 @@ add_library(grpc++ src/cpp/server/server_posix.cc src/cpp/thread_manager/thread_manager.cc src/cpp/util/byte_buffer_cc.cc - src/cpp/util/slice_cc.cc src/cpp/util/status.cc src/cpp/util/string_ref.cc src/cpp/util/time_cc.cc @@ -2841,6 +2840,8 @@ foreach(_hdr include/grpcpp/support/byte_buffer.h include/grpcpp/support/channel_arguments.h include/grpcpp/support/config.h + include/grpcpp/support/proto_buffer_reader.h + include/grpcpp/support/proto_buffer_writer.h include/grpcpp/support/slice.h include/grpcpp/support/status.h include/grpcpp/support/status_code_enum.h @@ -2959,6 +2960,8 @@ foreach(_hdr include/grpcpp/impl/codegen/sync_stream.h include/grpcpp/impl/codegen/time.h include/grpc++/impl/codegen/proto_utils.h + include/grpcpp/impl/codegen/proto_buffer_reader.h + include/grpcpp/impl/codegen/proto_buffer_writer.h include/grpcpp/impl/codegen/proto_utils.h include/grpc++/impl/codegen/config_protobuf.h include/grpcpp/impl/codegen/config_protobuf.h @@ -3067,7 +3070,6 @@ add_library(grpc++_cronet src/cpp/server/server_posix.cc src/cpp/thread_manager/thread_manager.cc src/cpp/util/byte_buffer_cc.cc - src/cpp/util/slice_cc.cc src/cpp/util/status.cc src/cpp/util/string_ref.cc src/cpp/util/time_cc.cc @@ -3402,6 +3404,8 @@ foreach(_hdr include/grpcpp/support/byte_buffer.h include/grpcpp/support/channel_arguments.h include/grpcpp/support/config.h + include/grpcpp/support/proto_buffer_reader.h + include/grpcpp/support/proto_buffer_writer.h include/grpcpp/support/slice.h include/grpcpp/support/status.h include/grpcpp/support/status_code_enum.h @@ -3945,6 +3949,8 @@ foreach(_hdr include/grpc/impl/codegen/sync_posix.h include/grpc/impl/codegen/sync_windows.h include/grpc++/impl/codegen/proto_utils.h + include/grpcpp/impl/codegen/proto_buffer_reader.h + include/grpcpp/impl/codegen/proto_buffer_writer.h include/grpcpp/impl/codegen/proto_utils.h include/grpc++/impl/codegen/config_protobuf.h include/grpcpp/impl/codegen/config_protobuf.h @@ -4118,6 +4124,8 @@ foreach(_hdr include/grpc/impl/codegen/sync_posix.h include/grpc/impl/codegen/sync_windows.h include/grpc++/impl/codegen/proto_utils.h + include/grpcpp/impl/codegen/proto_buffer_reader.h + include/grpcpp/impl/codegen/proto_buffer_writer.h include/grpcpp/impl/codegen/proto_utils.h include/grpc++/impl/codegen/config_protobuf.h include/grpcpp/impl/codegen/config_protobuf.h @@ -4166,7 +4174,6 @@ add_library(grpc++_unsecure src/cpp/server/server_posix.cc src/cpp/thread_manager/thread_manager.cc src/cpp/util/byte_buffer_cc.cc - src/cpp/util/slice_cc.cc src/cpp/util/status.cc src/cpp/util/string_ref.cc src/cpp/util/time_cc.cc @@ -4290,6 +4297,8 @@ foreach(_hdr include/grpcpp/support/byte_buffer.h include/grpcpp/support/channel_arguments.h include/grpcpp/support/config.h + include/grpcpp/support/proto_buffer_reader.h + include/grpcpp/support/proto_buffer_writer.h include/grpcpp/support/slice.h include/grpcpp/support/status.h include/grpcpp/support/status_code_enum.h diff --git a/Makefile b/Makefile index 77ef1b3cbc2..da5f2efebf9 100644 --- a/Makefile +++ b/Makefile @@ -5019,7 +5019,6 @@ LIBGRPC++_SRC = \ src/cpp/server/server_posix.cc \ src/cpp/thread_manager/thread_manager.cc \ src/cpp/util/byte_buffer_cc.cc \ - src/cpp/util/slice_cc.cc \ src/cpp/util/status.cc \ src/cpp/util/string_ref.cc \ src/cpp/util/time_cc.cc \ @@ -5109,6 +5108,8 @@ PUBLIC_HEADERS_CXX += \ include/grpcpp/support/byte_buffer.h \ include/grpcpp/support/channel_arguments.h \ include/grpcpp/support/config.h \ + include/grpcpp/support/proto_buffer_reader.h \ + include/grpcpp/support/proto_buffer_writer.h \ include/grpcpp/support/slice.h \ include/grpcpp/support/status.h \ include/grpcpp/support/status_code_enum.h \ @@ -5227,6 +5228,8 @@ PUBLIC_HEADERS_CXX += \ include/grpcpp/impl/codegen/sync_stream.h \ include/grpcpp/impl/codegen/time.h \ include/grpc++/impl/codegen/proto_utils.h \ + include/grpcpp/impl/codegen/proto_buffer_reader.h \ + include/grpcpp/impl/codegen/proto_buffer_writer.h \ include/grpcpp/impl/codegen/proto_utils.h \ include/grpc++/impl/codegen/config_protobuf.h \ include/grpcpp/impl/codegen/config_protobuf.h \ @@ -5380,7 +5383,6 @@ LIBGRPC++_CRONET_SRC = \ src/cpp/server/server_posix.cc \ src/cpp/thread_manager/thread_manager.cc \ src/cpp/util/byte_buffer_cc.cc \ - src/cpp/util/slice_cc.cc \ src/cpp/util/status.cc \ src/cpp/util/string_ref.cc \ src/cpp/util/time_cc.cc \ @@ -5679,6 +5681,8 @@ PUBLIC_HEADERS_CXX += \ include/grpcpp/support/byte_buffer.h \ include/grpcpp/support/channel_arguments.h \ include/grpcpp/support/config.h \ + include/grpcpp/support/proto_buffer_reader.h \ + include/grpcpp/support/proto_buffer_writer.h \ include/grpcpp/support/slice.h \ include/grpcpp/support/status.h \ include/grpcpp/support/status_code_enum.h \ @@ -6207,6 +6211,8 @@ PUBLIC_HEADERS_CXX += \ include/grpc/impl/codegen/sync_posix.h \ include/grpc/impl/codegen/sync_windows.h \ include/grpc++/impl/codegen/proto_utils.h \ + include/grpcpp/impl/codegen/proto_buffer_reader.h \ + include/grpcpp/impl/codegen/proto_buffer_writer.h \ include/grpcpp/impl/codegen/proto_utils.h \ include/grpc++/impl/codegen/config_protobuf.h \ include/grpcpp/impl/codegen/config_protobuf.h \ @@ -6357,6 +6363,8 @@ PUBLIC_HEADERS_CXX += \ include/grpc/impl/codegen/sync_posix.h \ include/grpc/impl/codegen/sync_windows.h \ include/grpc++/impl/codegen/proto_utils.h \ + include/grpcpp/impl/codegen/proto_buffer_reader.h \ + include/grpcpp/impl/codegen/proto_buffer_writer.h \ include/grpcpp/impl/codegen/proto_utils.h \ include/grpc++/impl/codegen/config_protobuf.h \ include/grpcpp/impl/codegen/config_protobuf.h \ @@ -6444,7 +6452,6 @@ LIBGRPC++_UNSECURE_SRC = \ src/cpp/server/server_posix.cc \ src/cpp/thread_manager/thread_manager.cc \ src/cpp/util/byte_buffer_cc.cc \ - src/cpp/util/slice_cc.cc \ src/cpp/util/status.cc \ src/cpp/util/string_ref.cc \ src/cpp/util/time_cc.cc \ @@ -6534,6 +6541,8 @@ PUBLIC_HEADERS_CXX += \ include/grpcpp/support/byte_buffer.h \ include/grpcpp/support/channel_arguments.h \ include/grpcpp/support/config.h \ + include/grpcpp/support/proto_buffer_reader.h \ + include/grpcpp/support/proto_buffer_writer.h \ include/grpcpp/support/slice.h \ include/grpcpp/support/status.h \ include/grpcpp/support/status_code_enum.h \ diff --git a/build.yaml b/build.yaml index aa5a40d8495..594df9526cd 100644 --- a/build.yaml +++ b/build.yaml @@ -1164,6 +1164,8 @@ filegroups: language: c++ public_headers: - include/grpc++/impl/codegen/proto_utils.h + - include/grpcpp/impl/codegen/proto_buffer_reader.h + - include/grpcpp/impl/codegen/proto_buffer_writer.h - include/grpcpp/impl/codegen/proto_utils.h uses: - grpc++_codegen_base @@ -1254,6 +1256,8 @@ filegroups: - include/grpcpp/support/byte_buffer.h - include/grpcpp/support/channel_arguments.h - include/grpcpp/support/config.h + - include/grpcpp/support/proto_buffer_reader.h + - include/grpcpp/support/proto_buffer_writer.h - include/grpcpp/support/slice.h - include/grpcpp/support/status.h - include/grpcpp/support/status_code_enum.h @@ -1300,7 +1304,6 @@ filegroups: - src/cpp/server/server_posix.cc - src/cpp/thread_manager/thread_manager.cc - src/cpp/util/byte_buffer_cc.cc - - src/cpp/util/slice_cc.cc - src/cpp/util/status.cc - src/cpp/util/string_ref.cc - src/cpp/util/time_cc.cc diff --git a/gRPC-C++.podspec b/gRPC-C++.podspec index c5a4e50cd3e..990b0a4f9d1 100644 --- a/gRPC-C++.podspec +++ b/gRPC-C++.podspec @@ -112,6 +112,8 @@ Pod::Spec.new do |s| 'include/grpcpp/support/byte_buffer.h', 'include/grpcpp/support/channel_arguments.h', 'include/grpcpp/support/config.h', + 'include/grpcpp/support/proto_buffer_reader.h', + 'include/grpcpp/support/proto_buffer_writer.h', 'include/grpcpp/support/slice.h', 'include/grpcpp/support/status.h', 'include/grpcpp/support/status_code_enum.h', @@ -206,7 +208,6 @@ Pod::Spec.new do |s| 'src/cpp/server/server_posix.cc', 'src/cpp/thread_manager/thread_manager.cc', 'src/cpp/util/byte_buffer_cc.cc', - 'src/cpp/util/slice_cc.cc', 'src/cpp/util/status.cc', 'src/cpp/util/string_ref.cc', 'src/cpp/util/time_cc.cc', diff --git a/grpc.gyp b/grpc.gyp index 30664695b3f..8d9422eee6e 100644 --- a/grpc.gyp +++ b/grpc.gyp @@ -1342,7 +1342,6 @@ 'src/cpp/server/server_posix.cc', 'src/cpp/thread_manager/thread_manager.cc', 'src/cpp/util/byte_buffer_cc.cc', - 'src/cpp/util/slice_cc.cc', 'src/cpp/util/status.cc', 'src/cpp/util/string_ref.cc', 'src/cpp/util/time_cc.cc', @@ -1490,7 +1489,6 @@ 'src/cpp/server/server_posix.cc', 'src/cpp/thread_manager/thread_manager.cc', 'src/cpp/util/byte_buffer_cc.cc', - 'src/cpp/util/slice_cc.cc', 'src/cpp/util/status.cc', 'src/cpp/util/string_ref.cc', 'src/cpp/util/time_cc.cc', diff --git a/include/grpcpp/impl/codegen/byte_buffer.h b/include/grpcpp/impl/codegen/byte_buffer.h index e637efeb857..fda13a04e6b 100644 --- a/include/grpcpp/impl/codegen/byte_buffer.h +++ b/include/grpcpp/impl/codegen/byte_buffer.h @@ -31,6 +31,8 @@ namespace grpc { +class ServerInterface; +class ByteBuffer; class ServerInterface; namespace internal { @@ -45,6 +47,7 @@ template class ServerStreamingHandler; template class DeserializeFuncType; +class GrpcByteBufferPeer; } // namespace internal /// A sequence of bytes. class ByteBuffer final { @@ -53,7 +56,30 @@ class ByteBuffer final { ByteBuffer() : buffer_(nullptr) {} /// Construct buffer from \a slices, of which there are \a nslices. - ByteBuffer(const Slice* slices, size_t nslices); + ByteBuffer(const Slice* slices, size_t nslices) { + // The following assertions check that the representation of a grpc::Slice + // is identical to that of a grpc_slice: it has a grpc_slice field, and + // nothing else. + static_assert(std::is_same::value, + "Slice must have same representation as grpc_slice"); + static_assert(sizeof(Slice) == sizeof(grpc_slice), + "Slice must have same representation as grpc_slice"); + // The following assertions check that the representation of a ByteBuffer is + // identical to grpc_byte_buffer*: it has a grpc_byte_buffer* field, + // and nothing else. + static_assert(std::is_same::value, + "ByteBuffer must have same representation as " + "grpc_byte_buffer*"); + static_assert(sizeof(ByteBuffer) == sizeof(grpc_byte_buffer*), + "ByteBuffer must have same representation as " + "grpc_byte_buffer*"); + // The const_cast is legal if grpc_raw_byte_buffer_create() does no more + // than its advertised side effect of increasing the reference count of the + // slices it processes, and such an increase does not affect the semantics + // seen by the caller of this constructor. + buffer_ = g_core_codegen_interface->grpc_raw_byte_buffer_create( + reinterpret_cast(const_cast(slices)), nslices); + } /// Constuct a byte buffer by referencing elements of existing buffer /// \a buf. Wrapper of core function grpc_byte_buffer_copy @@ -90,10 +116,18 @@ class ByteBuffer final { void Release() { buffer_ = nullptr; } /// Buffer size in bytes. - size_t Length() const; + size_t Length() const { + return buffer_ == nullptr + ? 0 + : g_core_codegen_interface->grpc_byte_buffer_length(buffer_); + } /// Swap the state of *this and *other. - void Swap(ByteBuffer* other); + void Swap(ByteBuffer* other) { + grpc_byte_buffer* tmp = other->buffer_; + other->buffer_ = buffer_; + buffer_ = tmp; + } /// Is this ByteBuffer valid? bool Valid() const { return (buffer_ != nullptr); } @@ -112,6 +146,9 @@ class ByteBuffer final { friend class internal::ServerStreamingHandler; template friend class internal::DeserializeFuncType; + friend class GrpcProtoBufferReader; + friend class GrpcProtoBufferWriter; + friend class internal::GrpcByteBufferPeer; grpc_byte_buffer* buffer_; diff --git a/include/grpcpp/impl/codegen/core_codegen.h b/include/grpcpp/impl/codegen/core_codegen.h index 0ca4ad524c4..e9df96bf048 100644 --- a/include/grpcpp/impl/codegen/core_codegen.h +++ b/include/grpcpp/impl/codegen/core_codegen.h @@ -73,6 +73,7 @@ class CoreCodegen final : public CoreCodegenInterface { grpc_byte_buffer* grpc_byte_buffer_copy(grpc_byte_buffer* bb) override; void grpc_byte_buffer_destroy(grpc_byte_buffer* bb) override; + size_t grpc_byte_buffer_length(grpc_byte_buffer* bb) override; int grpc_byte_buffer_reader_init(grpc_byte_buffer_reader* reader, grpc_byte_buffer* buffer) override; @@ -86,6 +87,8 @@ class CoreCodegen final : public CoreCodegenInterface { grpc_slice grpc_slice_new_with_user_data(void* p, size_t len, void (*destroy)(void*), void* user_data) override; + grpc_slice grpc_slice_new_with_len(void* p, size_t len, + void (*destroy)(void*, size_t)) override; grpc_slice grpc_empty_slice() override; grpc_slice grpc_slice_malloc(size_t length) override; void grpc_slice_unref(grpc_slice slice) override; diff --git a/include/grpcpp/impl/codegen/core_codegen_interface.h b/include/grpcpp/impl/codegen/core_codegen_interface.h index d72f579c8e8..1167a188a24 100644 --- a/include/grpcpp/impl/codegen/core_codegen_interface.h +++ b/include/grpcpp/impl/codegen/core_codegen_interface.h @@ -81,6 +81,8 @@ class CoreCodegenInterface { virtual grpc_byte_buffer* grpc_byte_buffer_copy(grpc_byte_buffer* bb) = 0; virtual void grpc_byte_buffer_destroy(grpc_byte_buffer* bb) = 0; + virtual size_t grpc_byte_buffer_length(grpc_byte_buffer* bb) + GRPC_MUST_USE_RESULT = 0; virtual int grpc_byte_buffer_reader_init(grpc_byte_buffer_reader* reader, grpc_byte_buffer* buffer) @@ -95,6 +97,9 @@ class CoreCodegenInterface { virtual grpc_slice grpc_slice_new_with_user_data(void* p, size_t len, void (*destroy)(void*), void* user_data) = 0; + virtual grpc_slice grpc_slice_new_with_len(void* p, size_t len, + void (*destroy)(void*, + size_t)) = 0; virtual grpc_call_error grpc_call_cancel_with_status(grpc_call* call, grpc_status_code status, const char* description, diff --git a/include/grpcpp/impl/codegen/proto_buffer_reader.h b/include/grpcpp/impl/codegen/proto_buffer_reader.h new file mode 100644 index 00000000000..149e05c74f0 --- /dev/null +++ b/include/grpcpp/impl/codegen/proto_buffer_reader.h @@ -0,0 +1,151 @@ +/* + * + * Copyright 2015 gRPC authors. + * + * Licensed 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. + * + */ + +#ifndef GRPCPP_IMPL_CODEGEN_PROTO_BUFFER_READER_H +#define GRPCPP_IMPL_CODEGEN_PROTO_BUFFER_READER_H + +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +/// This header provides an object that reads bytes directly from a +/// grpc::ByteBuffer, via the ZeroCopyInputStream interface + +namespace grpc { + +extern CoreCodegenInterface* g_core_codegen_interface; + +/// This is a specialization of the protobuf class ZeroCopyInputStream +/// The principle is to get one chunk of data at a time from the proto layer, +/// with options to backup (re-see some bytes) or skip (forward past some bytes) +/// +/// Read more about ZeroCopyInputStream interface here: +/// https://developers.google.com/protocol-buffers/docs/reference/cpp/google.protobuf.io.zero_copy_stream#ZeroCopyInputStream +class GrpcProtoBufferReader : public ::grpc::protobuf::io::ZeroCopyInputStream { + public: + /// Constructs buffer reader from \a buffer. Will set \a status() to non ok + /// if \a buffer is invalid (the internal buffer has not been initialized). + explicit GrpcProtoBufferReader(ByteBuffer* buffer) + : byte_count_(0), backup_count_(0), status_() { + /// Implemented through a grpc_byte_buffer_reader which iterates + /// over the slices that make up a byte buffer + if (!buffer->Valid() || + !g_core_codegen_interface->grpc_byte_buffer_reader_init( + &reader_, buffer->c_buffer())) { + status_ = Status(StatusCode::INTERNAL, + "Couldn't initialize byte buffer reader"); + } + } + + ~GrpcProtoBufferReader() { + if (status_.ok()) { + g_core_codegen_interface->grpc_byte_buffer_reader_destroy(&reader_); + } + } + + /// Give the proto library a chunk of data from the stream. The caller + /// may safely read from data[0, size - 1]. + bool Next(const void** data, int* size) override { + if (!status_.ok()) { + return false; + } + /// If we have backed up previously, we need to return the backed-up slice + if (backup_count_ > 0) { + *data = GRPC_SLICE_START_PTR(slice_) + GRPC_SLICE_LENGTH(slice_) - + backup_count_; + GPR_CODEGEN_ASSERT(backup_count_ <= INT_MAX); + *size = (int)backup_count_; + backup_count_ = 0; + return true; + } + /// Otherwise get the next slice from the byte buffer reader + if (!g_core_codegen_interface->grpc_byte_buffer_reader_next(&reader_, + &slice_)) { + return false; + } + g_core_codegen_interface->grpc_slice_unref(slice_); + *data = GRPC_SLICE_START_PTR(slice_); + // On win x64, int is only 32bit + GPR_CODEGEN_ASSERT(GRPC_SLICE_LENGTH(slice_) <= INT_MAX); + byte_count_ += * size = (int)GRPC_SLICE_LENGTH(slice_); + return true; + } + + /// Returns the status of the buffer reader. + Status status() const { return status_; } + + /// The proto library calls this to indicate that we should back up \a count + /// bytes that have already been returned by the last call of Next. + /// So do the backup and have that ready for a later Next. + void BackUp(int count) override { + GPR_CODEGEN_ASSERT(count <= static_cast(GRPC_SLICE_LENGTH(slice_))); + backup_count_ = count; + } + + /// The proto library calls this to skip over \a count bytes. Implement this + /// using Next and BackUp combined. + bool Skip(int count) override { + const void* data; + int size; + while (Next(&data, &size)) { + if (size >= count) { + BackUp(size - count); + return true; + } + // size < count; + count -= size; + } + // error or we have too large count; + return false; + } + + /// Returns the total number of bytes read since this object was created. + grpc::protobuf::int64 ByteCount() const override { + return byte_count_ - backup_count_; + } + + // These protected members are needed to support internal optimizations. + // they expose internal bits of grpc core that are NOT stable. If you have + // a use case needs to use one of these functions, please send an email to + // https://groups.google.com/forum/#!forum/grpc-io. + protected: + void set_byte_count(int64_t byte_count) { byte_count_ = byte_count; } + int64_t backup_count() { return backup_count_; } + void set_backup_count(int64_t backup_count) { backup_count_ = backup_count; } + grpc_byte_buffer_reader* reader() { return &reader_; } + grpc_slice* slice() { return &slice_; } + + private: + int64_t byte_count_; ///< total bytes read since object creation + int64_t backup_count_; ///< how far backed up in the stream we are + grpc_byte_buffer_reader reader_; ///< internal object to read \a grpc_slice + ///< from the \a grpc_byte_buffer + grpc_slice slice_; ///< current slice passed back to the caller + Status status_; ///< status of the entire object +}; + +} // namespace grpc + +#endif // GRPCPP_IMPL_CODEGEN_PROTO_BUFFER_READER_H diff --git a/include/grpcpp/impl/codegen/proto_buffer_writer.h b/include/grpcpp/impl/codegen/proto_buffer_writer.h new file mode 100644 index 00000000000..faf99800cd3 --- /dev/null +++ b/include/grpcpp/impl/codegen/proto_buffer_writer.h @@ -0,0 +1,168 @@ +/* + * + * Copyright 2018 gRPC authors. + * + * Licensed 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. + * + */ + +#ifndef GRPCPP_IMPL_CODEGEN_PROTO_BUFFER_WRITER_H +#define GRPCPP_IMPL_CODEGEN_PROTO_BUFFER_WRITER_H + +#include + +#include +#include +#include +#include +#include +#include +#include + +/// This header provides an object that writes bytes directly into a +/// grpc::ByteBuffer, via the ZeroCopyOutputStream interface + +namespace grpc { + +extern CoreCodegenInterface* g_core_codegen_interface; + +// Forward declaration for testing use only +namespace internal { +class GrpcProtoBufferWriterPeer; +} // namespace internal + +const int kGrpcProtoBufferWriterMaxBufferLength = 1024 * 1024; + +/// This is a specialization of the protobuf class ZeroCopyOutputStream. +/// The principle is to give the proto layer one buffer of bytes at a time +/// that it can use to serialize the next portion of the message, with the +/// option to "backup" if more buffer is given than required at the last buffer. +/// +/// Read more about ZeroCopyOutputStream interface here: +/// https://developers.google.com/protocol-buffers/docs/reference/cpp/google.protobuf.io.zero_copy_stream#ZeroCopyOutputStream +class GrpcProtoBufferWriter + : public ::grpc::protobuf::io::ZeroCopyOutputStream { + public: + /// Constructor for this derived class + /// + /// \param[out] byte_buffer A pointer to the grpc::ByteBuffer created + /// \param block_size How big are the chunks to allocate at a time + /// \param total_size How many total bytes are required for this proto + GrpcProtoBufferWriter(ByteBuffer* byte_buffer, int block_size, int total_size) + : block_size_(block_size), + total_size_(total_size), + byte_count_(0), + have_backup_(false) { + GPR_CODEGEN_ASSERT(!byte_buffer->Valid()); + /// Create an empty raw byte buffer and look at its underlying slice buffer + grpc_byte_buffer* bp = + g_core_codegen_interface->grpc_raw_byte_buffer_create(NULL, 0); + byte_buffer->set_buffer(bp); + slice_buffer_ = &bp->data.raw.slice_buffer; + } + + ~GrpcProtoBufferWriter() { + if (have_backup_) { + g_core_codegen_interface->grpc_slice_unref(backup_slice_); + } + } + + /// Give the proto library the next buffer of bytes and its size. It is + /// safe for the caller to write from data[0, size - 1]. + bool Next(void** data, int* size) override { + // Protobuf should not ask for more memory than total_size_. + GPR_CODEGEN_ASSERT(byte_count_ < total_size_); + // 1. Use the remaining backup slice if we have one + // 2. Otherwise allocate a slice, up to the remaining length needed + // or our maximum allocation size + // 3. Provide the slice start and size available + // 4. Add the slice being returned to the slice buffer + size_t remain = total_size_ - byte_count_; + if (have_backup_) { + /// If we have a backup slice, we should use it first + slice_ = backup_slice_; + have_backup_ = false; + if (GRPC_SLICE_LENGTH(slice_) > remain) { + GRPC_SLICE_SET_LENGTH(slice_, remain); + } + } else { + // When less than a whole block is needed, only allocate that much. + // But make sure the allocated slice is not inlined. + size_t allocate_length = + remain > static_cast(block_size_) ? block_size_ : remain; + slice_ = g_core_codegen_interface->grpc_slice_malloc( + allocate_length > GRPC_SLICE_INLINED_SIZE + ? allocate_length + : GRPC_SLICE_INLINED_SIZE + 1); + } + *data = GRPC_SLICE_START_PTR(slice_); + // On win x64, int is only 32bit + GPR_CODEGEN_ASSERT(GRPC_SLICE_LENGTH(slice_) <= INT_MAX); + byte_count_ += * size = (int)GRPC_SLICE_LENGTH(slice_); + g_core_codegen_interface->grpc_slice_buffer_add(slice_buffer_, slice_); + return true; + } + + /// Backup by \a count bytes because Next returned more bytes than needed + /// (only used in the last buffer). \a count must be less than or equal too + /// the last buffer returned from next. + void BackUp(int count) override { + /// 1. Remove the partially-used last slice from the slice buffer + /// 2. Split it into the needed (if any) and unneeded part + /// 3. Add the needed part back to the slice buffer + /// 4. Mark that we still have the remaining part (for later use/unref) + GPR_CODEGEN_ASSERT(count <= static_cast(GRPC_SLICE_LENGTH(slice_))); + g_core_codegen_interface->grpc_slice_buffer_pop(slice_buffer_); + if ((size_t)count == GRPC_SLICE_LENGTH(slice_)) { + backup_slice_ = slice_; + } else { + backup_slice_ = g_core_codegen_interface->grpc_slice_split_tail( + &slice_, GRPC_SLICE_LENGTH(slice_) - count); + g_core_codegen_interface->grpc_slice_buffer_add(slice_buffer_, slice_); + } + // It's dangerous to keep an inlined grpc_slice as the backup slice, since + // on a following Next() call, a reference will be returned to this slice + // via GRPC_SLICE_START_PTR, which will not be an address held by + // slice_buffer_. + have_backup_ = backup_slice_.refcount != NULL; + byte_count_ -= count; + } + + /// Returns the total number of bytes written since this object was created. + grpc::protobuf::int64 ByteCount() const override { return byte_count_; } + + // These protected members are needed to support internal optimizations. + // they expose internal bits of grpc core that are NOT stable. If you have + // a use case needs to use one of these functions, please send an email to + // https://groups.google.com/forum/#!forum/grpc-io. + protected: + grpc_slice_buffer* slice_buffer() { return slice_buffer_; } + void set_byte_count(int64_t byte_count) { byte_count_ = byte_count; } + + private: + // friend for testing purposes only + friend class internal::GrpcProtoBufferWriterPeer; + const int block_size_; ///< size to alloc for each new \a grpc_slice needed + const int total_size_; ///< byte size of proto being serialized + int64_t byte_count_; ///< bytes written since this object was created + grpc_slice_buffer* + slice_buffer_; ///< internal buffer of slices holding the serialized data + bool have_backup_; ///< if we are holding a backup slice or not + grpc_slice backup_slice_; ///< holds space we can still write to, if the + ///< caller has called BackUp + grpc_slice slice_; ///< current slice passed back to the caller +}; + +} // namespace grpc + +#endif // GRPCPP_IMPL_CODEGEN_PROTO_BUFFER_WRITER_H diff --git a/include/grpcpp/impl/codegen/proto_utils.h b/include/grpcpp/impl/codegen/proto_utils.h index 81438ee1d52..ec1dccaa748 100644 --- a/include/grpcpp/impl/codegen/proto_utils.h +++ b/include/grpcpp/impl/codegen/proto_utils.h @@ -24,203 +24,62 @@ #include #include #include +#include #include #include +#include +#include #include +#include #include +/// This header provides serialization and deserialization between gRPC +/// messages serialized using protobuf and the C++ objects they represent. + namespace grpc { extern CoreCodegenInterface* g_core_codegen_interface; -namespace internal { - -class GrpcBufferWriterPeer; - -const int kGrpcBufferWriterMaxBufferLength = 1024 * 1024; - -class GrpcBufferWriter : public ::grpc::protobuf::io::ZeroCopyOutputStream { - public: - GrpcBufferWriter(grpc_byte_buffer** bp, int block_size, int total_size) - : block_size_(block_size), - total_size_(total_size), - byte_count_(0), - have_backup_(false) { - *bp = g_core_codegen_interface->grpc_raw_byte_buffer_create(NULL, 0); - slice_buffer_ = &(*bp)->data.raw.slice_buffer; - } - - ~GrpcBufferWriter() override { - if (have_backup_) { - g_core_codegen_interface->grpc_slice_unref(backup_slice_); - } - } - - bool Next(void** data, int* size) override { - // Protobuf should not ask for more memory than total_size_. - GPR_CODEGEN_ASSERT(byte_count_ < total_size_); - size_t remain = total_size_ - byte_count_; - if (have_backup_) { - slice_ = backup_slice_; - have_backup_ = false; - if (GRPC_SLICE_LENGTH(slice_) > remain) { - GRPC_SLICE_SET_LENGTH(slice_, remain); - } - } else { - // When less than a whole block is needed, only allocate that much. - // But make sure the allocated slice is not inlined. - size_t allocate_length = - remain > static_cast(block_size_) ? block_size_ : remain; - slice_ = g_core_codegen_interface->grpc_slice_malloc( - allocate_length > GRPC_SLICE_INLINED_SIZE - ? allocate_length - : GRPC_SLICE_INLINED_SIZE + 1); - } - *data = GRPC_SLICE_START_PTR(slice_); - // On win x64, int is only 32bit - GPR_CODEGEN_ASSERT(GRPC_SLICE_LENGTH(slice_) <= INT_MAX); - byte_count_ += * size = (int)GRPC_SLICE_LENGTH(slice_); - g_core_codegen_interface->grpc_slice_buffer_add(slice_buffer_, slice_); - return true; - } - - void BackUp(int count) override { - g_core_codegen_interface->grpc_slice_buffer_pop(slice_buffer_); - if ((size_t)count == GRPC_SLICE_LENGTH(slice_)) { - backup_slice_ = slice_; - } else { - backup_slice_ = g_core_codegen_interface->grpc_slice_split_tail( - &slice_, GRPC_SLICE_LENGTH(slice_) - count); - g_core_codegen_interface->grpc_slice_buffer_add(slice_buffer_, slice_); - } - // It's dangerous to keep an inlined grpc_slice as the backup slice, since - // on a following Next() call, a reference will be returned to this slice - // via GRPC_SLICE_START_PTR, which will not be an adddress held by - // slice_buffer_. - have_backup_ = backup_slice_.refcount != NULL; - byte_count_ -= count; - } - - grpc::protobuf::int64 ByteCount() const override { return byte_count_; } - - protected: - friend class GrpcBufferWriterPeer; - const int block_size_; - const int total_size_; - int64_t byte_count_; - grpc_slice_buffer* slice_buffer_; - bool have_backup_; - grpc_slice backup_slice_; - grpc_slice slice_; -}; - -class GrpcBufferReader : public ::grpc::protobuf::io::ZeroCopyInputStream { - public: - explicit GrpcBufferReader(grpc_byte_buffer* buffer) - : byte_count_(0), backup_count_(0), status_() { - if (!g_core_codegen_interface->grpc_byte_buffer_reader_init(&reader_, - buffer)) { - status_ = Status(StatusCode::INTERNAL, - "Couldn't initialize byte buffer reader"); - } - } - ~GrpcBufferReader() override { - g_core_codegen_interface->grpc_byte_buffer_reader_destroy(&reader_); - } - - bool Next(const void** data, int* size) override { - if (!status_.ok()) { - return false; - } - if (backup_count_ > 0) { - *data = GRPC_SLICE_START_PTR(slice_) + GRPC_SLICE_LENGTH(slice_) - - backup_count_; - GPR_CODEGEN_ASSERT(backup_count_ <= INT_MAX); - *size = (int)backup_count_; - backup_count_ = 0; - return true; - } - if (!g_core_codegen_interface->grpc_byte_buffer_reader_next(&reader_, - &slice_)) { - return false; - } - g_core_codegen_interface->grpc_slice_unref(slice_); - *data = GRPC_SLICE_START_PTR(slice_); - // On win x64, int is only 32bit - GPR_CODEGEN_ASSERT(GRPC_SLICE_LENGTH(slice_) <= INT_MAX); - byte_count_ += * size = (int)GRPC_SLICE_LENGTH(slice_); - return true; - } - - Status status() const { return status_; } - - void BackUp(int count) override { backup_count_ = count; } - - bool Skip(int count) override { - const void* data; - int size; - while (Next(&data, &size)) { - if (size >= count) { - BackUp(size - count); - return true; - } - // size < count; - count -= size; - } - // error or we have too large count; - return false; - } - - grpc::protobuf::int64 ByteCount() const override { - return byte_count_ - backup_count_; - } - - protected: - int64_t byte_count_; - int64_t backup_count_; - grpc_byte_buffer_reader reader_; - grpc_slice slice_; - Status status_; -}; - -// BufferWriter must be a subclass of io::ZeroCopyOutputStream. -template -Status GenericSerialize(const grpc::protobuf::Message& msg, - grpc_byte_buffer** bp, bool* own_buffer) { - static_assert( - std::is_base_of::value, - "BufferWriter must be a subclass of io::ZeroCopyOutputStream"); +// ProtoBufferWriter must be a subclass of ::protobuf::io::ZeroCopyOutputStream. +template +Status GenericSerialize(const grpc::protobuf::Message& msg, ByteBuffer* bb, + bool* own_buffer) { + static_assert(std::is_base_of::value, + "ProtoBufferWriter must be a subclass of " + "::protobuf::io::ZeroCopyOutputStream"); *own_buffer = true; int byte_size = msg.ByteSize(); if ((size_t)byte_size <= GRPC_SLICE_INLINED_SIZE) { - grpc_slice slice = g_core_codegen_interface->grpc_slice_malloc(byte_size); - GPR_CODEGEN_ASSERT( - GRPC_SLICE_END_PTR(slice) == - msg.SerializeWithCachedSizesToArray(GRPC_SLICE_START_PTR(slice))); - *bp = g_core_codegen_interface->grpc_raw_byte_buffer_create(&slice, 1); - g_core_codegen_interface->grpc_slice_unref(slice); + Slice slice(byte_size); + // We serialize directly into the allocated slices memory + GPR_CODEGEN_ASSERT(slice.end() == msg.SerializeWithCachedSizesToArray( + const_cast(slice.begin()))); + ByteBuffer tmp(&slice, 1); + bb->Swap(&tmp); return g_core_codegen_interface->ok(); } - BufferWriter writer(bp, kGrpcBufferWriterMaxBufferLength, byte_size); + ProtoBufferWriter writer(bb, kGrpcProtoBufferWriterMaxBufferLength, + byte_size); return msg.SerializeToZeroCopyStream(&writer) ? g_core_codegen_interface->ok() : Status(StatusCode::INTERNAL, "Failed to serialize message"); } -// BufferReader must be a subclass of io::ZeroCopyInputStream. -template -Status GenericDeserialize(grpc_byte_buffer* buffer, - grpc::protobuf::Message* msg) { - static_assert( - std::is_base_of::value, - "BufferReader must be a subclass of io::ZeroCopyInputStream"); +// BufferReader must be a subclass of ::protobuf::io::ZeroCopyInputStream. +template +Status GenericDeserialize(ByteBuffer* buffer, grpc::protobuf::Message* msg) { + static_assert(std::is_base_of::value, + "ProtoBufferReader must be a subclass of " + "::protobuf::io::ZeroCopyInputStream"); if (buffer == nullptr) { return Status(StatusCode::INTERNAL, "No payload"); } Status result = g_core_codegen_interface->ok(); { - BufferReader reader(buffer); + ProtoBufferReader reader(buffer); if (!reader.status().ok()) { return reader.status(); } @@ -233,12 +92,10 @@ Status GenericDeserialize(grpc_byte_buffer* buffer, result = Status(StatusCode::INTERNAL, "Did not read entire message"); } } - g_core_codegen_interface->grpc_byte_buffer_destroy(buffer); + buffer->Clear(); return result; } -} // namespace internal - // this is needed so the following class does not conflict with protobuf // serializers that utilize internal-only tools. #ifdef GRPC_OPEN_SOURCE_PROTO @@ -249,16 +106,13 @@ template class SerializationTraits::value>::type> { public: - static Status Serialize(const grpc::protobuf::Message& msg, - grpc_byte_buffer** bp, bool* own_buffer) { - return internal::GenericSerialize( - msg, bp, own_buffer); + static Status Serialize(const grpc::protobuf::Message& msg, ByteBuffer* bb, + bool* own_buffer) { + return GenericSerialize(msg, bb, own_buffer); } - static Status Deserialize(grpc_byte_buffer* buffer, - grpc::protobuf::Message* msg) { - return internal::GenericDeserialize(buffer, - msg); + static Status Deserialize(ByteBuffer* buffer, grpc::protobuf::Message* msg) { + return GenericDeserialize(buffer, msg); } }; #endif diff --git a/include/grpcpp/impl/codegen/slice.h b/include/grpcpp/impl/codegen/slice.h index fcccd4b68e4..8966559dc85 100644 --- a/include/grpcpp/impl/codegen/slice.h +++ b/include/grpcpp/impl/codegen/slice.h @@ -35,34 +35,43 @@ namespace grpc { class Slice final { public: /// Construct an empty slice. - Slice(); + Slice() : slice_(g_core_codegen_interface->grpc_empty_slice()) {} /// Destructor - drops one reference. - ~Slice(); + ~Slice() { g_core_codegen_interface->grpc_slice_unref(slice_); } enum AddRef { ADD_REF }; /// Construct a slice from \a slice, adding a reference. - Slice(grpc_slice slice, AddRef); + Slice(grpc_slice slice, AddRef) + : slice_(g_core_codegen_interface->grpc_slice_ref(slice)) {} enum StealRef { STEAL_REF }; /// Construct a slice from \a slice, stealing a reference. - Slice(grpc_slice slice, StealRef); + Slice(grpc_slice slice, StealRef) : slice_(slice) {} /// Allocate a slice of specified size - Slice(size_t len); + Slice(size_t len) + : slice_(g_core_codegen_interface->grpc_slice_malloc(len)) {} /// Construct a slice from a copied buffer - Slice(const void* buf, size_t len); + Slice(const void* buf, size_t len) + : slice_(g_core_codegen_interface->grpc_slice_from_copied_buffer( + reinterpret_cast(buf), len)) {} /// Construct a slice from a copied string - Slice(const grpc::string& str); + Slice(const grpc::string& str) + : slice_(g_core_codegen_interface->grpc_slice_from_copied_buffer( + str.c_str(), str.length())) {} enum StaticSlice { STATIC_SLICE }; /// Construct a slice from a static buffer - Slice(const void* buf, size_t len, StaticSlice); + Slice(const void* buf, size_t len, StaticSlice) + : slice_(g_core_codegen_interface->grpc_slice_from_static_buffer( + reinterpret_cast(buf), len)) {} /// Copy constructor, adds a reference. - Slice(const Slice& other); + Slice(const Slice& other) + : slice_(g_core_codegen_interface->grpc_slice_ref(other.slice_)) {} /// Assignment, reference count is unchanged. Slice& operator=(Slice other) { @@ -75,14 +84,18 @@ class Slice final { /// user data pointer passed in at destruction. Can be the same as buf or /// different (e.g., if data is part of a larger structure that must be /// destroyed when the data is no longer needed) - Slice(void* buf, size_t len, void (*destroy)(void*), void* user_data); + Slice(void* buf, size_t len, void (*destroy)(void*), void* user_data) + : slice_(g_core_codegen_interface->grpc_slice_new_with_user_data( + buf, len, destroy, user_data)) {} /// Specialization of above for common case where buf == user_data Slice(void* buf, size_t len, void (*destroy)(void*)) : Slice(buf, len, destroy, buf) {} /// Similar to the above but has a destroy that also takes slice length - Slice(void* buf, size_t len, void (*destroy)(void*, size_t)); + Slice(void* buf, size_t len, void (*destroy)(void*, size_t)) + : slice_(g_core_codegen_interface->grpc_slice_new_with_len(buf, len, + destroy)) {} /// Byte size. size_t size() const { return GRPC_SLICE_LENGTH(slice_); } @@ -94,7 +107,9 @@ class Slice final { const uint8_t* end() const { return GRPC_SLICE_END_PTR(slice_); } /// Raw C slice. Caller needs to call grpc_slice_unref when done. - grpc_slice c_slice() const; + grpc_slice c_slice() const { + return g_core_codegen_interface->grpc_slice_ref(slice_); + } private: friend class ByteBuffer; diff --git a/include/grpcpp/support/proto_buffer_reader.h b/include/grpcpp/support/proto_buffer_reader.h new file mode 100644 index 00000000000..4cdb65d531b --- /dev/null +++ b/include/grpcpp/support/proto_buffer_reader.h @@ -0,0 +1,24 @@ +/* + * + * Copyright 2018 gRPC authors. + * + * Licensed 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. + * + */ + +#ifndef GRPCPP_SUPPORT_PROTO_BUFFER_READER_H +#define GRPCPP_SUPPORT_PROTO_BUFFER_READER_H + +#include + +#endif // GRPCPP_SUPPORT_PROTO_BUFFER_READER_H diff --git a/include/grpcpp/support/proto_buffer_writer.h b/include/grpcpp/support/proto_buffer_writer.h new file mode 100644 index 00000000000..01cf29c457e --- /dev/null +++ b/include/grpcpp/support/proto_buffer_writer.h @@ -0,0 +1,24 @@ +/* + * + * Copyright 2018 gRPC authors. + * + * Licensed 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. + * + */ + +#ifndef GRPCPP_SUPPORT_PROTO_BUFFER_WRITER_H +#define GRPCPP_SUPPORT_PROTO_BUFFER_WRITER_H + +#include + +#endif // GRPCPP_SUPPORT_PROTO_BUFFER_WRITER_H diff --git a/src/cpp/common/core_codegen.cc b/src/cpp/common/core_codegen.cc index aa9788da76d..619aacadaa0 100644 --- a/src/cpp/common/core_codegen.cc +++ b/src/cpp/common/core_codegen.cc @@ -98,6 +98,10 @@ void CoreCodegen::grpc_byte_buffer_destroy(grpc_byte_buffer* bb) { ::grpc_byte_buffer_destroy(bb); } +size_t CoreCodegen::grpc_byte_buffer_length(grpc_byte_buffer* bb) { + return ::grpc_byte_buffer_length(bb); +} + grpc_call_error CoreCodegen::grpc_call_cancel_with_status( grpc_call* call, grpc_status_code status, const char* description, void* reserved) { @@ -135,6 +139,12 @@ grpc_slice CoreCodegen::grpc_slice_new_with_user_data(void* p, size_t len, return ::grpc_slice_new_with_user_data(p, len, destroy, user_data); } +grpc_slice CoreCodegen::grpc_slice_new_with_len(void* p, size_t len, + void (*destroy)(void*, + size_t)) { + return ::grpc_slice_new_with_len(p, len, destroy); +} + grpc_slice CoreCodegen::grpc_empty_slice() { return ::grpc_empty_slice(); } grpc_slice CoreCodegen::grpc_slice_malloc(size_t length) { diff --git a/src/cpp/util/byte_buffer_cc.cc b/src/cpp/util/byte_buffer_cc.cc index fbc1768bcc4..d976b694403 100644 --- a/src/cpp/util/byte_buffer_cc.cc +++ b/src/cpp/util/byte_buffer_cc.cc @@ -23,34 +23,6 @@ namespace grpc { -static internal::GrpcLibraryInitializer g_gli_initializer; - -ByteBuffer::ByteBuffer(const Slice* slices, size_t nslices) { - // The following assertions check that the representation of a grpc::Slice is - // identical to that of a grpc_slice: it has a grpc_slice field, and nothing - // else. - static_assert(std::is_same::value, - "Slice must have same representation as grpc_slice"); - static_assert(sizeof(Slice) == sizeof(grpc_slice), - "Slice must have same representation as grpc_slice"); - // The following assertions check that the representation of a ByteBuffer is - // identical to grpc_byte_buffer*: it has a grpc_byte_buffer* field, - // and nothing else. - static_assert(std::is_same::value, - "ByteBuffer must have same representation as " - "grpc_byte_buffer*"); - static_assert(sizeof(ByteBuffer) == sizeof(grpc_byte_buffer*), - "ByteBuffer must have same representation as " - "grpc_byte_buffer*"); - g_gli_initializer.summon(); // Make sure that initializer linked in - // The const_cast is legal if grpc_raw_byte_buffer_create() does no more - // than its advertised side effect of increasing the reference count of the - // slices it processes, and such an increase does not affect the semantics - // seen by the caller of this constructor. - buffer_ = grpc_raw_byte_buffer_create( - reinterpret_cast(const_cast(slices)), nslices); -} - Status ByteBuffer::Dump(std::vector* slices) const { slices->clear(); if (!buffer_) { @@ -69,14 +41,6 @@ Status ByteBuffer::Dump(std::vector* slices) const { return Status::OK; } -size_t ByteBuffer::Length() const { - if (buffer_) { - return grpc_byte_buffer_length(buffer_); - } else { - return 0; - } -} - ByteBuffer::ByteBuffer(const ByteBuffer& buf) : buffer_(grpc_byte_buffer_copy(buf.buffer_)) {} @@ -90,10 +54,4 @@ ByteBuffer& ByteBuffer::operator=(const ByteBuffer& buf) { return *this; } -void ByteBuffer::Swap(ByteBuffer* other) { - grpc_byte_buffer* tmp = other->buffer_; - other->buffer_ = buffer_; - buffer_ = tmp; -} - } // namespace grpc diff --git a/src/cpp/util/slice_cc.cc b/src/cpp/util/slice_cc.cc deleted file mode 100644 index c72dbdbfc03..00000000000 --- a/src/cpp/util/slice_cc.cc +++ /dev/null @@ -1,55 +0,0 @@ -/* - * - * Copyright 2015 gRPC authors. - * - * Licensed 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 -#include - -namespace grpc { - -Slice::Slice() : slice_(grpc_empty_slice()) {} - -Slice::~Slice() { grpc_slice_unref(slice_); } - -Slice::Slice(grpc_slice slice, AddRef) : slice_(grpc_slice_ref(slice)) {} - -Slice::Slice(grpc_slice slice, StealRef) : slice_(slice) {} - -Slice::Slice(size_t len) : slice_(grpc_slice_malloc(len)) {} - -Slice::Slice(const void* buf, size_t len) - : slice_( - grpc_slice_from_copied_buffer(static_cast(buf), len)) {} - -Slice::Slice(const grpc::string& str) - : slice_(grpc_slice_from_copied_buffer(str.c_str(), str.length())) {} - -Slice::Slice(const void* buf, size_t len, StaticSlice) - : slice_( - grpc_slice_from_static_buffer(static_cast(buf), len)) {} - -Slice::Slice(const Slice& other) : slice_(grpc_slice_ref(other.slice_)) {} - -Slice::Slice(void* buf, size_t len, void (*destroy)(void*), void* user_data) - : slice_(grpc_slice_new_with_user_data(buf, len, destroy, user_data)) {} - -Slice::Slice(void* buf, size_t len, void (*destroy)(void*, size_t)) - : slice_(grpc_slice_new_with_len(buf, len, destroy)) {} - -grpc_slice Slice::c_slice() const { return grpc_slice_ref(slice_); } - -} // namespace grpc diff --git a/test/cpp/codegen/proto_utils_test.cc b/test/cpp/codegen/proto_utils_test.cc index 836d3d80768..53e2a2864c2 100644 --- a/test/cpp/codegen/proto_utils_test.cc +++ b/test/cpp/codegen/proto_utils_test.cc @@ -24,32 +24,43 @@ #include namespace grpc { + namespace internal { -// Provide access to GrpcBufferWriter internals. -class GrpcBufferWriterPeer { +// Provide access to GrpcProtoBufferWriter internals. +class GrpcProtoBufferWriterPeer { public: - explicit GrpcBufferWriterPeer(internal::GrpcBufferWriter* writer) + explicit GrpcProtoBufferWriterPeer(GrpcProtoBufferWriter* writer) : writer_(writer) {} bool have_backup() const { return writer_->have_backup_; } const grpc_slice& backup_slice() const { return writer_->backup_slice_; } const grpc_slice& slice() const { return writer_->slice_; } private: - GrpcBufferWriter* writer_; + GrpcProtoBufferWriter* writer_; +}; + +// Provide access to ByteBuffer internals. +class GrpcByteBufferPeer { + public: + explicit GrpcByteBufferPeer(ByteBuffer* bb) : bb_(bb) {} + grpc_byte_buffer* c_buffer() { return bb_->c_buffer(); } + + private: + ByteBuffer* bb_; }; class ProtoUtilsTest : public ::testing::Test {}; // Regression test for a memory corruption bug where a series of -// GrpcBufferWriter Next()/Backup() invocations could result in a dangling +// GrpcProtoBufferWriter Next()/Backup() invocations could result in a dangling // pointer returned by Next() due to the interaction between grpc_slice inlining // and GRPC_SLICE_START_PTR. TEST_F(ProtoUtilsTest, TinyBackupThenNext) { - grpc_byte_buffer* bp; + ByteBuffer bp; const int block_size = 1024; - GrpcBufferWriter writer(&bp, block_size, 8192); - GrpcBufferWriterPeer peer(&writer); + GrpcProtoBufferWriter writer(&bp, block_size, 8192); + GrpcProtoBufferWriterPeer peer(&writer); void* data; int size; @@ -63,17 +74,14 @@ TEST_F(ProtoUtilsTest, TinyBackupThenNext) { ASSERT_TRUE(writer.Next(&data, &size)); EXPECT_TRUE(peer.slice().refcount != nullptr); EXPECT_EQ(block_size, size); - - // Cleanup. - g_core_codegen_interface->grpc_byte_buffer_destroy(bp); } namespace { // Set backup_size to 0 to indicate no backup is needed. void BufferWriterTest(int block_size, int total_size, int backup_size) { - grpc_byte_buffer* bp; - GrpcBufferWriter writer(&bp, block_size, total_size); + ByteBuffer bb; + GrpcProtoBufferWriter writer(&bb, block_size, total_size); int written_size = 0; void* data; @@ -110,10 +118,11 @@ void BufferWriterTest(int block_size, int total_size, int backup_size) { writer.BackUp(backup_size); } } - EXPECT_EQ(grpc_byte_buffer_length(bp), (size_t)total_size); + EXPECT_EQ(bb.Length(), (size_t)total_size); grpc_byte_buffer_reader reader; - grpc_byte_buffer_reader_init(&reader, bp); + GrpcByteBufferPeer peer(&bb); + grpc_byte_buffer_reader_init(&reader, peer.c_buffer()); int read_bytes = 0; while (read_bytes < total_size) { grpc_slice s; @@ -126,7 +135,6 @@ void BufferWriterTest(int block_size, int total_size, int backup_size) { } EXPECT_EQ(read_bytes, total_size); grpc_byte_buffer_reader_destroy(&reader); - grpc_byte_buffer_destroy(bp); } TEST(WriterTest, TinyBlockTinyBackup) { @@ -154,7 +162,7 @@ TEST(WriterTest, LargeBlockLargeBackup) { BufferWriterTest(4096, 8192, 4095); } } // namespace grpc int main(int argc, char** argv) { - // Ensure the GrpcBufferWriter internals are initialized. + // Ensure the GrpcProtoBufferWriter internals are initialized. grpc::internal::GrpcLibraryInitializer init; init.summon(); grpc::GrpcLibraryCodegen lib; diff --git a/test/cpp/util/byte_buffer_test.cc b/test/cpp/util/byte_buffer_test.cc index 605ef15123e..47a5b7f03a2 100644 --- a/test/cpp/util/byte_buffer_test.cc +++ b/test/cpp/util/byte_buffer_test.cc @@ -16,7 +16,8 @@ * */ -#include +#include +#include #include #include @@ -27,6 +28,9 @@ #include namespace grpc { + +static internal::GrpcLibraryInitializer g_gli_initializer; + namespace { const char* kContent1 = "hello xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"; diff --git a/test/cpp/util/slice_test.cc b/test/cpp/util/slice_test.cc index 8e060623605..dc1910038f0 100644 --- a/test/cpp/util/slice_test.cc +++ b/test/cpp/util/slice_test.cc @@ -16,13 +16,17 @@ * */ -#include +#include +#include #include #include #include namespace grpc { + +static internal::GrpcLibraryInitializer g_gli_initializer; + namespace { const char* kContent = "hello xxxxxxxxxxxxxxxxxxxx world"; diff --git a/tools/doxygen/Doxyfile.c++ b/tools/doxygen/Doxyfile.c++ index 047b27ea574..22f225ec549 100644 --- a/tools/doxygen/Doxyfile.c++ +++ b/tools/doxygen/Doxyfile.c++ @@ -954,6 +954,8 @@ include/grpcpp/impl/codegen/create_auth_context.h \ include/grpcpp/impl/codegen/grpc_library.h \ include/grpcpp/impl/codegen/metadata_map.h \ include/grpcpp/impl/codegen/method_handler_impl.h \ +include/grpcpp/impl/codegen/proto_buffer_reader.h \ +include/grpcpp/impl/codegen/proto_buffer_writer.h \ include/grpcpp/impl/codegen/proto_utils.h \ include/grpcpp/impl/codegen/rpc_method.h \ include/grpcpp/impl/codegen/rpc_service_method.h \ @@ -992,6 +994,8 @@ include/grpcpp/support/async_unary_call.h \ include/grpcpp/support/byte_buffer.h \ include/grpcpp/support/channel_arguments.h \ include/grpcpp/support/config.h \ +include/grpcpp/support/proto_buffer_reader.h \ +include/grpcpp/support/proto_buffer_writer.h \ include/grpcpp/support/slice.h \ include/grpcpp/support/status.h \ include/grpcpp/support/status_code_enum.h \ diff --git a/tools/doxygen/Doxyfile.c++.internal b/tools/doxygen/Doxyfile.c++.internal index 3e2c1928640..63d238d741d 100644 --- a/tools/doxygen/Doxyfile.c++.internal +++ b/tools/doxygen/Doxyfile.c++.internal @@ -956,6 +956,8 @@ include/grpcpp/impl/codegen/create_auth_context.h \ include/grpcpp/impl/codegen/grpc_library.h \ include/grpcpp/impl/codegen/metadata_map.h \ include/grpcpp/impl/codegen/method_handler_impl.h \ +include/grpcpp/impl/codegen/proto_buffer_reader.h \ +include/grpcpp/impl/codegen/proto_buffer_writer.h \ include/grpcpp/impl/codegen/proto_utils.h \ include/grpcpp/impl/codegen/rpc_method.h \ include/grpcpp/impl/codegen/rpc_service_method.h \ @@ -994,6 +996,8 @@ include/grpcpp/support/async_unary_call.h \ include/grpcpp/support/byte_buffer.h \ include/grpcpp/support/channel_arguments.h \ include/grpcpp/support/config.h \ +include/grpcpp/support/proto_buffer_reader.h \ +include/grpcpp/support/proto_buffer_writer.h \ include/grpcpp/support/slice.h \ include/grpcpp/support/status.h \ include/grpcpp/support/status_code_enum.h \ @@ -1209,7 +1213,6 @@ src/cpp/server/thread_pool_interface.h \ src/cpp/thread_manager/thread_manager.cc \ src/cpp/thread_manager/thread_manager.h \ src/cpp/util/byte_buffer_cc.cc \ -src/cpp/util/slice_cc.cc \ src/cpp/util/status.cc \ src/cpp/util/string_ref.cc \ src/cpp/util/time_cc.cc \ diff --git a/tools/run_tests/generated/sources_and_headers.json b/tools/run_tests/generated/sources_and_headers.json index c7ea43fb09b..c79996f8188 100644 --- a/tools/run_tests/generated/sources_and_headers.json +++ b/tools/run_tests/generated/sources_and_headers.json @@ -10746,6 +10746,8 @@ ], "headers": [ "include/grpc++/impl/codegen/proto_utils.h", + "include/grpcpp/impl/codegen/proto_buffer_reader.h", + "include/grpcpp/impl/codegen/proto_buffer_writer.h", "include/grpcpp/impl/codegen/proto_utils.h" ], "is_filegroup": true, @@ -10753,6 +10755,8 @@ "name": "grpc++_codegen_proto", "src": [ "include/grpc++/impl/codegen/proto_utils.h", + "include/grpcpp/impl/codegen/proto_buffer_reader.h", + "include/grpcpp/impl/codegen/proto_buffer_writer.h", "include/grpcpp/impl/codegen/proto_utils.h" ], "third_party": false, @@ -10851,6 +10855,8 @@ "include/grpcpp/support/byte_buffer.h", "include/grpcpp/support/channel_arguments.h", "include/grpcpp/support/config.h", + "include/grpcpp/support/proto_buffer_reader.h", + "include/grpcpp/support/proto_buffer_writer.h", "include/grpcpp/support/slice.h", "include/grpcpp/support/status.h", "include/grpcpp/support/status_code_enum.h", @@ -10953,6 +10959,8 @@ "include/grpcpp/support/byte_buffer.h", "include/grpcpp/support/channel_arguments.h", "include/grpcpp/support/config.h", + "include/grpcpp/support/proto_buffer_reader.h", + "include/grpcpp/support/proto_buffer_writer.h", "include/grpcpp/support/slice.h", "include/grpcpp/support/status.h", "include/grpcpp/support/status_code_enum.h", @@ -10997,7 +11005,6 @@ "src/cpp/thread_manager/thread_manager.cc", "src/cpp/thread_manager/thread_manager.h", "src/cpp/util/byte_buffer_cc.cc", - "src/cpp/util/slice_cc.cc", "src/cpp/util/status.cc", "src/cpp/util/string_ref.cc", "src/cpp/util/time_cc.cc"