1 /*
2 * Copyright (c) 2022 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 #include "data_storage_helper.h"
16
17 #include <fcntl.h>
18 #include <fstream>
19 #include <unistd.h>
20 #include <sstream>
21 #include <sys/stat.h>
22
23 #include "common_utils.h"
24 #include "continuous_task_log.h"
25
26 namespace OHOS {
27 namespace BackgroundTaskMgr {
28 namespace {
29 static constexpr int32_t MAX_BUFFER = 2048;
30 static constexpr char TASK_RECORD_FILE_PATH[] = "/data/service/el1/public/background_task_mgr/running_task";
31 static const std::string RESOURCE_RECORD_FILE_PATH = "/data/service/el1/public/background_task_mgr/resource_record";
32 static const std::string APP_RESOURCE_RECORD = "appResourceRecord";
33 static const std::string PROCESS_RESOURCE_RECORD = "processResourceRecord";
34 }
35
DataStorageHelper()36 DataStorageHelper::DataStorageHelper() {}
37
~DataStorageHelper()38 DataStorageHelper::~DataStorageHelper() {}
39
RefreshTaskRecord(const std::unordered_map<std::string,std::shared_ptr<ContinuousTaskRecord>> & allRecord)40 ErrCode DataStorageHelper::RefreshTaskRecord(const std::unordered_map<std::string,
41 std::shared_ptr<ContinuousTaskRecord>> &allRecord)
42 {
43 nlohmann::json root;
44 for (const auto &iter : allRecord) {
45 auto record = iter.second;
46 std::string data = record->ParseToJsonStr();
47 nlohmann::json recordJson = nlohmann::json::parse(data, nullptr, false);;
48 if (!recordJson.is_discarded()) {
49 root[iter.first] = recordJson;
50 }
51 }
52 return SaveJsonValueToFile(root.dump(CommonUtils::jsonFormat_), TASK_RECORD_FILE_PATH);
53 }
54
RestoreTaskRecord(std::unordered_map<std::string,std::shared_ptr<ContinuousTaskRecord>> & allRecord)55 ErrCode DataStorageHelper::RestoreTaskRecord(std::unordered_map<std::string,
56 std::shared_ptr<ContinuousTaskRecord>> &allRecord)
57 {
58 nlohmann::json root;
59 if (ParseJsonValueFromFile(root, TASK_RECORD_FILE_PATH) != ERR_OK) {
60 return ERR_BGTASK_DATA_STORAGE_ERR;
61 }
62 for (auto iter = root.begin(); iter != root.end(); iter++) {
63 nlohmann::json recordJson = iter.value();
64 std::shared_ptr<ContinuousTaskRecord> record = std::make_shared<ContinuousTaskRecord>();
65 if (record->ParseFromJson(recordJson)) {
66 allRecord.emplace(iter.key(), record);
67 }
68 }
69 return ERR_OK;
70 }
71
RefreshResourceRecord(const ResourceRecordMap & appRecord,const ResourceRecordMap & processRecord)72 ErrCode DataStorageHelper::RefreshResourceRecord(const ResourceRecordMap &appRecord,
73 const ResourceRecordMap &processRecord)
74 {
75 std::string record {""};
76 ConvertMapToString(appRecord, processRecord, record);
77 return SaveJsonValueToFile(record, RESOURCE_RECORD_FILE_PATH);
78 }
79
RestoreResourceRecord(ResourceRecordMap & appRecord,ResourceRecordMap & processRecord)80 ErrCode DataStorageHelper::RestoreResourceRecord(ResourceRecordMap &appRecord,
81 ResourceRecordMap &processRecord)
82 {
83 nlohmann::json root;
84 if (ParseJsonValueFromFile(root, RESOURCE_RECORD_FILE_PATH) != ERR_OK) {
85 BGTASK_LOGD("can not read string form file: %{public}s", RESOURCE_RECORD_FILE_PATH.c_str());
86 return ERR_BGTASK_DATA_STORAGE_ERR;
87 }
88 DivideJsonToMap(root, appRecord, processRecord);
89 return ERR_OK;
90 }
91
SaveJsonValueToFile(const std::string & value,const std::string & filePath)92 int32_t DataStorageHelper::SaveJsonValueToFile(const std::string &value, const std::string &filePath)
93 {
94 if (!CreateNodeFile(filePath)) {
95 BGTASK_LOGE("Create file failed.");
96 return ERR_BGTASK_CREATE_FILE_ERR;
97 }
98 std::ofstream fout;
99 std::string realPath;
100 if (!ConvertFullPath(filePath, realPath)) {
101 BGTASK_LOGE("SaveJsonValueToFile Get real file path: %{public}s failed", filePath.c_str());
102 return ERR_BGTASK_GET_ACTUAL_FILE_ERR;
103 }
104 fout.open(realPath, std::ios::out);
105 if (!fout.is_open()) {
106 BGTASK_LOGE("Open file: %{public}s failed.", filePath.c_str());
107 return ERR_BGTASK_OPEN_FILE_ERR;
108 }
109 fout << value.c_str() << std::endl;
110 fout.close();
111 return ERR_OK;
112 }
113
ParseJsonValueFromFile(nlohmann::json & value,const std::string & filePath)114 int32_t DataStorageHelper::ParseJsonValueFromFile(nlohmann::json &value, const std::string &filePath)
115 {
116 std::ifstream fin;
117 std::string realPath;
118 if (!ConvertFullPath(filePath, realPath)) {
119 BGTASK_LOGE("Get real path failed");
120 return ERR_BGTASK_DATA_STORAGE_ERR;
121 }
122 fin.open(realPath, std::ios::in);
123 if (!fin.is_open()) {
124 BGTASK_LOGE("cannot open file %{public}s", realPath.c_str());
125 return ERR_BGTASK_DATA_STORAGE_ERR;
126 }
127 char buffer[MAX_BUFFER];
128 std::ostringstream os;
129 while (fin.getline(buffer, MAX_BUFFER)) {
130 os << buffer;
131 }
132 std::string data = os.str();
133 value = nlohmann::json::parse(data, nullptr, false);
134 if (value.is_discarded()) {
135 BGTASK_LOGE("failed due to data is discarded");
136 return ERR_BGTASK_DATA_STORAGE_ERR;
137 }
138 return ERR_OK;
139 }
140
CreateNodeFile(const std::string & filePath)141 bool DataStorageHelper::CreateNodeFile(const std::string &filePath)
142 {
143 if (access(filePath.c_str(), F_OK) == ERR_OK) {
144 BGTASK_LOGD("the file: %{public}s already exists.", filePath.c_str());
145 return true;
146 }
147 int32_t fd = open(filePath.c_str(), O_CREAT|O_RDWR, S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH);
148 if (fd < ERR_OK) {
149 BGTASK_LOGE("Fail to open file: %{public}s", filePath.c_str());
150 return false;
151 }
152 close(fd);
153 return true;
154 }
155
ConvertFullPath(const std::string & partialPath,std::string & fullPath)156 bool DataStorageHelper::ConvertFullPath(const std::string& partialPath, std::string& fullPath)
157 {
158 if (partialPath.empty() || partialPath.length() >= PATH_MAX) {
159 return false;
160 }
161 char tmpPath[PATH_MAX] = {0};
162 if (realpath(partialPath.c_str(), tmpPath) == nullptr) {
163 return false;
164 }
165 fullPath = tmpPath;
166 return true;
167 }
168
ConvertMapToString(const ResourceRecordMap & appRecord,const ResourceRecordMap & processRecord,std::string & recordString)169 void DataStorageHelper::ConvertMapToString(const ResourceRecordMap &appRecord,
170 const ResourceRecordMap &processRecord, std::string &recordString)
171 {
172 nlohmann::json root;
173 nlohmann::json appValue;
174 ConvertMapToJson(appRecord, appValue);
175 root[APP_RESOURCE_RECORD] = appValue;
176 nlohmann::json processValue;
177 ConvertMapToJson(processRecord, processValue);
178 root[PROCESS_RESOURCE_RECORD] = processValue;
179 recordString = root.dump(CommonUtils::jsonFormat_);
180 }
181
ConvertMapToJson(const ResourceRecordMap & appRecord,nlohmann::json & root)182 void DataStorageHelper::ConvertMapToJson(const ResourceRecordMap &appRecord, nlohmann::json &root)
183 {
184 for (const auto &iter : appRecord) {
185 nlohmann::json value;
186 iter.second->ParseToJson(value);
187 root[std::to_string(iter.first)] = value;
188 }
189 }
190
DivideJsonToMap(nlohmann::json & root,ResourceRecordMap & appRecord,ResourceRecordMap & processRecord)191 void DataStorageHelper::DivideJsonToMap(nlohmann::json &root,
192 ResourceRecordMap &appRecord, ResourceRecordMap &processRecord)
193 {
194 nlohmann::json appRecordJson = root.at(APP_RESOURCE_RECORD);
195 nlohmann::json processrecordJson = root.at(PROCESS_RESOURCE_RECORD);
196 ConvertJsonToMap(appRecordJson, appRecord);
197 ConvertJsonToMap(processrecordJson, processRecord);
198 }
199
ConvertJsonToMap(const nlohmann::json & value,ResourceRecordMap & recordMap)200 void DataStorageHelper::ConvertJsonToMap(const nlohmann::json &value, ResourceRecordMap &recordMap)
201 {
202 for (auto iter = value.begin(); iter != value.end(); iter++) {
203 std::shared_ptr<ResourceApplicationRecord> recordPtr = std::make_shared<ResourceApplicationRecord>();
204 recordPtr->ParseFromJson(iter.value());
205 recordMap.emplace(static_cast<uint32_t>(std::stoi(iter.key())), recordPtr);
206 }
207 }
208 } // namespace BackgroundTaskMgr
209 } // namespace OHOS
210
211