1 /*
2 * Copyright (c) 2021 Huawei Device Co., Ltd.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15 #include "trace_file_writer.h"
16
17 #include <cinttypes>
18 #include <memory>
19
20 #include "logging.h"
21
22 using CharPtr = std::unique_ptr<char>::pointer;
23 using ConstCharPtr = std::unique_ptr<const char>::pointer;
24
TraceFileWriter(const std::string & path)25 TraceFileWriter::TraceFileWriter(const std::string& path) : path_(path), writeBytes_(0)
26 {
27 Open(path);
28 }
29
~TraceFileWriter()30 TraceFileWriter::~TraceFileWriter()
31 {
32 Flush();
33 if (stream_.is_open()) {
34 stream_.close();
35 }
36 }
37
Path() const38 std::string TraceFileWriter::Path() const
39 {
40 return path_;
41 }
42
Open(const std::string & path)43 bool TraceFileWriter::Open(const std::string& path)
44 {
45 stream_.open(path, std::ios_base::out | std::ios_base::binary);
46 CHECK_TRUE(stream_.is_open(), false, "open %s failed, %d!", path.c_str(), errno);
47
48 // write initial header, makes file write position move forward
49 stream_.write(reinterpret_cast<CharPtr>(&header_), sizeof(header_));
50 CHECK_TRUE(stream_, 0, "write initial header to %s failed!", path_.c_str());
51 path_ = path;
52 return true;
53 }
54
Write(const void * data,size_t size)55 long TraceFileWriter::Write(const void* data, size_t size)
56 {
57 uint32_t dataLen = size;
58 CHECK_TRUE(stream_.is_open(), 0, "binary file %s not open or open failed!", path_.c_str());
59
60 // write 4B data length.
61 stream_.write(reinterpret_cast<CharPtr>(&dataLen), sizeof(dataLen));
62 CHECK_TRUE(stream_, 0, "binary file %s write raw buffer size failed!", path_.c_str());
63 CHECK_TRUE(helper_.AddSegment(reinterpret_cast<uint8_t*>(&size), sizeof(size)),
64 0, "Add payload for size %u FAILED!", dataLen);
65
66 // write data bytes
67 stream_.write(reinterpret_cast<ConstCharPtr>(data), size);
68 CHECK_TRUE(stream_, 0, "binary file %s write raw buffer data failed!", path_.c_str());
69 CHECK_TRUE(helper_.AddSegment(reinterpret_cast<uint8_t*>(const_cast<void*>(data)), size),
70 0, "Add payload for data bytes %zu FAILED!", size);
71
72 long nbytes = sizeof(dataLen) + size;
73 writeBytes_ += nbytes;
74 ++writeCount_;
75 return nbytes;
76 }
77
Write(const MessageLite & message)78 long TraceFileWriter::Write(const MessageLite& message)
79 {
80 // serialize message to bytes array
81 std::vector<char> msgData(message.ByteSizeLong());
82 CHECK_TRUE(message.SerializeToArray(msgData.data(), msgData.size()), 0, "SerializeToArray failed!");
83
84 return Write(msgData.data(), msgData.size());
85 }
86
Finish()87 bool TraceFileWriter::Finish()
88 {
89 // update header info
90 helper_.Update(header_);
91
92 // move write position to begin of file
93 stream_.seekp(0);
94 CHECK_TRUE(stream_, 0, "seek write position to head for %s failed!", path_.c_str());
95
96 // write final header
97 stream_.write(reinterpret_cast<CharPtr>(&header_), sizeof(header_));
98 CHECK_TRUE(stream_, 0, "write final header to %s failed!", path_.c_str());
99 return true;
100 }
101
Flush()102 bool TraceFileWriter::Flush()
103 {
104 CHECK_TRUE(stream_.is_open(), false, "binary file %s not open or open failed!", path_.c_str());
105 CHECK_TRUE(stream_.flush(), false, "binary file %s flush failed!", path_.c_str());
106 HILOG_INFO(LOG_CORE, "flush: %s, bytes: %" PRIu64 ", count: %" PRIu64, path_.c_str(), writeBytes_, writeCount_);
107 return true;
108 }
109