diff options
Diffstat (limited to 'src/serialize/protobuf_io.cc')
-rw-r--r-- | src/serialize/protobuf_io.cc | 173 |
1 files changed, 0 insertions, 173 deletions
diff --git a/src/serialize/protobuf_io.cc b/src/serialize/protobuf_io.cc deleted file mode 100644 index 1b6420f..0000000 --- a/src/serialize/protobuf_io.cc +++ /dev/null @@ -1,173 +0,0 @@ -// Copyright (C) 2017 The Android Open Source Project -// -// 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 "protobuf_io.h" - -#include "common/trace.h" -#include "serialize/arena_ptr.h" - -#include <android-base/chrono_utils.h> -#include <android-base/logging.h> -#include <android-base/unique_fd.h> -#include <fcntl.h> -#include <sys/mman.h> -#include <sys/stat.h> -#include <sys/types.h> -#include <unistd.h> -#include <utils/Trace.h> - -#include "google/protobuf/io/zero_copy_stream_impl_lite.h" -#include "system/iorap/src/serialize/TraceFile.pb.h" - -namespace iorap { -namespace serialize { - -ArenaPtr<proto::TraceFile> ProtobufIO::Open(std::string file_path) { - // TODO: file a bug about this. - // Note: can't use {} here, clang think it's narrowing from long->int. - android::base::unique_fd fd(TEMP_FAILURE_RETRY(::open(file_path.c_str(), O_RDONLY))); - if (fd.get() < 0) { - PLOG(DEBUG) << "ProtobufIO: open failed: " << file_path; - return nullptr; - } - - return Open(fd.get(), file_path.c_str()); -} - -ArenaPtr<proto::TraceFile> ProtobufIO::Open(int fd, const char* file_path) { - - ScopedFormatTrace atrace_protobuf_io_open(ATRACE_TAG_ACTIVITY_MANAGER, - "ProtobufIO::Open %s", - file_path); - android::base::Timer timer{}; - - struct stat buf; - if (fstat(fd, /*out*/&buf) < 0) { - PLOG(ERROR) << "ProtobufIO: open error, fstat failed: " << file_path; - return nullptr; - } - // XX: off64_t for stat::st_size ? - - // Using the mmap appears to be the only way to do zero-copy with protobuf lite. - void* data = mmap(/*addr*/nullptr, - buf.st_size, - PROT_READ, MAP_SHARED | MAP_POPULATE, - fd, - /*offset*/0); - if (data == nullptr) { - PLOG(ERROR) << "ProtobufIO: open error, mmap failed: " << file_path; - return nullptr; - } - - ArenaPtr<proto::TraceFile> protobuf_trace_file = ArenaPtr<proto::TraceFile>::Make(); - if (protobuf_trace_file == nullptr) { - LOG(ERROR) << "ProtobufIO: open error, failed to create arena: " << file_path; - return nullptr; - } - - google::protobuf::io::ArrayInputStream protobuf_input_stream{data, static_cast<int>(buf.st_size)}; - if (!protobuf_trace_file->ParseFromZeroCopyStream(/*in*/&protobuf_input_stream)) { - // XX: Does protobuf on android already have the right LogHandler ? - LOG(ERROR) << "ProtobufIO: open error, protobuf parsing failed: " << file_path; - return nullptr; - } - - if (munmap(data, buf.st_size) < 0) { - PLOG(WARNING) << "ProtobufIO: open problem, munmap failed, possibly memory leak? " - << file_path; - } - - LOG(VERBOSE) << "ProtobufIO: open succeeded: " << file_path << ", duration: " << timer; - return protobuf_trace_file; -} - -iorap::expected<size_t /*bytes written*/, int /*errno*/> ProtobufIO::WriteFully( - const ::google::protobuf::MessageLite& message, - std::string_view file_path) { - - std::string str{file_path}; - android::base::unique_fd fd(TEMP_FAILURE_RETRY( - ::open(str.c_str(), - O_CREAT | O_TRUNC | O_RDWR, - S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP))); // ugo: rw-rw---- - if (fd.get() < 0) { - int err = errno; - PLOG(ERROR) << "ProtobufIO: open failed: " << file_path; - return unexpected{err}; - } - - return WriteFully(message, fd.get(), file_path); -} - -iorap::expected<size_t /*bytes written*/, int /*errno*/> ProtobufIO::WriteFully( - const ::google::protobuf::MessageLite& message, - int fd, - std::string_view file_path) { - - int byte_size = message.ByteSize(); - if (byte_size < 0) { - DCHECK(false) << "Invalid protobuf size: " << byte_size; - LOG(ERROR) << "ProtobufIO: Invalid protobuf size: " << byte_size; - return unexpected{EDOM}; - } - size_t serialized_size = static_cast<size_t>(byte_size); - - // Change the file to be exactly the length of the protobuf. - if (ftruncate(fd, static_cast<off_t>(serialized_size)) < 0) { - int err = errno; - PLOG(ERROR) << "ProtobufIO: ftruncate (size=" << serialized_size << ") failed"; - return unexpected{err}; - } - - // Using the mmap appears to be the only way to do zero-copy with protobuf lite. - void* data = mmap(/*addr*/nullptr, - serialized_size, - PROT_WRITE, - MAP_SHARED, - fd, - /*offset*/0); - if (data == nullptr) { - int err = errno; - PLOG(ERROR) << "ProtobufIO: mmap failed: " << file_path; - return unexpected{err}; - } - - // Zero-copy write from protobuf to file via memory-map. - ::google::protobuf::io::ArrayOutputStream output_stream{data, byte_size}; - if (!message.SerializeToZeroCopyStream(/*inout*/&output_stream)) { - // This should never happen since we pre-allocated the file and memory map to be large - // enough to store the full protobuf. - DCHECK(false) << "ProtobufIO:: SerializeToZeroCopyStream failed despite precalculating size"; - LOG(ERROR) << "ProtobufIO: SerializeToZeroCopyStream failed"; - return unexpected{EXFULL}; - } - - // Guarantee that changes are written back prior to munmap. - if (msync(data, static_cast<size_t>(serialized_size), MS_SYNC) < 0) { - int err = errno; - PLOG(ERROR) << "ProtobufIO: msync failed"; - return unexpected{err}; - } - - if (munmap(data, serialized_size) < 0) { - PLOG(WARNING) << "ProtobufIO: munmap failed, possibly memory leak? " - << file_path; - } - - return serialized_size; -} - -} // namespace serialize -} // namespace iorap - |