1 /*
2 * Copyright (c) 2024 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 "cloud_daemon_statistic.h"
17
18 #include <fcntl.h>
19 #include <fstream>
20 #include <sys/stat.h>
21 #include <unistd.h>
22
23 #include "utils_log.h"
24
25 namespace OHOS {
26 namespace FileManagement {
27 namespace CloudFile {
28 using namespace std;
29
30 #define FILE_SIZE_BYTE_TO_KB 1024
31 #define FILE_SIZE_KB_TO_MB 1024
32 #define STAT_TIME_MS_TO_S 1000
33 #define CLOUD_FILE_DIR_MOD 0770
34 #define CLOUD_FILE_MOD 0660
35
36 static const string STAT_DATA_DIR_NAME = "/data/service/el1/public/cloudfile/cloud_data_statistic";
37 static const string STAT_DATA_FILE_NAME = "cloud_sync_read_file_stat";
38 static const vector<uint64_t> OPEN_SIZE_RANGE_VECTOR = { 256, 512, 1 * FILE_SIZE_KB_TO_MB, 2 * FILE_SIZE_KB_TO_MB,
39 4 * FILE_SIZE_KB_TO_MB, 6 * FILE_SIZE_KB_TO_MB, 8 * FILE_SIZE_KB_TO_MB, 15 * FILE_SIZE_KB_TO_MB };
40 static const vector<uint64_t> OPEN_TIME_RANGE_VECTOR = { 250, 500, 1000, 1500, 2000, 5000 };
41 static const vector<uint64_t> READ_SIZE_RANGE_VECTOR = { 128, 256, 512, 1 * FILE_SIZE_KB_TO_MB, 2 * FILE_SIZE_KB_TO_MB,
42 4 * FILE_SIZE_KB_TO_MB };
43 static const vector<uint64_t> READ_TIME_RANGE_VECTOR = { 300, 600, 900, 1200, 1500, 2000, 3000, 5000, 8000 };
44
GetRangeIndex(uint64_t value,const vector<uint64_t> rangeVector)45 static uint32_t GetRangeIndex(uint64_t value, const vector<uint64_t> rangeVector)
46 {
47 uint32_t index = 0;
48 for (; index < rangeVector.size(); index++) {
49 if (value <= rangeVector[index]) {
50 break;
51 }
52 }
53 return index;
54 }
55
CheckOverflow(uint64_t & data,uint64_t addValue)56 static void CheckOverflow(uint64_t &data, uint64_t addValue)
57 {
58 if (data >= UINT64_MAX - addValue) {
59 LOGE("update fail, overflow, data = %{public}llu, addValue = %{public}llu",
60 static_cast<unsigned long long>(data),
61 static_cast<unsigned long long>(addValue));
62 data = 0;
63 } else {
64 data += addValue;
65 }
66 }
67
UpdateOpenSizeStat(uint64_t size)68 void CloudDaemonStatistic::UpdateOpenSizeStat(uint64_t size)
69 {
70 uint32_t index = GetRangeIndex(size / FILE_SIZE_BYTE_TO_KB, OPEN_SIZE_RANGE_VECTOR);
71 if (index >= OPEN_SIZE_MAX) {
72 LOGE("update open size stat fail, index overflow, index = %{public}u.", index);
73 return;
74 }
75 CheckOverflow(openSizeStat_[index], 1);
76 }
77
UpdateOpenTimeStat(uint32_t type,uint64_t time)78 void CloudDaemonStatistic::UpdateOpenTimeStat(uint32_t type, uint64_t time)
79 {
80 uint32_t index = GetRangeIndex(time, OPEN_TIME_RANGE_VECTOR);
81 if (index >= OPEN_TIME_MAX) {
82 LOGE("update open time stat fail, index overflow, index = %{public}u.", index);
83 return;
84 }
85 CheckOverflow(openTimeStat_[type][index], 1);
86 }
87
UpdateReadSizeStat(uint64_t size)88 void CloudDaemonStatistic::UpdateReadSizeStat(uint64_t size)
89 {
90 uint32_t index = GetRangeIndex(size / FILE_SIZE_BYTE_TO_KB, READ_SIZE_RANGE_VECTOR);
91 if (index >= READ_SIZE_MAX) {
92 LOGE("update read size stat fail, index overflow, index = %{public}u.", index);
93 return;
94 }
95 CheckOverflow(readSizeStat_[index], 1);
96 }
97
UpdateReadTimeStat(uint64_t size,uint64_t time)98 void CloudDaemonStatistic::UpdateReadTimeStat(uint64_t size, uint64_t time)
99 {
100 uint32_t indexSize = GetRangeIndex(size / FILE_SIZE_BYTE_TO_KB, READ_SIZE_RANGE_VECTOR);
101 uint32_t indexTime = GetRangeIndex(time, READ_TIME_RANGE_VECTOR);
102 if (indexSize >= READ_SIZE_MAX || indexTime >= READ_TIME_MAX) {
103 LOGE("update read time stat fail, index overflow, indexSize = %{public}u, indexTime = %{public}u.",
104 indexSize, indexTime);
105 return;
106 }
107 CheckOverflow(readTimeStat_[indexSize][indexTime], 1);
108 }
109
AddFileData()110 void CloudDaemonStatistic::AddFileData()
111 {
112 /* file not exist means first time, no former data, normal case */
113 auto ret = access(STAT_DATA_DIR_NAME.c_str(), F_OK);
114 if (ret != 0) {
115 LOGI("dir cloud_data_statistic not exist, ret = %{public}d.", ret);
116 return;
117 }
118 std::ifstream statDataFile(STAT_DATA_DIR_NAME + "/" + STAT_DATA_FILE_NAME);
119 if (!statDataFile) {
120 LOGI("file cloud_sync_read_file_stat not exist.");
121 return;
122 }
123
124 uint64_t tmpData;
125 for (uint32_t i = 0; i < OPEN_SIZE_MAX; i++) {
126 statDataFile >> tmpData;
127 CheckOverflow(openSizeStat_[i], tmpData);
128 }
129 for (uint32_t i = 0; i < FILE_TYPE_MAX; i++) {
130 for (uint32_t j = 0; j < OPEN_TIME_MAX; j++) {
131 statDataFile >> tmpData;
132 CheckOverflow(openTimeStat_[i][j], tmpData);
133 }
134 }
135 for (uint32_t i = 0; i < READ_SIZE_MAX; i++) {
136 statDataFile >> tmpData;
137 CheckOverflow(readSizeStat_[i], tmpData);
138 }
139 for (uint32_t i = 0; i < READ_SIZE_MAX; i++) {
140 for (uint32_t j = 0; j < READ_TIME_MAX; j++) {
141 statDataFile >> tmpData;
142 CheckOverflow(readTimeStat_[i][j], tmpData);
143 }
144 }
145 statDataFile.close();
146 }
147
OutputToFile()148 void CloudDaemonStatistic::OutputToFile()
149 {
150 string tmpStr = "";
151
152 if (access(STAT_DATA_DIR_NAME.c_str(), F_OK) != 0) {
153 auto ret = mkdir(STAT_DATA_DIR_NAME.c_str(), CLOUD_FILE_DIR_MOD);
154 if (ret != 0) {
155 LOGE("mkdir cloud_data_statistic fail, ret = %{public}d.", ret);
156 return;
157 }
158 }
159 string statFilePath = STAT_DATA_DIR_NAME + "/" + STAT_DATA_FILE_NAME;
160 if (access(statFilePath.c_str(), F_OK) != 0) {
161 auto fd = creat(statFilePath.c_str(), CLOUD_FILE_MOD);
162 if (fd < 0) {
163 LOGE("create file cloud_sync_read_file_stat fail.");
164 return;
165 }
166 close(fd);
167 }
168
169 std::ofstream statDataFile(statFilePath);
170 if (!statDataFile) {
171 LOGE("open out stream file cloud_sync_read_file_stat fail.");
172 return;
173 }
174
175 for (uint32_t i = 0; i < OPEN_SIZE_MAX; i++) {
176 tmpStr += (to_string(openSizeStat_[i]) + " ");
177 }
178 statDataFile << tmpStr << endl << endl;
179 tmpStr = "";
180
181 for (uint32_t i = 0; i < FILE_TYPE_MAX; i++) {
182 for (uint32_t j = 0; j < OPEN_TIME_MAX; j++) {
183 tmpStr += (to_string(openTimeStat_[i][j]) + " ");
184 }
185 tmpStr += "\n";
186 }
187 statDataFile << tmpStr << endl;
188 tmpStr = "";
189
190 for (uint32_t i = 0; i < READ_SIZE_MAX; i++) {
191 tmpStr += (to_string(readSizeStat_[i]) + " ");
192 }
193 statDataFile << tmpStr << endl << endl;
194 tmpStr = "";
195
196 for (uint32_t i = 0; i < READ_SIZE_MAX; i++) {
197 for (uint32_t j = 0; j < READ_TIME_MAX; j++) {
198 tmpStr += (to_string(readTimeStat_[i][j]) + " ");
199 }
200 tmpStr += "\n";
201 }
202 statDataFile << tmpStr << endl;
203 statDataFile.close();
204 }
205
ClearStat()206 void CloudDaemonStatistic::ClearStat()
207 {
208 for (uint32_t i = 0; i < OPEN_SIZE_MAX; i++) {
209 openSizeStat_[i] = 0;
210 }
211 for (uint32_t i = 0; i < FILE_TYPE_MAX; i++) {
212 for (uint32_t j = 0; j < OPEN_TIME_MAX; j++) {
213 openTimeStat_[i][j] = 0;
214 }
215 }
216 for (uint32_t i = 0; i < READ_SIZE_MAX; i++) {
217 readSizeStat_[i] = 0;
218 }
219 for (uint32_t i = 0; i < READ_SIZE_MAX; i++) {
220 for (uint32_t j = 0; j < READ_TIME_MAX; j++) {
221 readTimeStat_[i][j] = 0;
222 }
223 }
224 }
225
UpdateStatData()226 void CloudDaemonStatistic::UpdateStatData()
227 {
228 lock_guard<mutex> lock(mutex_);
229 AddFileData();
230 OutputToFile();
231 ClearStat();
232 }
233
GetInstance()234 CloudDaemonStatistic &CloudDaemonStatistic::GetInstance()
235 {
236 static CloudDaemonStatistic instance_;
237 return instance_;
238 }
239
240 } // namespace CloudFile
241 } // namespace FileManagement
242 } // namespace OHOS