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 
UpdateOpenSizeStat(uint64_t size)56 void CloudDaemonStatistic::UpdateOpenSizeStat(uint64_t size)
57 {
58     uint32_t index = GetRangeIndex(size / FILE_SIZE_BYTE_TO_KB, OPEN_SIZE_RANGE_VECTOR);
59     if (index >= OPEN_SIZE_MAX) {
60         LOGE("update open size stat fail, index overflow, index = %{public}u.", index);
61         return;
62     }
63     openSizeStat_[index]++;
64 }
65 
UpdateOpenTimeStat(uint32_t type,uint64_t time)66 void CloudDaemonStatistic::UpdateOpenTimeStat(uint32_t type, uint64_t time)
67 {
68     uint32_t index = GetRangeIndex(time, OPEN_TIME_RANGE_VECTOR);
69     if (index >= OPEN_TIME_MAX) {
70         LOGE("update open time stat fail, index overflow, index = %{public}u.", index);
71         return;
72     }
73     openTimeStat_[type][index]++;
74 }
75 
UpdateReadSizeStat(uint64_t size)76 void CloudDaemonStatistic::UpdateReadSizeStat(uint64_t size)
77 {
78     uint32_t index = GetRangeIndex(size / FILE_SIZE_BYTE_TO_KB, READ_SIZE_RANGE_VECTOR);
79     if (index >= READ_SIZE_MAX) {
80         LOGE("update read size stat fail, index overflow, index = %{public}u.", index);
81         return;
82     }
83     readSizeStat_[index]++;
84 }
85 
UpdateReadTimeStat(uint64_t size,uint64_t time)86 void CloudDaemonStatistic::UpdateReadTimeStat(uint64_t size, uint64_t time)
87 {
88     uint32_t indexSize = GetRangeIndex(size / FILE_SIZE_BYTE_TO_KB, READ_SIZE_RANGE_VECTOR);
89     uint32_t indexTime = GetRangeIndex(time, READ_TIME_RANGE_VECTOR);
90     if (indexSize >= READ_SIZE_MAX || indexTime >= READ_TIME_MAX) {
91         LOGE("update read time stat fail, index overflow, indexSize = %{public}u, indexTime = %{public}u.",
92             indexSize, indexTime);
93         return;
94     }
95     readTimeStat_[indexSize][indexTime]++;
96 }
97 
AddFileData()98 void CloudDaemonStatistic::AddFileData()
99 {
100     /* file not exist means first time, no former data, normal case */
101     auto ret = access(STAT_DATA_DIR_NAME.c_str(), F_OK);
102     if (ret != 0) {
103         LOGI("dir cloud_data_statistic not exist, ret = %{public}d.", ret);
104         return;
105     }
106     std::ifstream statDataFile(STAT_DATA_DIR_NAME + "/" + STAT_DATA_FILE_NAME);
107     if (!statDataFile) {
108         LOGI("file cloud_sync_read_file_stat not exist.");
109         return;
110     }
111 
112     uint64_t tmpData;
113     for (uint32_t i = 0; i < OPEN_SIZE_MAX; i++) {
114         statDataFile >> tmpData;
115         openSizeStat_[i] += tmpData;
116     }
117     for (uint32_t i = 0; i < FILE_TYPE_MAX; i++) {
118         for (uint32_t j = 0; j < OPEN_TIME_MAX; j++) {
119             statDataFile >> tmpData;
120             openTimeStat_[i][j] += tmpData;
121         }
122     }
123     for (uint32_t i = 0; i < READ_SIZE_MAX; i++) {
124         statDataFile >> tmpData;
125         readSizeStat_[i] += tmpData;
126     }
127     for (uint32_t i = 0; i < READ_SIZE_MAX; i++) {
128         for (uint32_t j = 0; j < READ_TIME_MAX; j++) {
129             statDataFile >> tmpData;
130             readTimeStat_[i][j] += tmpData;
131         }
132     }
133     statDataFile.close();
134 }
135 
OutputToFile()136 void CloudDaemonStatistic::OutputToFile()
137 {
138     string tmpStr = "";
139 
140     if (access(STAT_DATA_DIR_NAME.c_str(), F_OK) != 0) {
141         auto ret = mkdir(STAT_DATA_DIR_NAME.c_str(), CLOUD_FILE_DIR_MOD);
142         if (ret != 0) {
143             LOGE("mkdir cloud_data_statistic fail, ret = %{public}d.", ret);
144             return;
145         }
146     }
147     string statFilePath = STAT_DATA_DIR_NAME + "/" + STAT_DATA_FILE_NAME;
148     if (access(statFilePath.c_str(), F_OK) != 0) {
149         auto fd = creat(statFilePath.c_str(), CLOUD_FILE_MOD);
150         if (fd < 0) {
151             LOGE("create file cloud_sync_read_file_stat fail.");
152             return;
153         }
154         close(fd);
155     }
156 
157     std::ofstream statDataFile(statFilePath);
158     if (!statDataFile) {
159         LOGE("open out stream file cloud_sync_read_file_stat fail.");
160         return;
161     }
162 
163     for (uint32_t i = 0; i < OPEN_SIZE_MAX; i++) {
164         tmpStr += (to_string(openSizeStat_[i]) + " ");
165     }
166     statDataFile << tmpStr << endl << endl;
167     tmpStr = "";
168 
169     for (uint32_t i = 0; i < FILE_TYPE_MAX; i++) {
170         for (uint32_t j = 0; j < OPEN_TIME_MAX; j++) {
171             tmpStr += (to_string(openTimeStat_[i][j]) + " ");
172         }
173         tmpStr += "\n";
174     }
175     statDataFile << tmpStr << endl;
176     tmpStr = "";
177 
178     for (uint32_t i = 0; i < READ_SIZE_MAX; i++) {
179         tmpStr += (to_string(readSizeStat_[i]) + " ");
180     }
181     statDataFile << tmpStr << endl << endl;
182     tmpStr = "";
183 
184     for (uint32_t i = 0; i < READ_SIZE_MAX; i++) {
185         for (uint32_t j = 0; j < READ_TIME_MAX; j++) {
186             tmpStr += (to_string(readTimeStat_[i][j]) + " ");
187         }
188         tmpStr += "\n";
189     }
190     statDataFile << tmpStr << endl;
191     statDataFile.close();
192 }
193 
ClearStat()194 void CloudDaemonStatistic::ClearStat()
195 {
196     for (uint32_t i = 0; i < OPEN_SIZE_MAX; i++) {
197         openSizeStat_[i] = 0;
198     }
199     for (uint32_t i = 0; i < FILE_TYPE_MAX; i++) {
200         for (uint32_t j = 0; j < OPEN_TIME_MAX; j++) {
201             openTimeStat_[i][j] = 0;
202         }
203     }
204     for (uint32_t i = 0; i < READ_SIZE_MAX; i++) {
205         readSizeStat_[i] = 0;
206     }
207     for (uint32_t i = 0; i < READ_SIZE_MAX; i++) {
208         for (uint32_t j = 0; j < READ_TIME_MAX; j++) {
209             readTimeStat_[i][j] = 0;
210         }
211     }
212 }
213 
UpdateStatData()214 void CloudDaemonStatistic::UpdateStatData()
215 {
216     AddFileData();
217     OutputToFile();
218     ClearStat();
219 }
220 
GetInstance()221 CloudDaemonStatistic &CloudDaemonStatistic::GetInstance()
222 {
223     static CloudDaemonStatistic instance_;
224     return instance_;
225 }
226 
227 } // namespace CloudFile
228 } // namespace FileManagement
229 } // namespace OHOS