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