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 "log_store_ex.h"
16 
17 #include <fstream>
18 #include <functional>
19 #include <string>
20 #include <vector>
21 
22 #include <fcntl.h>
23 #include <sys/stat.h>
24 #include <sys/types.h>
25 
26 #include "file_util.h"
27 #include "log_file.h"
28 #include "hiview_logger.h"
29 
30 namespace OHOS {
31 namespace HiviewDFX {
32 DEFINE_LOG_TAG("HiView-LogStoreEx");
33 constexpr int32_t DEFAULT_LOGSTORE_SIZE = 1024 * 1024 * 10;
34 constexpr int32_t DEFAULT_LOGSTORE_MIN_KEEP_FILE_COUNT = 100;
35 constexpr mode_t DEFAULT_LOG_FILE_MODE = 0664;
36 constexpr mode_t DEFAULT_LOG_DIR_MODE = 0770;
LogStoreEx(const std::string & path,bool autoDeleteFiles)37 LogStoreEx::LogStoreEx(const std::string& path, bool autoDeleteFiles)
38     : autoDeleteFiles_(autoDeleteFiles),
39       maxSize_(DEFAULT_LOGSTORE_SIZE),
40       minKeepingNumberOfFiles_(DEFAULT_LOGSTORE_MIN_KEEP_FILE_COUNT),
41       comparator_(nullptr),
42       path_(path)
43 {}
44 
Init()45 bool LogStoreEx::Init()
46 {
47     if (!FileUtil::FileExists(path_)) {
48         FileUtil::ForceCreateDirectory(path_);
49         FileUtil::ChangeModeDirectory(path_, DEFAULT_LOG_DIR_MODE);
50     }
51     return true;
52 }
53 
SetLogFileComparator(LogFileComparator comparator)54 void LogStoreEx::SetLogFileComparator(LogFileComparator comparator)
55 {
56     comparator_ = comparator;
57 }
58 
SetMaxSize(uint32_t size)59 void LogStoreEx::SetMaxSize(uint32_t size)
60 {
61     maxSize_ = size;
62 }
63 
SetMinKeepingFileNumber(uint32_t number)64 void LogStoreEx::SetMinKeepingFileNumber(uint32_t number)
65 {
66     minKeepingNumberOfFiles_ = number;
67 }
68 
GetPath() const69 const std::string& LogStoreEx::GetPath() const
70 {
71     return path_;
72 }
73 
GetLogFiles()74 std::vector<LogFile> LogStoreEx::GetLogFiles()
75 {
76     std::vector<std::string> fileVec;
77     std::vector<LogFile> logFileList;
78     FileUtil::GetDirFiles(path_, fileVec);
79     for (auto& filePath : fileVec) {
80         logFileList.push_back(LogFile(filePath));
81     }
82 
83     if (comparator_ != nullptr) {
84         std::sort(logFileList.begin(), logFileList.end(), comparator_);
85     } else {
86         std::sort(logFileList.begin(), logFileList.end());
87     }
88     return logFileList;
89 }
90 
GetLogFiles(LogFileFilter filter)91 std::vector<LogFile> LogStoreEx::GetLogFiles(LogFileFilter filter)
92 {
93     auto logFileList = GetLogFiles();
94     auto iter = logFileList.begin();
95     while (iter != logFileList.end()) {
96         if (!filter(*iter)) {
97             iter = logFileList.erase(iter);
98             continue;
99         }
100         iter++;
101     }
102     return logFileList;
103 }
104 
Clear()105 bool LogStoreEx::Clear()
106 {
107     if (!FileUtil::ForceRemoveDirectory(path_)) {
108         return false;
109     }
110     return Init();
111 }
112 
DoDeleteLogFiles(const std::vector<LogFile> & fileList,int32_t removeFileNums) const113 void LogStoreEx::DoDeleteLogFiles(const std::vector<LogFile> &fileList, int32_t removeFileNums) const
114 {
115     int32_t deleteCount = 0;
116     for (auto it = fileList.rbegin(); it != fileList.rend(); ++it) {
117         if (deleteCount >= removeFileNums) {
118             break;
119         }
120 
121         FileUtil::RemoveFile(it->path_);
122         HIVIEW_LOGI("Remove file:%{public}s.", it->path_.c_str());
123         deleteCount++;
124     }
125     HIVIEW_LOGI("Remove %d Files.", deleteCount);
126 }
127 
ClearOldestFilesIfNeeded()128 void LogStoreEx::ClearOldestFilesIfNeeded()
129 {
130     auto size = FileUtil::GetFolderSize(path_);
131     if (size < maxSize_) {
132         return;
133     }
134 
135     auto fileList = GetLogFiles();
136     int32_t removeFileNumber = fileList.size() - minKeepingNumberOfFiles_;
137     if (removeFileNumber < 0) {
138         removeFileNumber = fileList.size() / 2; // 2 : remove half of the total
139     }
140     DoDeleteLogFiles(fileList, removeFileNumber);
141 }
142 
ClearSameLogFilesIfNeeded(LogFileFilter filter,uint32_t maxCount)143 void LogStoreEx::ClearSameLogFilesIfNeeded(LogFileFilter filter, uint32_t maxCount)
144 {
145     auto fileList = GetLogFiles(filter);
146     uint32_t removeFileNumber = 0;
147     if (fileList.size() > maxCount) {
148         removeFileNumber = fileList.size() - maxCount;
149     }
150     DoDeleteLogFiles(fileList, removeFileNumber);
151 }
152 
CreateLogFile(const std::string & name)153 LogStoreEx::FileHandle LogStoreEx::CreateLogFile(const std::string& name)
154 {
155     if (autoDeleteFiles_) {
156         ClearOldestFilesIfNeeded();
157     }
158 
159     auto path = path_ + "/" + name;
160     auto fd = open(path.c_str(), O_CREAT | O_WRONLY | O_TRUNC, DEFAULT_LOG_FILE_MODE);
161     if (fd < 0) {
162         HIVIEW_LOGI("Fail to create %s.", name.c_str());
163     }
164     return fd;
165 }
166 
RemoveLogFile(const std::string & name)167 bool LogStoreEx::RemoveLogFile(const std::string& name)
168 {
169     auto path = path_ + "/" + name;
170     std::string realPath;
171     if (!FileUtil::PathToRealPath(path, realPath)) {
172         return false;
173     }
174     return FileUtil::RemoveFile(path);
175 }
176 } // namespace HiviewDFX
177 } // namespace OHOS