• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 "dfs_error.h"
24 #include "meta_file.h"
25 #include "hisysevent.h"
26 #include "utils_log.h"
27 
28 namespace OHOS {
29 namespace FileManagement {
30 namespace CloudFile {
31 using namespace std;
32 
33 #define FILE_SIZE_BYTE_TO_KB 1024
34 #define FILE_SIZE_KB_TO_MB 1024
35 #define STAT_TIME_MS_TO_S 1000
36 #define CLOUD_FILE_DIR_MOD 0770
37 #define CLOUD_FILE_MOD 0660
38 #define CLOUD_SYNC_SYS_EVENT(eventName, type, ...)    \
39     HiSysEventWrite(HiviewDFX::HiSysEvent::Domain::FILEMANAGEMENT, eventName,    \
40                     type, ##__VA_ARGS__)    \
41 
42 static const string STAT_DATA_DIR_NAME = "/data/service/el1/public/cloudfile/cloud_data_statistic";
43 static const string STAT_DATA_FILE_NAME = "cloud_sync_read_file_stat";
44 static const vector<uint64_t> OPEN_SIZE_RANGE_VECTOR = { 256, 512, 1 * FILE_SIZE_KB_TO_MB, 2 * FILE_SIZE_KB_TO_MB,
45     4 * FILE_SIZE_KB_TO_MB, 6 * FILE_SIZE_KB_TO_MB, 8 * FILE_SIZE_KB_TO_MB, 15 * FILE_SIZE_KB_TO_MB };
46 static const vector<uint64_t> OPEN_TIME_RANGE_VECTOR = { 250, 500, 1000, 1500, 2000, 5000 };
47 static const vector<uint64_t> READ_SIZE_RANGE_VECTOR = { 128, 256, 512, 1 * FILE_SIZE_KB_TO_MB, 2 * FILE_SIZE_KB_TO_MB,
48     4 * FILE_SIZE_KB_TO_MB };
49 static const vector<uint64_t> READ_TIME_RANGE_VECTOR = { 300, 600, 900, 1200, 1500, 2000, 3000, 5000, 8000 };
50 
GetRangeIndex(uint64_t value,const vector<uint64_t> rangeVector)51 static uint32_t GetRangeIndex(uint64_t value, const vector<uint64_t> rangeVector)
52 {
53     uint32_t index = 0;
54     for (; index < rangeVector.size(); index++) {
55         if (value <= rangeVector[index]) {
56             break;
57         }
58     }
59     return index;
60 }
61 
CheckOverflow(uint64_t & data,uint64_t addValue)62 static void CheckOverflow(uint64_t &data, uint64_t addValue)
63 {
64     if (data >= UINT64_MAX - addValue) {
65         LOGE("update fail, overflow, data = %{public}llu, addValue = %{public}llu",
66             static_cast<unsigned long long>(data),
67             static_cast<unsigned long long>(addValue));
68         data = 0;
69     } else {
70         data += addValue;
71     }
72 }
73 
CheckOverflow(uint32_t & data,uint32_t addValue)74 static void CheckOverflow(uint32_t &data, uint32_t addValue)
75 {
76     if (data > UINT32_MAX - addValue) {
77         LOGE("update fail, overflow, data = %{public}d, addValue = %{public}d",
78             data, addValue);
79         data = UINT32_MAX;
80     } else {
81         data += addValue;
82     }
83 }
84 
UpdateOpenSizeStat(uint64_t size)85 void CloudDaemonStatistic::UpdateOpenSizeStat(uint64_t size)
86 {
87     uint32_t index = GetRangeIndex(size / FILE_SIZE_BYTE_TO_KB, OPEN_SIZE_RANGE_VECTOR);
88     if (index >= OPEN_SIZE_MAX) {
89         LOGE("update open size stat fail, index overflow, index = %{public}u.", index);
90         return;
91     }
92     CheckOverflow(openSizeStat_[index], 1);
93 }
94 
UpdateOpenTimeStat(uint32_t type,uint64_t time)95 void CloudDaemonStatistic::UpdateOpenTimeStat(uint32_t type, uint64_t time)
96 {
97     uint32_t index = GetRangeIndex(time, OPEN_TIME_RANGE_VECTOR);
98     if (index >= OPEN_TIME_MAX) {
99         LOGE("update open time stat fail, index overflow, index = %{public}u.", index);
100         return;
101     }
102     CheckOverflow(openTimeStat_[type][index], 1);
103 }
104 
UpdateReadSizeStat(uint64_t size)105 void CloudDaemonStatistic::UpdateReadSizeStat(uint64_t size)
106 {
107     uint32_t index = GetRangeIndex(size / FILE_SIZE_BYTE_TO_KB, READ_SIZE_RANGE_VECTOR);
108     if (index >= READ_SIZE_MAX) {
109         LOGE("update read size stat fail, index overflow, index = %{public}u.", index);
110         return;
111     }
112     CheckOverflow(readSizeStat_[index], 1);
113 }
114 
UpdateReadTimeStat(uint64_t size,uint64_t time)115 void CloudDaemonStatistic::UpdateReadTimeStat(uint64_t size, uint64_t time)
116 {
117     uint32_t indexSize = GetRangeIndex(size / FILE_SIZE_BYTE_TO_KB, READ_SIZE_RANGE_VECTOR);
118     uint32_t indexTime = GetRangeIndex(time, READ_TIME_RANGE_VECTOR);
119     if (indexSize >= READ_SIZE_MAX || indexTime >= READ_TIME_MAX) {
120         LOGE("update read time stat fail, index overflow, indexSize = %{public}u, indexTime = %{public}u.",
121             indexSize, indexTime);
122         return;
123     }
124     CheckOverflow(readTimeStat_[indexSize][indexTime], 1);
125 }
126 
UpdateReadInfo(uint32_t index)127 void CloudDaemonStatistic::UpdateReadInfo(uint32_t index)
128 {
129     if (index >= VIDEO_READ_INFO) {
130         return;
131     }
132     CheckOverflow(videoReadInfo_[index], 1);
133 }
134 
UpdateBundleName(const std::string & bundleName)135 void CloudDaemonStatistic::UpdateBundleName(const std::string &bundleName)
136 {
137     bundleName_ = bundleName;
138 }
139 
AddFileData(CloudDaemonStatisticInfo & info)140 void CloudDaemonStatistic::AddFileData(CloudDaemonStatisticInfo &info)
141 {
142     /* file not exist means first time, no former data, normal case */
143     auto ret = access(STAT_DATA_DIR_NAME.c_str(), F_OK);
144     if (ret != 0) {
145         LOGI("dir cloud_data_statistic not exist, ret = %{public}d.", ret);
146         return;
147     }
148     std::ifstream statDataFile(STAT_DATA_DIR_NAME + "/" + STAT_DATA_FILE_NAME);
149     if (!statDataFile) {
150         LOGI("file cloud_sync_read_file_stat not exist.");
151         return;
152     }
153 
154     for (uint32_t i = 0; i < OPEN_SIZE_MAX; i++) {
155         statDataFile >> info.openSizeStat[i];
156     }
157     for (uint32_t i = 0; i < FILE_TYPE_MAX; i++) {
158         for (uint32_t j = 0; j < OPEN_TIME_MAX; j++) {
159             statDataFile >> info.openTimeStat[i][j];
160         }
161     }
162     for (uint32_t i = 0; i < READ_SIZE_MAX; i++) {
163         statDataFile >> info.readSizeStat[i];
164     }
165     for (uint32_t i = 0; i < READ_SIZE_MAX; i++) {
166         for (uint32_t j = 0; j < READ_TIME_MAX; j++) {
167             statDataFile >> info.readTimeStat[i][j];
168         }
169     }
170     for (uint32_t i = 0; i < VIDEO_READ_INFO; i++) {
171         statDataFile >> info.videoReadInfo[i];
172     }
173     statDataFile >> info.bundleName;
174     statDataFile.close();
175 }
176 
CheckFileStat()177 int32_t CloudDaemonStatistic::CheckFileStat()
178 {
179     if (access(STAT_DATA_DIR_NAME.c_str(), F_OK) != 0) {
180         auto ret = mkdir(STAT_DATA_DIR_NAME.c_str(), CLOUD_FILE_DIR_MOD);
181         if (ret != 0) {
182             LOGE("mkdir cloud_data_statistic fail, ret = %{public}d.", ret);
183             return ret;
184         }
185     }
186     string statFilePath = STAT_DATA_DIR_NAME + "/" + STAT_DATA_FILE_NAME;
187     if (access(statFilePath.c_str(), F_OK) != 0) {
188         auto fd = creat(statFilePath.c_str(), CLOUD_FILE_MOD);
189         if (fd < 0) {
190             LOGE("create file cloud_sync_read_file_stat fail.");
191             return E_NO_SUCH_FILE;
192         }
193         close(fd);
194     }
195     return E_OK;
196 }
197 
OutputToFile()198 void CloudDaemonStatistic::OutputToFile()
199 {
200     string tmpStr = "";
201 
202     int32_t ret = CheckFileStat();
203     if (ret != E_OK) {
204         return;
205     }
206     string statFilePath = STAT_DATA_DIR_NAME + "/" + STAT_DATA_FILE_NAME;
207     std::ofstream statDataFile(statFilePath);
208     if (!statDataFile) {
209         LOGE("open out stream file cloud_sync_read_file_stat fail.");
210         return;
211     }
212     for (uint32_t i = 0; i < OPEN_SIZE_MAX; i++) {
213         tmpStr += (to_string(openSizeStat_[i]) + " ");
214     }
215     statDataFile << tmpStr << endl << endl;
216     tmpStr = "";
217     for (uint32_t i = 0; i < FILE_TYPE_MAX; i++) {
218         for (uint32_t j = 0; j < OPEN_TIME_MAX; j++) {
219             tmpStr += (to_string(openTimeStat_[i][j]) + " ");
220         }
221         tmpStr += "\n";
222     }
223     statDataFile << tmpStr << endl;
224     tmpStr = "";
225     for (uint32_t i = 0; i < READ_SIZE_MAX; i++) {
226         tmpStr += (to_string(readSizeStat_[i]) + " ");
227     }
228     statDataFile << tmpStr << endl << endl;
229     tmpStr = "";
230     for (uint32_t i = 0; i < READ_SIZE_MAX; i++) {
231         for (uint32_t j = 0; j < READ_TIME_MAX; j++) {
232             tmpStr += (to_string(readTimeStat_[i][j]) + " ");
233         }
234         tmpStr += "\n";
235     }
236     statDataFile << tmpStr << endl;
237     tmpStr = "";
238     for (uint32_t i = 0; i < VIDEO_READ_INFO; i++) {
239         tmpStr += (to_string(videoReadInfo_[i]) + " ");
240     }
241     statDataFile << tmpStr << endl;
242     statDataFile << bundleName_ << endl;
243     statDataFile.close();
244 }
245 
ClearStat()246 void CloudDaemonStatistic::ClearStat()
247 {
248     for (uint32_t i = 0; i < OPEN_SIZE_MAX; i++) {
249         openSizeStat_[i] = 0;
250     }
251     for (uint32_t i = 0; i < FILE_TYPE_MAX; i++) {
252         for (uint32_t j = 0; j < OPEN_TIME_MAX; j++) {
253             openTimeStat_[i][j] = 0;
254         }
255     }
256     for (uint32_t i = 0; i < READ_SIZE_MAX; i++) {
257         readSizeStat_[i] = 0;
258     }
259     for (uint32_t i = 0; i < READ_SIZE_MAX; i++) {
260         for (uint32_t j = 0; j < READ_TIME_MAX; j++) {
261             readTimeStat_[i][j] = 0;
262         }
263     }
264     for (uint32_t i = 0; i < VIDEO_READ_INFO; i++) {
265         videoReadInfo_[i] = 0;
266     }
267 }
268 
SumTwoReadStat(const CloudDaemonStatisticInfo & info)269 void CloudDaemonStatistic::SumTwoReadStat(const CloudDaemonStatisticInfo &info)
270 {
271     for (uint32_t i = 0; i < OPEN_SIZE_MAX; i++) {
272         CheckOverflow(openSizeStat_[i], info.openSizeStat[i]);
273     }
274     for (uint32_t i = 0; i < FILE_TYPE_MAX; i++) {
275         for (uint32_t j = 0; j < OPEN_TIME_MAX; j++) {
276             CheckOverflow(openTimeStat_[i][j], info.openTimeStat[i][j]);
277         }
278     }
279     for (uint32_t i = 0; i < READ_SIZE_MAX; i++) {
280         CheckOverflow(readSizeStat_[i], info.readSizeStat[i]);
281     }
282     for (uint32_t i = 0; i < READ_SIZE_MAX; i++) {
283         for (uint32_t j = 0; j < READ_TIME_MAX; j++) {
284             CheckOverflow(readTimeStat_[i][j], info.readTimeStat[i][j]);
285         }
286     }
287     for (uint32_t i = 0; i < VIDEO_READ_INFO; i++) {
288         CheckOverflow(videoReadInfo_[i], info.videoReadInfo[i]);
289     }
290 }
291 
ReportReadStat(const CloudDaemonStatisticInfo & info)292 int32_t CloudDaemonStatistic::ReportReadStat(const CloudDaemonStatisticInfo &info)
293 {
294     int32_t ret = CLOUD_SYNC_SYS_EVENT("CLOUD_SYNC_READ_FILE_STAT",
295         HiviewDFX::HiSysEvent::EventType::STATISTIC,
296         "open_size", info.openSizeStat,
297         "open_thm_time", info.openTimeStat[FILE_TYPE_THUMBNAIL],
298         "open_lcd_time", info.openTimeStat[FILE_TYPE_LCD],
299         "open_content_time", info.openTimeStat[FILE_TYPE_CONTENT],
300         "read_size", info.readSizeStat,
301         "read_time_128KB", info.readTimeStat[READ_SIZE_128K],
302         "read_time_256KB", info.readTimeStat[READ_SIZE_256K],
303         "read_time_512KB", info.readTimeStat[READ_SIZE_512K],
304         "read_time_1M", info.readTimeStat[READ_SIZE_1M],
305         "read_time_2M", info.readTimeStat[READ_SIZE_2M],
306         "read_time_4M", info.readTimeStat[READ_SIZE_4M],
307         "video_read_info", info.videoReadInfo,
308         "bundle_name", info.bundleName
309     );
310     return ret;
311 }
312 
HandleBundleName(const CloudDaemonStatisticInfo & info)313 void CloudDaemonStatistic::HandleBundleName(const CloudDaemonStatisticInfo &info)
314 {
315     if (!info.bundleName.empty() && info.bundleName != bundleName_) {
316         auto ret = ReportReadStat(info);
317         if (ret != E_OK) {
318             LOGE("report CLOUD_SYNC_READ_FILE_STAT error %{public}d", ret);
319         }
320     } else {
321         SumTwoReadStat(info);
322     }
323 }
324 
UpdateStatData()325 void CloudDaemonStatistic::UpdateStatData()
326 {
327     lock_guard<mutex> lock(mutex_);
328     CloudDaemonStatisticInfo info;
329     AddFileData(info);
330     HandleBundleName(info);
331     OutputToFile();
332     ClearStat();
333 }
334 
GetInstance()335 CloudDaemonStatistic &CloudDaemonStatistic::GetInstance()
336 {
337     static CloudDaemonStatistic instance_;
338     return instance_;
339 }
340 
341 } // namespace CloudFile
342 } // namespace FileManagement
343 } // namespace OHOS