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 #define LOG_TAG "AssetChangeTimer"
16 #include "asset_change_timer.h"
17
18 #include "anonymous.h"
19 #include "client_adaptor.h"
20 #include "logger.h"
21 #include "objectstore_errors.h"
22
23 namespace OHOS::ObjectStore {
24 std::mutex AssetChangeTimer::instanceMutex;
25 AssetChangeTimer *AssetChangeTimer::instance = nullptr;
26 static constexpr size_t MAX_THREADS = 3;
27 static constexpr size_t MIN_THREADS = 0;
28 static constexpr uint32_t WAIT_INTERVAL = 100;
29 static constexpr char ASSET_SEPARATOR = '#';
30
GetInstance(FlatObjectStore * flatObjectStore)31 AssetChangeTimer *AssetChangeTimer::GetInstance(FlatObjectStore *flatObjectStore)
32 {
33 if (instance == nullptr) {
34 std::lock_guard<decltype(instanceMutex)> lockGuard(instanceMutex);
35 if (instance == nullptr) {
36 instance = new (std::nothrow) AssetChangeTimer(flatObjectStore);
37 }
38 }
39 return instance;
40 }
41
AssetChangeTimer(FlatObjectStore * flatObjectStore)42 AssetChangeTimer::AssetChangeTimer(FlatObjectStore *flatObjectStore) : flatObjectStore_(flatObjectStore)
43 {
44 executor_ = std::make_shared<ExecutorPool>(MAX_THREADS, MIN_THREADS, "OBJECT_TASK");
45 }
46
OnAssetChanged(const std::string & sessionId,const std::string & assetKey,std::shared_ptr<ObjectWatcher> watcher)47 void AssetChangeTimer::OnAssetChanged(
48 const std::string &sessionId, const std::string &assetKey, std::shared_ptr<ObjectWatcher> watcher)
49 {
50 StartTimer(sessionId, assetKey, watcher);
51 }
52
StartTimer(const std::string & sessionId,const std::string & assetKey,std::shared_ptr<ObjectWatcher> watcher)53 void AssetChangeTimer::StartTimer(
54 const std::string &sessionId, const std::string &assetKey, std::shared_ptr<ObjectWatcher> watcher)
55 {
56 std::string key = sessionId + ASSET_SEPARATOR + assetKey;
57 std::lock_guard<decltype(mutex_)> lockGuard(mutex_);
58 if (assetChangeTasks_.find(key) == assetChangeTasks_.end()) {
59 assetChangeTasks_[key] =
60 executor_->Schedule(std::chrono::milliseconds(WAIT_INTERVAL), ProcessTask(sessionId, assetKey, watcher));
61 } else {
62 assetChangeTasks_[key] = executor_->Reset(assetChangeTasks_[key], std::chrono::milliseconds(WAIT_INTERVAL));
63 }
64 }
65
ProcessTask(const std::string & sessionId,const std::string & assetKey,std::shared_ptr<ObjectWatcher> watcher)66 std::function<void()> AssetChangeTimer::ProcessTask(
67 const std::string &sessionId, const std::string &assetKey, std::shared_ptr<ObjectWatcher> watcher)
68 {
69 return [=]() {
70 LOG_DEBUG("Start working on a task, sessionId: %{public}s, assetKey: %{public}s",
71 Anonymous::Change(sessionId).c_str(), assetKey.c_str());
72 StopTimer(sessionId, assetKey);
73 uint32_t status = HandleAssetChanges(sessionId, assetKey);
74 if (status == SUCCESS) {
75 LOG_DEBUG("Asset change task end, start callback, sessionId: %{public}s, assetKey: %{public}s",
76 Anonymous::Change(sessionId).c_str(), assetKey.c_str());
77 watcher->OnChanged(sessionId, { assetKey });
78 }
79 };
80 }
81
StopTimer(const std::string & sessionId,const std::string & assetKey)82 void AssetChangeTimer::StopTimer(const std::string &sessionId, const std::string &assetKey)
83 {
84 std::string key = sessionId + ASSET_SEPARATOR + assetKey;
85 std::lock_guard<decltype(mutex_)> lockGuard(mutex_);
86 executor_->Remove(assetChangeTasks_[key]);
87 assetChangeTasks_.erase(key);
88 }
89
HandleAssetChanges(const std::string & sessionId,const std::string & assetKey)90 uint32_t AssetChangeTimer::HandleAssetChanges(const std::string &sessionId, const std::string &assetKey)
91 {
92 Asset assetValue;
93 if (!GetAssetValue(sessionId, assetKey, assetValue)) {
94 LOG_ERROR("GetAssetValue assetValue is not complete, sessionId: %{public}s, assetKey: %{public}s",
95 Anonymous::Change(sessionId).c_str(), assetKey.c_str());
96 return ERR_DB_GET_FAIL;
97 }
98
99 std::string deviceId;
100 uint32_t status = flatObjectStore_->GetString(sessionId, DEVICEID_KEY, deviceId);
101 if (status != SUCCESS) {
102 LOG_ERROR("get deviceId failed %{public}d", status);
103 return status;
104 }
105
106 sptr<OHOS::DistributedObject::IObjectService> proxy = ClientAdaptor::GetObjectService();
107 if (proxy == nullptr) {
108 LOG_ERROR("proxy is nullptr.");
109 return ERR_NULL_PTR;
110 }
111 int32_t res = proxy->OnAssetChanged(flatObjectStore_->GetBundleName(), sessionId, deviceId, assetValue);
112 if (res != SUCCESS) {
113 LOG_ERROR("OnAssetChanged failed status: %{public}d, sessionId: %{public}s, assetKey: %{public}s", status,
114 Anonymous::Change(sessionId).c_str(), assetKey.c_str());
115 }
116 return res;
117 }
118
GetAssetValue(const std::string & sessionId,const std::string & assetKey,Asset & assetValue)119 bool AssetChangeTimer::GetAssetValue(const std::string &sessionId, const std::string &assetKey, Asset &assetValue)
120 {
121 double doubleStatus;
122 if (flatObjectStore_->GetDouble(sessionId, assetKey + STATUS_SUFFIX, doubleStatus) == SUCCESS) {
123 assetValue.status = static_cast<uint32_t>(doubleStatus);
124 }
125 bool isComplete = true;
126 isComplete = isComplete &&
127 (flatObjectStore_->GetString(sessionId, assetKey + NAME_SUFFIX, assetValue.name) == SUCCESS);
128 isComplete = isComplete &&
129 (flatObjectStore_->GetString(sessionId, assetKey + URI_SUFFIX, assetValue.uri) == SUCCESS);
130 isComplete = isComplete &&
131 (flatObjectStore_->GetString(sessionId, assetKey + PATH_SUFFIX, assetValue.path) == SUCCESS);
132 isComplete = isComplete &&
133 (flatObjectStore_->GetString(sessionId, assetKey + CREATE_TIME_SUFFIX, assetValue.createTime) == SUCCESS);
134 isComplete = isComplete &&
135 (flatObjectStore_->GetString(sessionId, assetKey + MODIFY_TIME_SUFFIX, assetValue.modifyTime) == SUCCESS);
136 isComplete = isComplete &&
137 (flatObjectStore_->GetString(sessionId, assetKey + SIZE_SUFFIX, assetValue.size) == SUCCESS);
138 if (isComplete) {
139 assetValue.name = assetValue.name.substr(STRING_PREFIX_LEN);
140 assetValue.uri = assetValue.uri.substr(STRING_PREFIX_LEN);
141 assetValue.path = assetValue.path.substr(STRING_PREFIX_LEN);
142 assetValue.createTime = assetValue.createTime.substr(STRING_PREFIX_LEN);
143 assetValue.modifyTime = assetValue.modifyTime.substr(STRING_PREFIX_LEN);
144 assetValue.size = assetValue.size.substr(STRING_PREFIX_LEN);
145 assetValue.hash = assetValue.modifyTime + "_" + assetValue.size;
146 }
147 return isComplete;
148 }
149 } // namespace OHOS::ObjectStore