1 /*
2 * Copyright (c) 2025 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 "utils/storage_statistics_radar.h"
17
18 #include "storage_service_log.h"
19 #include "unique_fd.h"
20 #include <fcntl.h>
21 #include <fstream>
22 #include <iostream>
23 #include <sstream>
24 #include <sys/types.h>
25 #include <unistd.h>
26
27 #include "cJSON.h"
28
29 namespace OHOS {
30 namespace StorageDaemon {
31 namespace {
32 const std::string PATH_STORAGE_RADAR = "/data/service/el1/public/storage_daemon/radar/";
33 const std::string STATISTIC_FILE_NAME = "StorageStatisticFile.json";
34 const uint32_t OP_COUNT = 12;
35 const uint32_t KEY_LOAD_SUCC_COUNT = 0;
36 const uint32_t KEY_LOAD_FAIL_COUNT = 1;
37 const uint32_t KEY_UNLOAD_SUCC_COUNT = 2;
38 const uint32_t KEY_UNLOAD_FAIL_COUNT = 3;
39 const uint32_t USER_ADD_SUCC_COUNT = 4;
40 const uint32_t USER_ADD_FAIL_COUNT = 5;
41 const uint32_t USER_REMOVE_SUCC_COUNT = 6;
42 const uint32_t USER_REMOVE_FAIL_COUNT = 7;
43 const uint32_t USER_START_SUCC_COUNT = 8;
44 const uint32_t USER_START_FAIL_COUNT = 9;
45 const uint32_t USER_STOP_SUCC_COUNT = 10;
46 const uint32_t USER_STOP_FAIL_COUNT = 11;
47 }
48
CreateStatisticFile()49 bool StorageStatisticRadar::CreateStatisticFile()
50 {
51 std::string filePath = PATH_STORAGE_RADAR + STATISTIC_FILE_NAME;
52 if (access(filePath.c_str(), F_OK) == 0) {
53 LOGI("File exist filePath:%{public}s", filePath.c_str());
54 return true;
55 }
56 LOGI("Failed to access filePath :%{public}s", filePath.c_str());
57 UniqueFd fd(open(filePath.c_str(), O_RDWR | O_CREAT, S_IRUSR | S_IWUSR));
58 if (fd < 0) {
59 LOGE("Failed to creat filePath :%{public}s", filePath.c_str());
60 return false;
61 }
62 return true;
63 }
64
CleanStatisticFile()65 void StorageStatisticRadar::CleanStatisticFile()
66 {
67 std::string filePath = PATH_STORAGE_RADAR + STATISTIC_FILE_NAME;
68 std::ofstream outFile(filePath, std::ios::trunc);
69 if (!outFile.is_open()) {
70 LOGE("Open statistic file failed");
71 return;
72 }
73 outFile.close();
74 LOGI("Clean statistic file ok, filePath :%{public}s", filePath.c_str());
75 }
76
GetCountInfoString(const RadarStatisticInfo & info)77 std::string StorageStatisticRadar::GetCountInfoString(const RadarStatisticInfo &info)
78 {
79 std::string opCountStr = std::to_string(info.keyLoadSuccCount) + ',' +
80 std::to_string(info.keyLoadFailCount) + ',' +
81 std::to_string(info.keyUnloadSuccCount) + ',' +
82 std::to_string(info.keyUnloadFailCount) + ',' +
83 std::to_string(info.userAddSuccCount) + ',' +
84 std::to_string(info.userAddFailCount) + ',' +
85 std::to_string(info.userRemoveSuccCount) + ',' +
86 std::to_string(info.userRemoveFailCount) + ',' +
87 std::to_string(info.userStartSuccCount) + ',' +
88 std::to_string(info.userStartFailCount) + ',' +
89 std::to_string(info.userStopSuccCount) + ',' +
90 std::to_string(info.userStopFailCount);
91 return opCountStr;
92 }
93
CreateJsonString(const std::map<uint32_t,RadarStatisticInfo> & statistics)94 std::string StorageStatisticRadar::CreateJsonString(const std::map<uint32_t, RadarStatisticInfo> &statistics)
95 {
96 // create statistic json string
97 cJSON *jsonStorageObject = cJSON_CreateObject();
98 if (jsonStorageObject == nullptr) {
99 LOGE("Creat json failed.");
100 return "";
101 }
102 cJSON *jsonArray = cJSON_CreateArray();
103 if (jsonArray == nullptr) {
104 LOGE("Creat json failed.");
105 cJSON_Delete(jsonStorageObject);
106 return "";
107 }
108 cJSON_AddItemToObject(jsonStorageObject, "storageStatisticFile", jsonArray);
109
110 for (const auto &info : statistics) {
111 cJSON *newItem = cJSON_CreateObject();
112 if (newItem == nullptr) {
113 LOGE("Create json item failed.");
114 cJSON_Delete(jsonStorageObject);
115 return "";
116 }
117 cJSON_AddNumberToObject(newItem, "userId", info.first);
118 std::string oprateCountStr = GetCountInfoString(info.second);
119 cJSON_AddStringToObject(newItem, "oprateCount", oprateCountStr.c_str());
120 cJSON_AddItemToArray(jsonArray, newItem);
121 }
122 char *jsonStr = cJSON_Print(jsonStorageObject);
123 if (jsonStr == nullptr) {
124 LOGE("JSON Print failed");
125 cJSON_Delete(jsonStorageObject);
126 return "";
127 }
128 cJSON_Delete(jsonStorageObject);
129 std::string statisticJsonStr(jsonStr);
130 free(jsonStr);
131 return statisticJsonStr;
132 }
133
UpdateStatisticFile(const std::map<uint32_t,RadarStatisticInfo> & statistics)134 bool StorageStatisticRadar::UpdateStatisticFile(const std::map<uint32_t, RadarStatisticInfo> &statistics)
135 {
136 if (statistics.empty()) {
137 LOGI("Statistics is empty");
138 return false;
139 }
140 std::string filePath = PATH_STORAGE_RADAR + STATISTIC_FILE_NAME;
141 std::ofstream outFile(filePath, std::ios::trunc);
142 if (!outFile.is_open()) {
143 LOGE("Open statistic file failed");
144 return false;
145 }
146 std::string statisticJsonStr = CreateJsonString(statistics);
147 // write StorageStatisticFile.json
148 outFile << statisticJsonStr;
149 outFile.close();
150 LOGI("Storage update radar statistic is %{public}s.", statisticJsonStr.c_str());
151 return true;
152 }
153
ReadStatisticFile(std::map<uint32_t,RadarStatisticInfo> & statistics)154 bool StorageStatisticRadar::ReadStatisticFile(std::map<uint32_t, RadarStatisticInfo> &statistics)
155 {
156 std::string filePath = PATH_STORAGE_RADAR + STATISTIC_FILE_NAME;
157 std::ifstream inFile(filePath);
158 if (!inFile.is_open()) {
159 LOGE("Open json failed");
160 return false;
161 }
162 std::string jsonString((std::istreambuf_iterator<char>(inFile)), std::istreambuf_iterator<char>());
163 inFile.close();
164 if (jsonString.length() == 0) {
165 LOGI("Statistic file is empty.");
166 return true;
167 }
168 LOGI("Storage read radar statistic is %{public}s.", jsonString.c_str());
169
170 cJSON *jsonStorageObject = cJSON_Parse(jsonString.c_str());
171 if (jsonStorageObject == nullptr) {
172 LOGE("Parse json failed");
173 return false;
174 }
175
176 cJSON *statisticArray = cJSON_GetObjectItem(jsonStorageObject, "storageStatisticFile");
177 if (statisticArray == nullptr || !cJSON_IsArray(statisticArray)) {
178 LOGE("Parse json failed");
179 cJSON_Delete(jsonStorageObject);
180 return false;
181 }
182 uint32_t userId = 0;
183 std::string operateCountStr;
184 for (int i = 0; i < cJSON_GetArraySize(statisticArray); ++i) {
185 cJSON *item = cJSON_GetArrayItem(statisticArray, i);
186 if (item == nullptr) {
187 LOGE("Get json item failed");
188 cJSON_Delete(jsonStorageObject);
189 return false;
190 }
191 cJSON *userIdItem = cJSON_GetObjectItem(item, "userId");
192 if (userIdItem != nullptr && cJSON_IsNumber(userIdItem)) {
193 userId = userIdItem->valueint;
194 }
195 cJSON *countItem = cJSON_GetObjectItem(item, "oprateCount");
196 if (countItem != nullptr && cJSON_IsString(countItem)) {
197 operateCountStr = countItem->valuestring;
198 }
199 // update statistics
200 ParseJsonInfo(userId, operateCountStr, statistics);
201 }
202 cJSON_Delete(jsonStorageObject);
203 return true;
204 }
205
ParseJsonInfo(uint32_t userId,const std::string & countInfo,std::map<uint32_t,RadarStatisticInfo> & statistics)206 bool StorageStatisticRadar::ParseJsonInfo(uint32_t userId, const std::string &countInfo,
207 std::map<uint32_t, RadarStatisticInfo> &statistics)
208 {
209 std::stringstream iss(countInfo);
210 std::string count;
211 std::vector<uint64_t> countVec;
212 while (std::getline(iss, count, ',')) {
213 countVec.push_back(std::atoll(count.c_str()));
214 }
215 if (countVec.size() != OP_COUNT) {
216 LOGE("Statistic count num is invalid");
217 return false;
218 }
219 RadarStatisticInfo info;
220 info.keyLoadSuccCount = countVec.at(KEY_LOAD_SUCC_COUNT);
221 info.keyLoadFailCount = countVec.at(KEY_LOAD_FAIL_COUNT);
222 info.keyUnloadSuccCount = countVec.at(KEY_UNLOAD_SUCC_COUNT);
223 info.keyUnloadFailCount = countVec.at(KEY_UNLOAD_FAIL_COUNT);
224 info.userAddSuccCount = countVec.at(USER_ADD_SUCC_COUNT);
225 info.userAddFailCount = countVec.at(USER_ADD_FAIL_COUNT);
226 info.userRemoveSuccCount = countVec.at(USER_REMOVE_SUCC_COUNT);
227 info.userRemoveFailCount = countVec.at(USER_REMOVE_FAIL_COUNT);
228 info.userStartSuccCount = countVec.at(USER_START_SUCC_COUNT);
229 info.userStartFailCount = countVec.at(USER_START_FAIL_COUNT);
230 info.userStopSuccCount = countVec.at(USER_STOP_SUCC_COUNT);
231 info.userStopFailCount = countVec.at(USER_STOP_FAIL_COUNT);
232 statistics.insert(std::make_pair(userId, info));
233 return true;
234 }
235 } // namespace StorageService
236 } // namespace OHOS
237