• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2023 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 
16 #include "avcodec_log_dump.h"
17 #include <fstream>
18 #include <unistd.h>
19 #include <malloc.h>
20 #include <sys/time.h>
21 #include "securec.h"
22 #include "avcodec_log.h"
23 
24 namespace {
25 constexpr int32_t FILE_MAX = 100;
26 constexpr int32_t FILE_LINE_MAX = 50000;
27 constexpr ::OHOS::HiviewDFX::HiLogLabel LABEL = {LOG_CORE, LOG_DOMAIN, "AVCodecLogDump"};
28 }
29 
30 namespace OHOS {
31 namespace MediaAVCodec {
GetInstance()32 AVCodecLogDump &AVCodecLogDump::GetInstance()
33 {
34     static AVCodecLogDump avcodecLogDump;
35     return avcodecLogDump;
36 }
37 
AVCodecLogDump()38 AVCodecLogDump::AVCodecLogDump()
39 {
40     CHECK_AND_RETURN_LOG(thread_ == nullptr, "TaskProcessor is existed");
41     thread_ = std::make_unique<std::thread>(&AVCodecLogDump::TaskProcessor, this);
42 }
43 
~AVCodecLogDump()44 AVCodecLogDump::~AVCodecLogDump()
45 {
46     {
47         std::unique_lock<std::mutex> lock(mutex_);
48         isExit_ = true;
49         cond_.notify_all();
50     }
51     if (thread_ != nullptr && thread_->joinable()) {
52         thread_->join();
53     }
54 }
55 
AddNewLog(std::string & logStr)56 static void AddNewLog(std::string &logStr)
57 {
58     struct timeval time = {};
59     (void)gettimeofday(&time, nullptr);
60     int64_t second = time.tv_sec % 60;
61     int64_t allMinute = time.tv_sec / 60;
62     int64_t minute = allMinute % 60;
63     int64_t hour = allMinute / 60 % 24;
64     int64_t mSecond = time.tv_usec / 1000;
65 
66     logStr += std::to_string(hour);
67     logStr += ":";
68     logStr += std::to_string(minute);
69     logStr += ":";
70     logStr += std::to_string(second);
71     logStr += ":";
72     logStr += std::to_string(mSecond);
73     logStr += " ";
74     logStr += " pid:";
75     logStr += std::to_string(getpid());
76     logStr += " tid:";
77     logStr += std::to_string(gettid());
78     logStr += " ";
79 }
80 
SaveLog(const char * fmt,...)81 void AVCodecLogDump::SaveLog(const char *fmt, ...)
82 {
83     std::unique_lock<std::mutex> lock(mutex_);
84     if (!isEnable_) {
85         return;
86     }
87     std::string temp = "";
88     std::string fmtStr = fmt;
89     int32_t srcPos = 0;
90     auto dtsPos = fmtStr.find("{public}", srcPos);
91     const int32_t pubLen = 8;
92     while (dtsPos != std::string::npos) {
93         temp += fmtStr.substr(srcPos, dtsPos - srcPos);
94         srcPos = static_cast<int32_t>(dtsPos) + pubLen;
95         dtsPos = fmtStr.find("{public}", srcPos);
96     }
97     temp += fmtStr.substr(srcPos);
98 
99     va_list ap;
100     va_start(ap, fmt);
101     constexpr uint8_t maxLogLen = 255;
102     char logBuf[maxLogLen];
103     auto ret = vsnprintf_s(logBuf, maxLogLen, maxLogLen - 1, temp.c_str(), ap);
104     va_end(ap);
105 
106     AddNewLog(logString_);
107     if (ret < 0) {
108         logString_ += "dump log error";
109     } else {
110         logString_ += logBuf;
111     }
112     logString_ += "\n";
113     lineCount_++;
114     if (lineCount_ >= FILE_LINE_MAX) {
115         cond_.notify_all();
116     }
117 }
118 
UpdateCheckEnable()119 void AVCodecLogDump::UpdateCheckEnable()
120 {
121     std::string file = "/data/media/log/check.config";
122     std::ofstream ofStream(file);
123     if (!ofStream.is_open()) {
124         isEnable_ = false;
125         return;
126     }
127     ofStream.close();
128     isEnable_ = true;
129 }
130 
TaskProcessor()131 void AVCodecLogDump::TaskProcessor()
132 {
133     pthread_setname_np(pthread_self(), "AVCodecLogDumpTask");
134     (void)mallopt(M_SET_THREAD_CACHE, M_THREAD_CACHE_DISABLE);
135     (void)mallopt(M_DELAYED_FREE, M_DELAYED_FREE_DISABLE);
136     while (true) {
137         std::string temp;
138         int32_t lineCount = 0;
139         {
140             std::unique_lock<std::mutex> lock(mutex_);
141             if (isExit_) {
142                 return;
143             }
144             static constexpr int32_t timeout = 60; // every 1 minute have a log
145             cond_.wait_for(lock, std::chrono::seconds(timeout),
146                 [this] {
147                     UpdateCheckEnable();
148                     return isExit_ || isDump_ || lineCount_ >= FILE_LINE_MAX || !logString_.empty();
149             });
150             isDump_ = false;
151             lineCount = lineCount_;
152             lineCount_ = lineCount_ >= FILE_LINE_MAX ? 0 : lineCount_;
153             swap(logString_, temp);
154         }
155 
156         std::string file = "/data/media/avcodec/log/";
157         file += std::to_string(getpid());
158         file += "dump_log_avcodec.log";
159         file += std::to_string(fileCount_);
160         std::ofstream ofStream;
161         if (isNewFile_) {
162             ofStream.open(file, std::ios::out | std::ios::trunc);
163         } else {
164             ofStream.open(file, std::ios::out | std::ios::app);
165         }
166         if (!ofStream.is_open()) {
167             continue;
168         }
169         isNewFile_ = false;
170         if (lineCount >= FILE_LINE_MAX) {
171             isNewFile_ = true;
172             fileCount_++;
173             fileCount_ = fileCount_ > FILE_MAX ? 0 : fileCount_;
174         }
175         ofStream.write(temp.c_str(), temp.size());
176         ofStream.close();
177     }
178 }
179 } // namespace MediaAVCodec
180 } // namespace OHOS