1 /*
2 * Copyright (c) 2021 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 "auto_launch.h"
17
18 #include "cloud/cloud_db_constant.h"
19 #include "concurrent_adapter.h"
20 #include "db_common.h"
21 #include "db_dump_helper.h"
22 #include "db_dfx_adapter.h"
23 #include "db_errno.h"
24 #include "kv_store_changed_data_impl.h"
25 #include "kv_store_nb_conflict_data_impl.h"
26 #include "kvdb_manager.h"
27 #include "kvdb_pragma.h"
28 #include "log_print.h"
29 #include "param_check_utils.h"
30 #include "relational_store_instance.h"
31 #include "relational_store_changed_data_impl.h"
32 #include "res_finalizer.h"
33 #include "runtime_context.h"
34 #include "semaphore_utils.h"
35 #include "sync_able_kvdb_connection.h"
36
37 namespace DistributedDB {
38 namespace {
39 constexpr int MAX_AUTO_LAUNCH_ITEM_NUM = 8;
40 }
41
SetCommunicatorAggregator(ICommunicatorAggregator * aggregator)42 void AutoLaunch::SetCommunicatorAggregator(ICommunicatorAggregator *aggregator)
43 {
44 LOGI("[AutoLaunch] SetCommunicatorAggregator");
45 std::lock_guard<std::mutex> autoLock(communicatorLock_);
46 int errCode;
47 if (communicatorAggregator_ != nullptr) {
48 LOGI("[AutoLaunch] SetCommunicatorAggregator communicatorAggregator_ is not nullptr");
49 errCode = communicatorAggregator_->RegOnConnectCallback(nullptr, nullptr);
50 if (errCode != E_OK) {
51 LOGW("[AutoLaunch] RegOnConnectCallback set nullptr failed, errCode:%d", errCode);
52 }
53 errCode = communicatorAggregator_->RegCommunicatorLackCallback(nullptr, nullptr);
54 if (errCode != E_OK) {
55 LOGW("[AutoLaunch] RegCommunicatorLackCallback set nullptr failed, errCode:%d", errCode);
56 }
57 }
58 communicatorAggregator_ = aggregator;
59 if (aggregator == nullptr) {
60 LOGI("[AutoLaunch] SetCommunicatorAggregator aggregator is nullptr");
61 return;
62 }
63 errCode = aggregator->RegOnConnectCallback(
64 [this](const std::string &device, bool isConnect) { OnlineCallBack(device, isConnect); }, nullptr);
65 if (errCode != E_OK) {
66 LOGE("[AutoLaunch] RegOnConnectCallback errCode:%d", errCode);
67 }
68 errCode = aggregator->RegCommunicatorLackCallback(
69 [this](const LabelType &label, const std::string &originalUserId) {
70 return ReceiveUnknownIdentifierCallBack(label, originalUserId);
71 }, nullptr);
72 if (errCode != E_OK) {
73 LOGE("[AutoLaunch] RegCommunicatorLackCallback errCode:%d", errCode);
74 }
75 }
76
~AutoLaunch()77 AutoLaunch::~AutoLaunch()
78 {
79 {
80 std::lock_guard<std::mutex> autoLock(communicatorLock_);
81 LOGI("[AutoLaunch] ~AutoLaunch()");
82 if (communicatorAggregator_ != nullptr) {
83 communicatorAggregator_->RegOnConnectCallback(nullptr, nullptr);
84 communicatorAggregator_->RegCommunicatorLackCallback(nullptr, nullptr);
85 communicatorAggregator_ = nullptr;
86 }
87 }
88 // {identifier, userId}
89 std::set<std::pair<std::string, std::string>> inDisableSet;
90 std::set<std::pair<std::string, std::string>> inWaitIdleSet;
91 std::unique_lock<std::mutex> autoLock(dataLock_);
92 for (auto &items : autoLaunchItemMap_) {
93 for (auto &iter : items.second) {
94 if (iter.second.isDisable) {
95 inDisableSet.insert({ items.first, iter.first });
96 } else if (iter.second.state == AutoLaunchItemState::IDLE && (!iter.second.inObserver)) {
97 TryCloseConnection(iter.second);
98 } else {
99 inWaitIdleSet.insert({ items.first, iter.first });
100 iter.second.isDisable = true;
101 }
102 }
103 }
104 for (const auto &identifierInfo : inDisableSet) {
105 cv_.wait(autoLock, [identifierInfo, this] {
106 return autoLaunchItemMap_.count(identifierInfo.first) == 0 ||
107 autoLaunchItemMap_[identifierInfo.first].count(identifierInfo.second) == 0 ||
108 (!autoLaunchItemMap_[identifierInfo.first][identifierInfo.second].isDisable);
109 });
110 if (autoLaunchItemMap_.count(identifierInfo.first) != 0 &&
111 autoLaunchItemMap_[identifierInfo.first].count(identifierInfo.second)) { // LCOV_EXCL_BR_LINE
112 TryCloseConnection(autoLaunchItemMap_[identifierInfo.first][identifierInfo.second]);
113 }
114 }
115 for (const auto &info : inWaitIdleSet) {
116 cv_.wait(autoLock, [info, this] {
117 return (autoLaunchItemMap_[info.first][info.second].state == AutoLaunchItemState::IDLE) &&
118 (!autoLaunchItemMap_[info.first][info.second].inObserver);
119 });
120 TryCloseConnection(autoLaunchItemMap_[info.first][info.second]);
121 }
122 }
123
EnableKvStoreAutoLaunchParmCheck(AutoLaunchItem & autoLaunchItem,const std::string & normalIdentifier,const std::string & dualTupleIdentifier,bool isDualTupleMode)124 int AutoLaunch::EnableKvStoreAutoLaunchParmCheck(AutoLaunchItem &autoLaunchItem, const std::string &normalIdentifier,
125 const std::string &dualTupleIdentifier, bool isDualTupleMode)
126 {
127 std::lock_guard<std::mutex> autoLock(dataLock_);
128 std::string userId = autoLaunchItem.propertiesPtr->GetStringProp(DBProperties::USER_ID, "");
129 if (isDualTupleMode && autoLaunchItemMap_.count(normalIdentifier) != 0 &&
130 autoLaunchItemMap_[normalIdentifier].count(userId) != 0) {
131 LOGE("[AutoLaunch] EnableKvStoreAutoLaunchParmCheck identifier is already enabled in normal tuple mode");
132 return -E_ALREADY_SET;
133 }
134 if (!isDualTupleMode && autoLaunchItemMap_.count(dualTupleIdentifier) != 0 &&
135 autoLaunchItemMap_[dualTupleIdentifier].count(userId) != 0) {
136 LOGE("[AutoLaunch] EnableKvStoreAutoLaunchParmCheck identifier is already enabled in dual tuple mode");
137 return -E_ALREADY_SET;
138 }
139 std::string identifier = isDualTupleMode ? dualTupleIdentifier : normalIdentifier;
140 if (identifier.empty()) {
141 LOGE("[AutoLaunch] EnableKvStoreAutoLaunchParmCheck identifier is invalid");
142 return -E_INVALID_ARGS;
143 }
144 if (autoLaunchItemMap_.count(identifier) != 0 && autoLaunchItemMap_[identifier].count(userId) != 0) {
145 LOGE("[AutoLaunch] EnableKvStoreAutoLaunchParmCheck identifier is already enabled!");
146 return -E_ALREADY_SET;
147 }
148 uint32_t autoLaunchItemSize = 0;
149 for (const auto &item : autoLaunchItemMap_) {
150 autoLaunchItemSize += item.second.size();
151 }
152 if (autoLaunchItemSize == MAX_AUTO_LAUNCH_ITEM_NUM) {
153 LOGE("[AutoLaunch] EnableKvStoreAutoLaunchParmCheck size is max(8) now");
154 return -E_MAX_LIMITS;
155 }
156 autoLaunchItem.state = AutoLaunchItemState::IN_ENABLE;
157 autoLaunchItemMap_[identifier][userId] = autoLaunchItem;
158 LOGI("[AutoLaunch] EnableKvStoreAutoLaunchParmCheck ok identifier=%.6s, isDual=%d",
159 STR_TO_HEX(identifier), isDualTupleMode);
160 return E_OK;
161 }
162
EnableKvStoreAutoLaunch(const KvDBProperties & properties,AutoLaunchNotifier notifier,const AutoLaunchOption & option)163 int AutoLaunch::EnableKvStoreAutoLaunch(const KvDBProperties &properties, AutoLaunchNotifier notifier,
164 const AutoLaunchOption &option)
165 {
166 LOGI("[AutoLaunch] EnableKvStoreAutoLaunch");
167 bool isDualTupleMode = properties.GetBoolProp(KvDBProperties::SYNC_DUAL_TUPLE_MODE, false);
168 std::string dualTupleIdentifier = properties.GetStringProp(KvDBProperties::DUAL_TUPLE_IDENTIFIER_DATA, "");
169 std::string identifier = properties.GetStringProp(KvDBProperties::IDENTIFIER_DATA, "");
170 std::string userId = properties.GetStringProp(KvDBProperties::USER_ID, "");
171 std::shared_ptr<DBProperties> ptr = std::make_shared<KvDBProperties>(properties);
172 AutoLaunchItem autoLaunchItem { ptr, notifier, option.observer, option.conflictType, option.notifier };
173 autoLaunchItem.isAutoSync = option.isAutoSync;
174 autoLaunchItem.type = DBTypeInner::DB_KV;
175 int errCode = EnableKvStoreAutoLaunchParmCheck(autoLaunchItem, identifier, dualTupleIdentifier, isDualTupleMode);
176 if (errCode != E_OK) {
177 LOGE("[AutoLaunch] EnableKvStoreAutoLaunch failed errCode:%d", errCode);
178 return errCode;
179 }
180 if (isDualTupleMode && !RuntimeContext::GetInstance()->IsSyncerNeedActive(properties)) {
181 std::lock_guard<std::mutex> autoLock(dataLock_);
182 std::string tmpIdentifier = isDualTupleMode ? dualTupleIdentifier : identifier;
183 LOGI("[AutoLaunch] GetDoOpenMap identifier=%.6s no need to open", STR_TO_HEX(tmpIdentifier));
184 autoLaunchItemMap_[tmpIdentifier][userId].state = AutoLaunchItemState::IDLE;
185 return errCode;
186 }
187 errCode = GetKVConnectionInEnable(autoLaunchItem, isDualTupleMode ? dualTupleIdentifier : identifier);
188 if (errCode == E_OK) {
189 LOGI("[AutoLaunch] EnableKvStoreAutoLaunch ok");
190 } else {
191 LOGE("[AutoLaunch] EnableKvStoreAutoLaunch failed errCode:%d", errCode);
192 }
193 return errCode;
194 }
195
GetKVConnectionInEnableInner(const AutoLaunchItem & autoLaunchItem,const std::string & identifier,const std::string & userId)196 void AutoLaunch::GetKVConnectionInEnableInner(const AutoLaunchItem &autoLaunchItem, const std::string &identifier,
197 const std::string &userId)
198 {
199 std::lock_guard<std::mutex> autoLock(dataLock_);
200 autoLaunchItemMap_[identifier][userId].state = AutoLaunchItemState::IDLE;
201 autoLaunchItemMap_[identifier][userId].conn = autoLaunchItem.conn;
202 autoLaunchItemMap_[identifier][userId].observerHandle = autoLaunchItem.observerHandle;
203 }
204
GetKVConnectionInEnable(AutoLaunchItem & autoLaunchItem,const std::string & identifier)205 int AutoLaunch::GetKVConnectionInEnable(AutoLaunchItem &autoLaunchItem, const std::string &identifier)
206 {
207 LOGI("[AutoLaunch] GetKVConnectionInEnable");
208 int errCode;
209 std::shared_ptr<KvDBProperties> properties = std::static_pointer_cast<KvDBProperties>(autoLaunchItem.propertiesPtr);
210 if (properties == nullptr) {
211 LOGE("[AutoLaunch] GetKVConnectionInEnable properties is nullptr");
212 return -E_INTERNAL_ERROR;
213 }
214 std::string userId = properties->GetStringProp(KvDBProperties::USER_ID, "");
215 autoLaunchItem.conn = KvDBManager::GetDatabaseConnection(*properties, errCode, false);
216 if (errCode == -E_ALREADY_OPENED) {
217 LOGI("[AutoLaunch] GetKVConnectionInEnable user already getkvstore by self");
218 std::lock_guard<std::mutex> autoLock(dataLock_);
219 autoLaunchItemMap_[identifier][userId].state = AutoLaunchItemState::IDLE;
220 return E_OK;
221 }
222 if (autoLaunchItem.conn == nullptr) {
223 EraseAutoLaunchItem(identifier, userId);
224 return errCode;
225 }
226 bool isEmpty = false;
227 {
228 std::lock_guard<std::mutex> onlineDevicesLock(dataLock_);
229 isEmpty = onlineDevices_.empty();
230 }
231 if (isEmpty) {
232 LOGI("[AutoLaunch] GetKVConnectionInEnable no online device, ReleaseDatabaseConnection");
233 IKvDBConnection *kvConn = static_cast<IKvDBConnection *>(autoLaunchItem.conn);
234 errCode = KvDBManager::ReleaseDatabaseConnection(kvConn);
235 if (errCode != E_OK) {
236 LOGE("[AutoLaunch] GetKVConnectionInEnable ReleaseDatabaseConnection failed errCode:%d", errCode);
237 EraseAutoLaunchItem(identifier, userId);
238 return errCode;
239 }
240 std::lock_guard<std::mutex> autoLock(dataLock_);
241 autoLaunchItemMap_[identifier][userId].state = AutoLaunchItemState::IDLE;
242 return E_OK;
243 }
244 errCode = RegisterObserverAndLifeCycleCallback(autoLaunchItem, identifier, false);
245 if (errCode == E_OK) {
246 GetKVConnectionInEnableInner(autoLaunchItem, identifier, userId);
247 } else {
248 LOGE("[AutoLaunch] GetKVConnectionInEnable RegisterObserverAndLifeCycleCallback err, do CloseConnection");
249 TryCloseConnection(autoLaunchItem); // do nothing if failed
250 EraseAutoLaunchItem(identifier, userId);
251 }
252 return errCode;
253 }
254
255 // we will return errCode, if errCode != E_OK
CloseConnectionStrict(AutoLaunchItem & autoLaunchItem)256 int AutoLaunch::CloseConnectionStrict(AutoLaunchItem &autoLaunchItem)
257 {
258 LOGI("[AutoLaunch] CloseConnectionStrict");
259 if (autoLaunchItem.conn == nullptr) {
260 LOGI("[AutoLaunch] CloseConnectionStrict conn is nullptr, do nothing");
261 return E_OK;
262 }
263 IKvDBConnection *kvConn = static_cast<IKvDBConnection *>(autoLaunchItem.conn);
264 int errCode = kvConn->RegisterLifeCycleCallback(nullptr);
265 if (errCode != E_OK) {
266 LOGE("[AutoLaunch] CloseConnectionStrict RegisterLifeCycleCallback failed errCode:%d", errCode);
267 return errCode;
268 }
269 if (autoLaunchItem.observerHandle != nullptr) {
270 errCode = kvConn->UnRegisterObserver(autoLaunchItem.observerHandle);
271 if (errCode != E_OK) {
272 LOGE("[AutoLaunch] CloseConnectionStrict UnRegisterObserver failed errCode:%d", errCode);
273 return errCode;
274 }
275 autoLaunchItem.observerHandle = nullptr;
276 }
277 errCode = KvDBManager::ReleaseDatabaseConnection(kvConn);
278 if (errCode != E_OK) {
279 LOGE("[AutoLaunch] CloseConnectionStrict ReleaseDatabaseConnection failed errCode:%d", errCode);
280 }
281 return errCode;
282 }
283
284 // before ReleaseDatabaseConnection, if errCode != E_OK, we not return, we try close more
TryCloseConnection(AutoLaunchItem & autoLaunchItem)285 void AutoLaunch::TryCloseConnection(AutoLaunchItem &autoLaunchItem)
286 {
287 LOGI("[AutoLaunch] TryCloseConnection");
288 switch (autoLaunchItem.type) {
289 case DBTypeInner::DB_KV:
290 TryCloseKvConnection(autoLaunchItem);
291 break;
292 case DBTypeInner::DB_RELATION:
293 TryCloseRelationConnection(autoLaunchItem);
294 break;
295 default:
296 LOGD("[AutoLaunch] Unknown type[%d] when try to close connection", static_cast<int>(autoLaunchItem.type));
297 break;
298 }
299 }
300
RegisterObserverAndLifeCycleCallback(AutoLaunchItem & autoLaunchItem,const std::string & identifier,bool isExt)301 int AutoLaunch::RegisterObserverAndLifeCycleCallback(AutoLaunchItem &autoLaunchItem, const std::string &identifier,
302 bool isExt)
303 {
304 int errCode = RegisterObserver(autoLaunchItem, identifier, isExt);
305 if (errCode != E_OK) {
306 return errCode;
307 }
308 LOGI("[AutoLaunch] RegisterObserver ok");
309
310 errCode = RegisterLifeCycleCallback(autoLaunchItem, identifier, isExt);
311 if (errCode != E_OK) {
312 LOGE("[AutoLaunch] RegisterLifeCycleCallback failed, errCode:%d", errCode);
313 return errCode;
314 }
315 LOGI("[AutoLaunch] RegisterLifeCycleCallback ok");
316
317 errCode = SetConflictNotifier(autoLaunchItem);
318 if (errCode != E_OK) {
319 LOGE("[AutoLaunch] SetConflictNotifier failed, errCode:%d", errCode);
320 return errCode;
321 }
322
323 return PragmaAutoSync(autoLaunchItem);
324 }
325
RegisterObserver(AutoLaunchItem & autoLaunchItem,const std::string & identifier,bool isExt)326 int AutoLaunch::RegisterObserver(AutoLaunchItem &autoLaunchItem, const std::string &identifier, bool isExt)
327 {
328 if (autoLaunchItem.conn == nullptr) {
329 LOGE("[AutoLaunch] autoLaunchItem.conn is nullptr");
330 return -E_INTERNAL_ERROR;
331 }
332 LOGI("[AutoLaunch] RegisterObserver type=%d", static_cast<int>(autoLaunchItem.type));
333 switch (autoLaunchItem.type) {
334 case DBTypeInner::DB_RELATION:
335 return RegisterRelationalObserver(autoLaunchItem, identifier, isExt);
336 case DBTypeInner::DB_KV:
337 return RegisterKvObserver(autoLaunchItem, identifier, isExt);
338 default:
339 return -E_INVALID_ARGS;
340 }
341 }
342
ObserverFunc(const KvDBCommitNotifyData & notifyData,const std::string & identifier,const std::string & userId)343 void AutoLaunch::ObserverFunc(const KvDBCommitNotifyData ¬ifyData, const std::string &identifier,
344 const std::string &userId)
345 {
346 LOGD("[AutoLaunch] ObserverFunc identifier=%.6s", STR_TO_HEX(identifier));
347 AutoLaunchItem autoLaunchItem;
348 std::string appId;
349 std::string storeId;
350 {
351 std::lock_guard<std::mutex> autoLock(dataLock_);
352 if (autoLaunchItemMap_.count(identifier) == 0 || autoLaunchItemMap_[identifier].count(userId) == 0) {
353 LOGE("[AutoLaunch] ObserverFunc err no this identifier in map");
354 return;
355 }
356 if (autoLaunchItemMap_[identifier][userId].isDisable) {
357 LOGI("[AutoLaunch] ObserverFunc isDisable, do nothing");
358 return;
359 }
360 autoLaunchItemMap_[identifier][userId].inObserver = true;
361 autoLaunchItem.observer = autoLaunchItemMap_[identifier][userId].observer;
362 autoLaunchItem.isWriteOpenNotified = autoLaunchItemMap_[identifier][userId].isWriteOpenNotified;
363 autoLaunchItem.notifier = autoLaunchItemMap_[identifier][userId].notifier;
364
365 std::shared_ptr<KvDBProperties> properties =
366 std::static_pointer_cast<KvDBProperties>(autoLaunchItemMap_[identifier][userId].propertiesPtr);
367 appId = properties->GetStringProp(KvDBProperties::APP_ID, "");
368 storeId = properties->GetStringProp(KvDBProperties::STORE_ID, "");
369 }
370 if (autoLaunchItem.observer != nullptr) {
371 LOGI("[AutoLaunch] do user observer");
372 KvStoreChangedDataImpl data(¬ifyData);
373 (autoLaunchItem.observer)->OnChange(data);
374 }
375 LOGI("[AutoLaunch] in observer autoLaunchItem.isWriteOpenNotified:%d", autoLaunchItem.isWriteOpenNotified);
376
377 if (!autoLaunchItem.isWriteOpenNotified && autoLaunchItem.notifier != nullptr) {
378 {
379 std::lock_guard<std::mutex> autoLock(dataLock_);
380 autoLaunchItemMap_[identifier][userId].isWriteOpenNotified = true;
381 }
382 AutoLaunchNotifier notifier = autoLaunchItem.notifier;
383 int retCode = RuntimeContext::GetInstance()->ScheduleTask([notifier, userId, appId, storeId] {
384 LOGI("[AutoLaunch] notify the user auto opened event");
385 notifier(userId, appId, storeId, AutoLaunchStatus::WRITE_OPENED);
386 });
387 if (retCode != E_OK) {
388 LOGE("[AutoLaunch] ObserverFunc notifier ScheduleTask retCode:%d", retCode);
389 }
390 }
391 std::lock_guard<std::mutex> autoLock(dataLock_);
392 autoLaunchItemMap_[identifier][userId].inObserver = false;
393 cv_.notify_all();
394 }
395
DisableKvStoreAutoLaunch(const std::string & normalIdentifier,const std::string & dualTupleIdentifier,const std::string & userId)396 int AutoLaunch::DisableKvStoreAutoLaunch(const std::string &normalIdentifier, const std::string &dualTupleIdentifier,
397 const std::string &userId)
398 {
399 std::string identifier;
400 AutoLaunchItem autoLaunchItem;
401 {
402 std::unique_lock<std::mutex> autoLock(dataLock_);
403 identifier = (autoLaunchItemMap_.count(normalIdentifier) == 0) ? dualTupleIdentifier : normalIdentifier;
404 LOGI("[AutoLaunch] DisableKvStoreAutoLaunch identifier=%.6s", STR_TO_HEX(identifier));
405 if (autoLaunchItemMap_.count(identifier) == 0 || autoLaunchItemMap_[identifier].count(userId) == 0) {
406 LOGE("[AutoLaunch] DisableKvStoreAutoLaunch identifier is not exist!");
407 return -E_NOT_FOUND;
408 }
409 if (autoLaunchItemMap_[identifier][userId].isDisable) {
410 LOGI("[AutoLaunch] DisableKvStoreAutoLaunch already disabling in another thread, do nothing here");
411 return -E_BUSY;
412 }
413 if (autoLaunchItemMap_[identifier][userId].state == AutoLaunchItemState::IN_ENABLE) {
414 LOGE("[AutoLaunch] DisableKvStoreAutoLaunch enable not return, do not disable!");
415 return -E_BUSY;
416 }
417 autoLaunchItemMap_[identifier][userId].isDisable = true;
418 if (autoLaunchItemMap_[identifier][userId].state != AutoLaunchItemState::IDLE) {
419 LOGI("[AutoLaunch] DisableKvStoreAutoLaunch wait idle");
420 cv_.wait(autoLock, [identifier, userId, this] {
421 return (autoLaunchItemMap_[identifier][userId].state == AutoLaunchItemState::IDLE) &&
422 (!autoLaunchItemMap_[identifier][userId].inObserver);
423 });
424 LOGI("[AutoLaunch] DisableKvStoreAutoLaunch wait idle ok");
425 }
426 autoLaunchItem = autoLaunchItemMap_[identifier][userId];
427 }
428
429 int errCode = CloseConnectionStrict(autoLaunchItem);
430 if (errCode != E_OK) {
431 LOGE("[AutoLaunch] DisableKvStoreAutoLaunch CloseConnection failed errCode:%d", errCode);
432 std::lock_guard<std::mutex> autoLock(dataLock_);
433 autoLaunchItemMap_[identifier][userId].isDisable = false;
434 autoLaunchItemMap_[identifier][userId].observerHandle = autoLaunchItem.observerHandle;
435 cv_.notify_all();
436 return errCode;
437 }
438
439 EraseAutoLaunchItem(identifier, userId);
440 cv_.notify_all();
441 if (autoLaunchItem.isWriteOpenNotified && autoLaunchItem.notifier) {
442 RuntimeContext::GetInstance()->ScheduleTask([autoLaunchItem] { CloseNotifier(autoLaunchItem); });
443 }
444 LOGI("[AutoLaunch] DisableKvStoreAutoLaunch ok");
445 return E_OK;
446 }
447
GetAutoLaunchSyncDevices(const std::string & identifier,std::vector<std::string> & devices) const448 void AutoLaunch::GetAutoLaunchSyncDevices(const std::string &identifier, std::vector<std::string> &devices) const
449 {
450 devices.clear();
451 std::lock_guard<std::mutex> autoLock(dataLock_);
452 if (autoLaunchItemMap_.count(identifier) == 0) {
453 LOGD("[AutoLaunch] GetSyncDevices identifier is not exist!");
454 return;
455 }
456 for (const auto &device : onlineDevices_) {
457 devices.push_back(device);
458 }
459 devices.shrink_to_fit();
460 }
461
CloseNotifier(const AutoLaunchItem & autoLaunchItem)462 void AutoLaunch::CloseNotifier(const AutoLaunchItem &autoLaunchItem)
463 {
464 if (autoLaunchItem.notifier) {
465 std::string userId = autoLaunchItem.propertiesPtr->GetStringProp(DBProperties::USER_ID, "");
466 std::string appId = autoLaunchItem.propertiesPtr->GetStringProp(DBProperties::APP_ID, "");
467 std::string storeId = autoLaunchItem.propertiesPtr->GetStringProp(DBProperties::STORE_ID, "");
468 LOGI("[AutoLaunch] CloseNotifier do autoLaunchItem.notifier");
469 autoLaunchItem.notifier(userId, appId, storeId, AutoLaunchStatus::WRITE_CLOSED);
470 LOGI("[AutoLaunch] CloseNotifier do autoLaunchItem.notifier finished");
471 } else {
472 LOGI("[AutoLaunch] CloseNotifier autoLaunchItem.notifier is nullptr");
473 }
474 }
475
ConnectionLifeCycleCallbackTask(const std::string & identifier,const std::string & userId)476 void AutoLaunch::ConnectionLifeCycleCallbackTask(const std::string &identifier, const std::string &userId)
477 {
478 LOGI("[AutoLaunch] ConnectionLifeCycleCallbackTask identifier=%.6s", STR_TO_HEX(identifier));
479 AutoLaunchItem autoLaunchItem;
480 {
481 std::lock_guard<std::mutex> autoLock(dataLock_);
482 if (autoLaunchItemMap_.count(identifier) == 0 || autoLaunchItemMap_[identifier].count(userId) == 0) {
483 LOGE("[AutoLaunch] ConnectionLifeCycleCallback identifier is not exist!");
484 return;
485 }
486 if (autoLaunchItemMap_[identifier][userId].isDisable) {
487 LOGI("[AutoLaunch] ConnectionLifeCycleCallback isDisable, do nothing");
488 return;
489 }
490 if (autoLaunchItemMap_[identifier][userId].state != AutoLaunchItemState::IDLE) {
491 LOGI("[AutoLaunch] ConnectionLifeCycleCallback state:%d is not idle, do nothing",
492 static_cast<int>(autoLaunchItemMap_[identifier][userId].state));
493 return;
494 }
495 autoLaunchItemMap_[identifier][userId].state = AutoLaunchItemState::IN_LIFE_CYCLE_CALL_BACK;
496 autoLaunchItem = autoLaunchItemMap_[identifier][userId];
497 }
498 LOGI("[AutoLaunch] ConnectionLifeCycleCallbackTask do CloseConnection");
499 TryCloseConnection(autoLaunchItem); // do nothing if failed
500 LOGI("[AutoLaunch] ConnectionLifeCycleCallback do CloseConnection finished");
501 {
502 std::lock_guard<std::mutex> lock(dataLock_);
503 autoLaunchItemMap_[identifier][userId].state = AutoLaunchItemState::IDLE;
504 autoLaunchItemMap_[identifier][userId].conn = nullptr;
505 autoLaunchItemMap_[identifier][userId].isWriteOpenNotified = false;
506 cv_.notify_all();
507 LOGI("[AutoLaunch] ConnectionLifeCycleCallback notify_all");
508 }
509 if (autoLaunchItem.isWriteOpenNotified) {
510 CloseNotifier(autoLaunchItem);
511 }
512 }
513
ConnectionLifeCycleCallback(const std::string & identifier,const std::string & userId)514 void AutoLaunch::ConnectionLifeCycleCallback(const std::string &identifier, const std::string &userId)
515 {
516 LOGI("[AutoLaunch] ConnectionLifeCycleCallback identifier=%.6s", STR_TO_HEX(identifier));
517 int errCode = RuntimeContext::GetInstance()->ScheduleTask(
518 [this, identifier, userId] { ConnectionLifeCycleCallbackTask(identifier, userId); });
519 if (errCode != E_OK) {
520 LOGE("[AutoLaunch] ConnectionLifeCycleCallback ScheduleTask failed");
521 }
522 }
523
OpenOneConnection(AutoLaunchItem & autoLaunchItem)524 int AutoLaunch::OpenOneConnection(AutoLaunchItem &autoLaunchItem)
525 {
526 LOGI("[AutoLaunch] GetOneConnection");
527 int errCode;
528 switch (autoLaunchItem.type) {
529 case DBTypeInner::DB_KV:
530 errCode = OpenKvConnection(autoLaunchItem);
531 break;
532 case DBTypeInner::DB_RELATION:
533 errCode = OpenRelationalConnection(autoLaunchItem);
534 break;
535 default:
536 errCode = -E_INVALID_ARGS;
537 }
538 return errCode;
539 }
540
OnlineCallBack(const std::string & device,bool isConnect)541 void AutoLaunch::OnlineCallBack(const std::string &device, bool isConnect)
542 {
543 LOGI("[AutoLaunch] OnlineCallBack device:%s{private}, isConnect:%d", device.c_str(), isConnect);
544 if (!isConnect) {
545 std::lock_guard<std::mutex> autoLock(dataLock_);
546 onlineDevices_.erase(device);
547 return;
548 }
549 {
550 std::lock_guard<std::mutex> autoLock(dataLock_);
551 onlineDevices_.insert(device);
552 }
553
554 int errCode = RuntimeContext::GetInstance()->ScheduleTask([this] { OnlineCallBackTask(); });
555 if (errCode != E_OK) {
556 LOGE("[AutoLaunch] OnlineCallBack ScheduleTask failed");
557 }
558 }
559
OnlineCallBackTask()560 void AutoLaunch::OnlineCallBackTask()
561 {
562 LOGI("[AutoLaunch] OnlineCallBackTask");
563 // <identifier, <userId, AutoLaunchItem>>
564 std::map<std::string, std::map<std::string, AutoLaunchItem>> doOpenMap;
565 GetDoOpenMap(doOpenMap);
566 GetConnInDoOpenMap(doOpenMap);
567 UpdateGlobalMap(doOpenMap);
568 }
569
GetDoOpenMap(std::map<std::string,std::map<std::string,AutoLaunchItem>> & doOpenMap)570 void AutoLaunch::GetDoOpenMap(std::map<std::string, std::map<std::string, AutoLaunchItem>> &doOpenMap)
571 {
572 std::lock_guard<std::mutex> autoLock(dataLock_);
573 LOGI("[AutoLaunch] GetDoOpenMap");
574 for (auto &items : autoLaunchItemMap_) {
575 for (auto &iter : items.second) {
576 bool isDualTupleMode = iter.second.propertiesPtr->GetBoolProp(DBProperties::SYNC_DUAL_TUPLE_MODE, false);
577 if (iter.second.isDisable) {
578 LOGI("[AutoLaunch] GetDoOpenMap this item isDisable do nothing");
579 continue;
580 } else if (iter.second.state != AutoLaunchItemState::IDLE) {
581 LOGI("[AutoLaunch] GetDoOpenMap this item state:%d is not idle do nothing",
582 static_cast<int>(iter.second.state));
583 continue;
584 } else if (iter.second.conn != nullptr) {
585 LOGI("[AutoLaunch] GetDoOpenMap this item is opened");
586 continue;
587 } else if (isDualTupleMode &&
588 !RuntimeContext::GetInstance()->IsSyncerNeedActive(*iter.second.propertiesPtr)) {
589 LOGI("[AutoLaunch] GetDoOpenMap this item no need to open");
590 continue;
591 } else {
592 doOpenMap[items.first][iter.first] = iter.second;
593 iter.second.state = AutoLaunchItemState::IN_COMMUNICATOR_CALL_BACK;
594 LOGI("[AutoLaunch] GetDoOpenMap this item in IN_COMMUNICATOR_CALL_BACK");
595 }
596 }
597 }
598 }
599
GetConnInDoOpenMapInner(std::pair<const std::string,std::map<std::string,AutoLaunchItem>> & items,SemaphoreUtils & sema)600 void AutoLaunch::GetConnInDoOpenMapInner(std::pair<const std::string, std::map<std::string, AutoLaunchItem>> &items,
601 SemaphoreUtils &sema)
602 {
603 for (auto &iter : items.second) {
604 int errCode = RuntimeContext::GetInstance()->ScheduleTask([&sema, &iter, &items, this] {
605 int ret = OpenOneConnection(iter.second);
606 LOGI("[AutoLaunch] GetConnInDoOpenMap GetOneConnection errCode:%d", ret);
607 if (ret != E_OK) { // LCOV_EXCL_BR_LINE
608 sema.SendSemaphore();
609 LOGI("[AutoLaunch] GetConnInDoOpenMap in open thread finish SendSemaphore");
610 return;
611 }
612 ret = RegisterObserverAndLifeCycleCallback(iter.second, items.first, false);
613 if (ret != E_OK) { // LCOV_EXCL_BR_LINE
614 LOGE("[AutoLaunch] GetConnInDoOpenMap failed, we do CloseConnection");
615 TryCloseConnection(iter.second); // if here failed, do nothing
616 iter.second.conn = nullptr;
617 }
618 sema.SendSemaphore();
619 LOGI("[AutoLaunch] GetConnInDoOpenMap in open thread finish SendSemaphore");
620 });
621 if (errCode != E_OK) { // LCOV_EXCL_BR_LINE
622 LOGE("[AutoLaunch] GetConnInDoOpenMap ScheduleTask failed, SendSemaphore");
623 sema.SendSemaphore();
624 }
625 }
626 }
627
GetConnInDoOpenMap(std::map<std::string,std::map<std::string,AutoLaunchItem>> & doOpenMap)628 void AutoLaunch::GetConnInDoOpenMap(std::map<std::string, std::map<std::string, AutoLaunchItem>> &doOpenMap)
629 {
630 LOGI("[AutoLaunch] GetConnInDoOpenMap doOpenMap.size():%zu", doOpenMap.size());
631 if (doOpenMap.empty()) {
632 return;
633 }
634 uint32_t totalSize = 0u;
635 for (auto &items : doOpenMap) {
636 totalSize += items.second.size();
637 }
638 SemaphoreUtils sema(1 - totalSize);
639 for (auto &items : doOpenMap) {
640 GetConnInDoOpenMapInner(items, sema);
641 }
642 LOGI("[AutoLaunch] GetConnInDoOpenMap WaitSemaphore");
643 sema.WaitSemaphore();
644 LOGI("[AutoLaunch] GetConnInDoOpenMap WaitSemaphore ok");
645 }
646
UpdateGlobalMap(std::map<std::string,std::map<std::string,AutoLaunchItem>> & doOpenMap)647 void AutoLaunch::UpdateGlobalMap(std::map<std::string, std::map<std::string, AutoLaunchItem>> &doOpenMap)
648 {
649 std::lock_guard<std::mutex> autoLock(dataLock_);
650 LOGI("[AutoLaunch] UpdateGlobalMap");
651 for (const auto &items : doOpenMap) {
652 for (const auto &iter : items.second) {
653 if (iter.second.conn != nullptr) {
654 autoLaunchItemMap_[items.first][iter.first].conn = iter.second.conn;
655 autoLaunchItemMap_[items.first][iter.first].observerHandle = iter.second.observerHandle;
656 autoLaunchItemMap_[items.first][iter.first].isWriteOpenNotified = false;
657 LOGI("[AutoLaunch] UpdateGlobalMap opened conn update map");
658 }
659 autoLaunchItemMap_[items.first][iter.first].state = AutoLaunchItemState::IDLE;
660 LOGI("[AutoLaunch] UpdateGlobalMap opened conn set state IDLE");
661 }
662 }
663 cv_.notify_all();
664 LOGI("[AutoLaunch] UpdateGlobalMap finish notify_all");
665 }
666
ReceiveUnknownIdentifierCallBackTask(const std::string & identifier,const std::string & userId)667 void AutoLaunch::ReceiveUnknownIdentifierCallBackTask(const std::string &identifier, const std::string &userId)
668 {
669 LOGI("[AutoLaunch] ReceiveUnknownIdentifierCallBackTask identifier=%.6s", STR_TO_HEX(identifier));
670 AutoLaunchItem autoLaunchItem;
671 {
672 std::lock_guard<std::mutex> autoLock(dataLock_);
673 autoLaunchItem = autoLaunchItemMap_[identifier][userId];
674 }
675 int errCode = OpenOneConnection(autoLaunchItem);
676 LOGI("[AutoLaunch] ReceiveUnknownIdentifierCallBack GetOneConnection errCode:%d", errCode);
677 if (autoLaunchItem.conn == nullptr) {
678 std::lock_guard<std::mutex> autoLock(dataLock_);
679 autoLaunchItemMap_[identifier][userId].state = AutoLaunchItemState::IDLE;
680 cv_.notify_all();
681 LOGI("[AutoLaunch] ReceiveUnknownIdentifierCallBackTask set state IDLE");
682 return;
683 }
684 errCode = RegisterObserverAndLifeCycleCallback(autoLaunchItem, identifier, false);
685 if (errCode != E_OK) {
686 LOGE("[AutoLaunch] ReceiveUnknownIdentifierCallBackTask RegisterObserverAndLifeCycleCallback failed");
687 LOGI("[AutoLaunch] ReceiveUnknownIdentifierCallBackTask do CloseConnection");
688 TryCloseConnection(autoLaunchItem); // if here failed, do nothing
689 std::lock_guard<std::mutex> autoLock(dataLock_);
690 autoLaunchItemMap_[identifier][userId].state = AutoLaunchItemState::IDLE;
691 cv_.notify_all();
692 LOGI("[AutoLaunch] ReceiveUnknownIdentifierCallBackTask set state IDLE");
693 return;
694 }
695 std::lock_guard<std::mutex> autoLock(dataLock_);
696 autoLaunchItemMap_[identifier][userId].conn = autoLaunchItem.conn;
697 autoLaunchItemMap_[identifier][userId].observerHandle = autoLaunchItem.observerHandle;
698 autoLaunchItemMap_[identifier][userId].isWriteOpenNotified = false;
699 autoLaunchItemMap_[identifier][userId].state = AutoLaunchItemState::IDLE;
700 cv_.notify_all();
701 LOGI("[AutoLaunch] ReceiveUnknownIdentifierCallBackTask conn opened set state IDLE");
702 }
703
ReceiveUnknownIdentifierCallBack(const LabelType & label,const std::string & originalUserId)704 int AutoLaunch::ReceiveUnknownIdentifierCallBack(const LabelType &label, const std::string &originalUserId)
705 {
706 const std::string identifier(label.begin(), label.end());
707 LOGI("[AutoLaunch] ReceiveUnknownIdentifierCallBack identifier=%.6s", STR_TO_HEX(identifier));
708 // originalUserId size maybe 0
709 bool handleByCallback = false;
710 std::string userId = GetAutoLaunchItemUid(identifier, originalUserId, handleByCallback);
711 if (handleByCallback) {
712 goto EXT;
713 }
714 int errCode;
715 {
716 std::lock_guard<std::mutex> autoLock(dataLock_);
717 if (autoLaunchItemMap_.count(identifier) == 0 || autoLaunchItemMap_[identifier].count(userId) == 0) {
718 LOGI("[AutoLaunch] ReceiveUnknownIdentifierCallBack not find identifier");
719 goto EXT;
720 } else if (autoLaunchItemMap_[identifier][userId].isDisable) {
721 LOGI("[AutoLaunch] ReceiveUnknownIdentifierCallBack isDisable ,do nothing");
722 return -E_NOT_FOUND; // not E_OK is ok for communicator
723 } else if (autoLaunchItemMap_[identifier][userId].conn != nullptr) {
724 LOGI("[AutoLaunch] ReceiveUnknownIdentifierCallBack conn is not nullptr");
725 return E_OK;
726 } else if (autoLaunchItemMap_[identifier][userId].state != AutoLaunchItemState::IDLE) {
727 LOGI("[AutoLaunch] ReceiveUnknownIdentifierCallBack state:%d is not idle, do nothing",
728 static_cast<int>(autoLaunchItemMap_[identifier][userId].state));
729 return E_OK;
730 }
731 autoLaunchItemMap_[identifier][userId].state = AutoLaunchItemState::IN_COMMUNICATOR_CALL_BACK;
732 LOGI("[AutoLaunch] ReceiveUnknownIdentifierCallBack set state IN_COMMUNICATOR_CALL_BACK");
733 }
734
735 errCode = RuntimeContext::GetInstance()->ScheduleTask(
736 [this, identifier, userId] { ReceiveUnknownIdentifierCallBackTask(identifier, userId); });
737 if (errCode != E_OK) {
738 LOGE("[AutoLaunch] ReceiveUnknownIdentifierCallBack ScheduleTask failed");
739 std::lock_guard<std::mutex> autoLock(dataLock_);
740 autoLaunchItemMap_[identifier][userId].state = AutoLaunchItemState::IDLE;
741 }
742 return errCode;
743 EXT:
744 return AutoLaunchExt(identifier, userId);
745 }
746
SetAutoLaunchRequestCallback(const AutoLaunchRequestCallback & callback,DBTypeInner type)747 void AutoLaunch::SetAutoLaunchRequestCallback(const AutoLaunchRequestCallback &callback, DBTypeInner type)
748 {
749 LOGI("[AutoLaunch] SetAutoLaunchRequestCallback type[%d]", static_cast<int>(type));
750 TaskHandle handle = ConcurrentAdapter::ScheduleTaskH([this, callback, type] () mutable {
751 ConcurrentAdapter::AdapterAutoLock(extLock_);
752 ResFinalizer finalizer([this]() { ConcurrentAdapter::AdapterAutoUnLock(extLock_); });
753 if (callback) {
754 autoLaunchRequestCallbackMap_[type] = callback;
755 } else {
756 autoLaunchRequestCallbackMap_.erase(type);
757 }
758 }, nullptr, &autoLaunchRequestCallbackMap_);
759 ADAPTER_WAIT(handle);
760 }
761
AutoLaunchExt(const std::string & identifier,const std::string & userId)762 int AutoLaunch::AutoLaunchExt(const std::string &identifier, const std::string &userId)
763 {
764 AutoLaunchParam param;
765 // for non dual tuple mode, userId is ""
766 param.userId = userId;
767 DBTypeInner openType = DBTypeInner::DB_INVALID;
768 int errCode = ExtAutoLaunchRequestCallBack(identifier, param, openType);
769 if (errCode != E_OK) {
770 return errCode; // not E_OK is ok for communicator
771 }
772
773 std::shared_ptr<DBProperties> ptr;
774 errCode = AutoLaunch::GetAutoLaunchProperties(param, openType, false, ptr);
775 if (errCode != E_OK) {
776 LOGE("[AutoLaunch] AutoLaunchExt param check fail errCode:%d", errCode);
777 if (!param.notifier) {
778 return errCode;
779 }
780 int retCode = RuntimeContext::GetInstance()->ScheduleTask([param] {
781 param.notifier(param.userId, param.appId, param.storeId, INVALID_PARAM);
782 });
783 if (retCode != E_OK) {
784 LOGE("[AutoLaunch] AutoLaunchExt notifier ScheduleTask retCode:%d", retCode);
785 }
786 return errCode;
787 }
788 AutoLaunchItem autoLaunchItem{ptr, param.notifier, param.option.observer, param.option.conflictType,
789 param.option.notifier};
790 autoLaunchItem.isAutoSync = param.option.isAutoSync;
791 autoLaunchItem.type = openType;
792 autoLaunchItem.storeObserver = param.option.storeObserver;
793 errCode = RuntimeContext::GetInstance()->ScheduleTask([this, identifier, userId = param.userId, autoLaunchItem] {
794 AutoLaunchItem item = autoLaunchItem;
795 AutoLaunchExtTask(identifier, userId, item);
796 });
797 if (errCode != E_OK) {
798 LOGE("[AutoLaunch] AutoLaunchExt ScheduleTask errCode:%d", errCode);
799 }
800 return errCode;
801 }
802
AutoLaunchExtTask(const std::string & identifier,const std::string & userId,AutoLaunchItem & autoLaunchItem)803 void AutoLaunch::AutoLaunchExtTask(const std::string &identifier, const std::string &userId,
804 AutoLaunchItem &autoLaunchItem)
805 {
806 {
807 bool isReturn = false;
808 TaskHandle handle = ConcurrentAdapter::ScheduleTaskH([this, &identifier, &userId,
809 &autoLaunchItem, &isReturn] () mutable {
810 ConcurrentAdapter::AdapterAutoLock(extLock_);
811 ResFinalizer finalizer([this]() { ConcurrentAdapter::AdapterAutoUnLock(extLock_); });
812 if (extItemMap_.count(identifier) != 0 && extItemMap_[identifier].count(userId) != 0) {
813 LOGE("[AutoLaunch] extItemMap has this identifier");
814 isReturn = true;
815 return;
816 }
817 extItemMap_[identifier][userId] = autoLaunchItem;
818 }, nullptr, &extItemMap_);
819 ADAPTER_WAIT(handle);
820 if (isReturn) {
821 return;
822 }
823 }
824 bool abort = ChkAutoLaunchAbort(identifier, autoLaunchItem);
825 if (abort) {
826 TaskHandle handle = ConcurrentAdapter::ScheduleTaskH([this, &identifier, &userId] () mutable {
827 ConcurrentAdapter::AdapterAutoLock(extLock_);
828 ResFinalizer finalizer([this]() { ConcurrentAdapter::AdapterAutoUnLock(extLock_); });
829 extItemMap_[identifier].erase(userId);
830 if (extItemMap_[identifier].empty()) {
831 extItemMap_.erase(identifier);
832 }
833 }, nullptr, &extItemMap_);
834 ADAPTER_WAIT(handle);
835 return;
836 }
837 TaskHandle handle = ConcurrentAdapter::ScheduleTaskH([this, &identifier, &userId, &autoLaunchItem] () mutable {
838 ConcurrentAdapter::AdapterAutoLock(extLock_);
839 ResFinalizer finalizer([this]() { ConcurrentAdapter::AdapterAutoUnLock(extLock_); });
840 extItemMap_[identifier][userId] = autoLaunchItem; // Reassign item to prevent it from being erased
841 extItemMap_[identifier][userId].isWriteOpenNotified = false;
842 LOGI("[AutoLaunch] AutoLaunchExtTask ok");
843 }, nullptr, &extItemMap_);
844 ADAPTER_WAIT(handle);
845 }
846
ExtObserverFunc(const KvDBCommitNotifyData & notifyData,const std::string & identifier,const std::string & userId)847 void AutoLaunch::ExtObserverFunc(const KvDBCommitNotifyData ¬ifyData, const std::string &identifier,
848 const std::string &userId)
849 {
850 LOGD("[AutoLaunch] ExtObserverFunc identifier=%.6s", STR_TO_HEX(identifier));
851 AutoLaunchItem autoLaunchItem;
852 AutoLaunchNotifier notifier;
853 {
854 bool isReturn = false;
855 TaskHandle handle = ConcurrentAdapter::ScheduleTaskH([this, &identifier, &userId,
856 &autoLaunchItem, &isReturn] () mutable {
857 ConcurrentAdapter::AdapterAutoLock(extLock_);
858 ResFinalizer finalizer([this]() { ConcurrentAdapter::AdapterAutoUnLock(extLock_); });
859 if (extItemMap_.count(identifier) == 0 || extItemMap_[identifier].count(userId) == 0) {
860 LOGE("[AutoLaunch] ExtObserverFunc this identifier not in map");
861 isReturn = true;
862 return;
863 }
864 autoLaunchItem = extItemMap_[identifier][userId];
865 }, &extItemMap_, nullptr);
866 ADAPTER_WAIT(handle);
867 if (isReturn) {
868 return;
869 }
870 }
871 if (autoLaunchItem.observer != nullptr) {
872 LOGD("[AutoLaunch] do user observer");
873 KvStoreChangedDataImpl data(¬ifyData);
874 autoLaunchItem.observer->OnChange(data);
875 }
876
877 {
878 bool isReturn = false;
879 TaskHandle handle = ConcurrentAdapter::ScheduleTaskH([this, &identifier, &userId, &autoLaunchItem,
880 ¬ifier, &isReturn] () mutable {
881 ConcurrentAdapter::AdapterAutoLock(extLock_);
882 ResFinalizer finalizer([this]() { ConcurrentAdapter::AdapterAutoUnLock(extLock_); });
883 if (extItemMap_.count(identifier) != 0 && extItemMap_[identifier].count(userId) != 0 &&
884 !extItemMap_[identifier][userId].isWriteOpenNotified &&
885 autoLaunchItem.notifier != nullptr) {
886 extItemMap_[identifier][userId].isWriteOpenNotified = true;
887 notifier = autoLaunchItem.notifier;
888 } else {
889 isReturn = true;
890 }
891 }, nullptr, &extItemMap_);
892 ADAPTER_WAIT(handle);
893 if (isReturn) {
894 return;
895 }
896 }
897
898 NotifyAutoLaunch(userId, autoLaunchItem, notifier);
899 }
900
ExtConnectionLifeCycleCallback(const std::string & identifier,const std::string & userId)901 void AutoLaunch::ExtConnectionLifeCycleCallback(const std::string &identifier, const std::string &userId)
902 {
903 LOGI("[AutoLaunch] ExtConnectionLifeCycleCallback identifier=%.6s", STR_TO_HEX(identifier));
904 int errCode = RuntimeContext::GetInstance()->ScheduleTask(
905 [this, identifier, userId] { ExtConnectionLifeCycleCallbackTask(identifier, userId); });
906 if (errCode != E_OK) {
907 LOGE("[AutoLaunch] ExtConnectionLifeCycleCallback ScheduleTask failed");
908 }
909 }
910
ExtConnectionLifeCycleCallbackTask(const std::string & identifier,const std::string & userId)911 void AutoLaunch::ExtConnectionLifeCycleCallbackTask(const std::string &identifier, const std::string &userId)
912 {
913 LOGI("[AutoLaunch] ExtConnectionLifeCycleCallbackTask identifier=%.6s", STR_TO_HEX(identifier));
914 AutoLaunchItem autoLaunchItem;
915 {
916 bool isReturn = false;
917 TaskHandle handle = ConcurrentAdapter::ScheduleTaskH([this, &identifier, &userId,
918 &autoLaunchItem, &isReturn] () mutable {
919 ConcurrentAdapter::AdapterAutoLock(extLock_);
920 ResFinalizer finalizer([this]() { ConcurrentAdapter::AdapterAutoUnLock(extLock_); });
921 if (extItemMap_.count(identifier) == 0 || extItemMap_[identifier].count(userId) == 0) {
922 LOGE("[AutoLaunch] ExtConnectionLifeCycleCallbackTask identifier is not exist!");
923 isReturn = true;
924 return;
925 }
926 autoLaunchItem = extItemMap_[identifier][userId];
927 extItemMap_[identifier].erase(userId);
928 if (extItemMap_[identifier].empty()) {
929 extItemMap_.erase(identifier);
930 }
931 }, nullptr, &extItemMap_);
932 ADAPTER_WAIT(handle);
933 if (isReturn) {
934 return;
935 }
936 }
937 LOGI("[AutoLaunch] ExtConnectionLifeCycleCallbackTask do CloseConnection");
938 TryCloseConnection(autoLaunchItem); // do nothing if failed
939 if (autoLaunchItem.isWriteOpenNotified) {
940 CloseNotifier(autoLaunchItem);
941 }
942 }
943
SetConflictNotifier(AutoLaunchItem & autoLaunchItem)944 int AutoLaunch::SetConflictNotifier(AutoLaunchItem &autoLaunchItem)
945 {
946 if (autoLaunchItem.type != DBTypeInner::DB_KV) {
947 LOGD("[AutoLaunch] Current Type[%d] Not Support ConflictNotifier Now", static_cast<int>(autoLaunchItem.type));
948 return E_OK;
949 }
950
951 IKvDBConnection *kvConn = static_cast<IKvDBConnection *>(autoLaunchItem.conn);
952 int conflictType = autoLaunchItem.conflictType;
953 const KvStoreNbConflictNotifier ¬ifier = autoLaunchItem.conflictNotifier;
954 if (conflictType == 0) {
955 return E_OK;
956 }
957 int errCode;
958 if (!notifier) {
959 errCode = kvConn->SetConflictNotifier(conflictType, nullptr);
960 goto END;
961 }
962
963 errCode = kvConn->SetConflictNotifier(conflictType,
964 [conflictType, notifier](const KvDBCommitNotifyData &data) {
965 int resultCode;
966 const std::list<KvDBConflictEntry> entries = data.GetCommitConflicts(resultCode);
967 if (resultCode != E_OK) {
968 LOGE("Get commit conflicted entries failed:%d!", resultCode);
969 return;
970 }
971
972 for (const auto &entry : entries) {
973 // Prohibit signed numbers to perform bit operations
974 uint32_t entryType = static_cast<uint32_t>(entry.type);
975 uint32_t type = static_cast<uint32_t>(conflictType);
976 if ((entryType & type) != 0) {
977 KvStoreNbConflictDataImpl dataImpl;
978 dataImpl.SetConflictData(entry);
979 notifier(dataImpl);
980 }
981 }
982 });
983
984 END:
985 if (errCode != E_OK) {
986 LOGE("[KvStoreNbDelegate] Register conflict failed:%d!", errCode);
987 }
988 return errCode;
989 }
990
GetAutoLaunchProperties(const AutoLaunchParam & param,const DBTypeInner & openType,bool checkDir,std::shared_ptr<DBProperties> & propertiesPtr)991 int AutoLaunch::GetAutoLaunchProperties(const AutoLaunchParam ¶m, const DBTypeInner &openType, bool checkDir,
992 std::shared_ptr<DBProperties> &propertiesPtr)
993 {
994 int errCode = E_OK;
995 switch (openType) {
996 case DBTypeInner::DB_KV: {
997 propertiesPtr = std::make_shared<KvDBProperties>();
998 std::shared_ptr<KvDBProperties> kvPtr = std::static_pointer_cast<KvDBProperties>(propertiesPtr);
999 errCode = GetAutoLaunchKVProperties(param, kvPtr, checkDir);
1000 break;
1001 }
1002 case DBTypeInner::DB_RELATION: {
1003 propertiesPtr = std::make_shared<RelationalDBProperties>();
1004 std::shared_ptr<RelationalDBProperties> rdbPtr =
1005 std::static_pointer_cast<RelationalDBProperties>(propertiesPtr);
1006 errCode = GetAutoLaunchRelationProperties(param, rdbPtr);
1007 break;
1008 }
1009 default:
1010 return -E_INVALID_ARGS;
1011 }
1012 propertiesPtr->SetIntProp(DBProperties::AUTO_LAUNCH_ID,
1013 static_cast<int>(RuntimeContext::GetInstance()->GenerateSessionId()));
1014 return errCode;
1015 }
1016
GetAutoLaunchKVProperties(const AutoLaunchParam & param,const std::shared_ptr<KvDBProperties> & propertiesPtr,bool checkDir)1017 int AutoLaunch::GetAutoLaunchKVProperties(const AutoLaunchParam ¶m,
1018 const std::shared_ptr<KvDBProperties> &propertiesPtr, bool checkDir)
1019 {
1020 SchemaObject schemaObject;
1021 std::string canonicalDir;
1022 int errCode = ParamCheckUtils::CheckAndTransferAutoLaunchParam(param, checkDir, schemaObject, canonicalDir);
1023 if (errCode != E_OK) {
1024 return errCode;
1025 }
1026
1027 if (param.option.isEncryptedDb) {
1028 propertiesPtr->SetPassword(param.option.cipher, param.option.passwd);
1029 }
1030 propertiesPtr->SetStringProp(KvDBProperties::DATA_DIR, canonicalDir);
1031 propertiesPtr->SetBoolProp(KvDBProperties::CREATE_IF_NECESSARY, param.option.createIfNecessary);
1032 propertiesPtr->SetBoolProp(KvDBProperties::CREATE_DIR_BY_STORE_ID_ONLY, param.option.createDirByStoreIdOnly);
1033 propertiesPtr->SetBoolProp(KvDBProperties::MEMORY_MODE, false);
1034 propertiesPtr->SetBoolProp(KvDBProperties::ENCRYPTED_MODE, param.option.isEncryptedDb);
1035 propertiesPtr->SetIntProp(KvDBProperties::DATABASE_TYPE, KvDBProperties::SINGLE_VER_TYPE_SQLITE);
1036 propertiesPtr->SetIntProp(KvDBProperties::CONFLICT_RESOLVE_POLICY, param.option.conflictResolvePolicy);
1037 propertiesPtr->SetSchema(schemaObject);
1038 if (RuntimeContext::GetInstance()->IsProcessSystemApiAdapterValid()) {
1039 propertiesPtr->SetIntProp(KvDBProperties::SECURITY_LABEL, param.option.secOption.securityLabel);
1040 propertiesPtr->SetIntProp(KvDBProperties::SECURITY_FLAG, param.option.secOption.securityFlag);
1041 }
1042 propertiesPtr->SetBoolProp(DBProperties::COMPRESS_ON_SYNC, param.option.isNeedCompressOnSync);
1043 if (param.option.isNeedCompressOnSync) {
1044 propertiesPtr->SetIntProp(DBProperties::COMPRESSION_RATE,
1045 ParamCheckUtils::GetValidCompressionRate(param.option.compressionRate));
1046 }
1047 propertiesPtr->SetBoolProp(KvDBProperties::SYNC_DUAL_TUPLE_MODE, param.option.syncDualTupleMode);
1048 propertiesPtr->SetBoolProp(KvDBProperties::READ_ONLY_MODE, false);
1049 propertiesPtr->SetBoolProp(KvDBProperties::SHARED_MODE, false);
1050 DbIdParam dbIdParam = { param.appId, param.userId, param.storeId, param.subUser };
1051 DBCommon::SetDatabaseIds(*propertiesPtr, dbIdParam);
1052 return E_OK;
1053 }
1054
GetAutoLaunchRelationProperties(const AutoLaunchParam & param,const std::shared_ptr<RelationalDBProperties> & propertiesPtr)1055 int AutoLaunch::GetAutoLaunchRelationProperties(const AutoLaunchParam ¶m,
1056 const std::shared_ptr<RelationalDBProperties> &propertiesPtr)
1057 {
1058 if (!ParamCheckUtils::CheckStoreParameter({param.userId, param.appId, param.storeId},
1059 false, param.subUser, true)) {
1060 LOGE("[AutoLaunch] CheckStoreParameter is invalid.");
1061 return -E_INVALID_ARGS;
1062 }
1063 propertiesPtr->SetStringProp(RelationalDBProperties::DATA_DIR, param.path);
1064 propertiesPtr->SetIdentifier(param.userId, param.appId, param.storeId, param.subUser);
1065 propertiesPtr->SetBoolProp(RelationalDBProperties::SYNC_DUAL_TUPLE_MODE, param.option.syncDualTupleMode);
1066 propertiesPtr->SetIntProp(RelationalDBProperties::DISTRIBUTED_TABLE_MODE, static_cast<int>(param.option.tableMode));
1067 if (param.option.isEncryptedDb) {
1068 if (!ParamCheckUtils::CheckEncryptedParameter(param.option.cipher, param.option.passwd) ||
1069 param.option.iterateTimes == 0) {
1070 return -E_INVALID_ARGS;
1071 }
1072 propertiesPtr->SetCipherArgs(param.option.cipher, param.option.passwd, param.option.iterateTimes);
1073 }
1074 propertiesPtr->SetBoolProp(DBProperties::COMPRESS_ON_SYNC, param.option.isNeedCompressOnSync);
1075 if (param.option.isNeedCompressOnSync) {
1076 propertiesPtr->SetIntProp(DBProperties::COMPRESSION_RATE,
1077 ParamCheckUtils::GetValidCompressionRate(param.option.compressionRate));
1078 }
1079 return E_OK;
1080 }
1081
ExtAutoLaunchRequestCallBack(const std::string & identifier,AutoLaunchParam & param,DBTypeInner & openType)1082 int AutoLaunch::ExtAutoLaunchRequestCallBack(const std::string &identifier, AutoLaunchParam ¶m,
1083 DBTypeInner &openType)
1084 {
1085 std::map<DBTypeInner, AutoLaunchRequestCallback> callbackMap;
1086 TaskHandle handle = ConcurrentAdapter::ScheduleTaskH([this, &callbackMap] () mutable {
1087 ConcurrentAdapter::AdapterAutoLock(extLock_);
1088 ResFinalizer finalizer([this]() { ConcurrentAdapter::AdapterAutoUnLock(extLock_); });
1089 callbackMap = autoLaunchRequestCallbackMap_;
1090 return E_OK;
1091 }, &autoLaunchRequestCallbackMap_);
1092 ADAPTER_WAIT(handle);
1093 if (callbackMap.empty()) {
1094 LOGI("[AutoLaunch] autoLaunchRequestCallbackMap_ is empty");
1095 return -E_NOT_FOUND;
1096 }
1097 bool needOpen = false;
1098 for (const auto &[type, callBack] : callbackMap) {
1099 needOpen = callBack(identifier, param);
1100 if (needOpen) {
1101 openType = type;
1102 break;
1103 }
1104 }
1105
1106 if (!needOpen) {
1107 LOGI("[AutoLaunch] autoLaunchRequestCallback is not need open");
1108 return -E_NOT_FOUND; // not E_OK is ok for communicator
1109 }
1110 return E_OK;
1111 }
1112
OpenKvConnection(AutoLaunchItem & autoLaunchItem)1113 int AutoLaunch::OpenKvConnection(AutoLaunchItem &autoLaunchItem)
1114 {
1115 std::shared_ptr<KvDBProperties> properties =
1116 std::static_pointer_cast<KvDBProperties>(autoLaunchItem.propertiesPtr);
1117 int errCode = E_OK;
1118 IKvDBConnection *conn = KvDBManager::GetDatabaseConnection(*properties, errCode, false);
1119 if (errCode == -E_ALREADY_OPENED) {
1120 LOGI("[AutoLaunch] GetOneConnection user already getkvstore by self");
1121 } else if (conn == nullptr) {
1122 LOGE("[AutoLaunch] GetOneConnection GetDatabaseConnection failed errCode:%d", errCode);
1123 }
1124 autoLaunchItem.conn = conn;
1125 return errCode;
1126 }
1127
OpenRelationalConnection(AutoLaunchItem & autoLaunchItem)1128 int AutoLaunch::OpenRelationalConnection(AutoLaunchItem &autoLaunchItem)
1129 {
1130 std::shared_ptr<RelationalDBProperties> properties =
1131 std::static_pointer_cast<RelationalDBProperties>(autoLaunchItem.propertiesPtr);
1132 int errCode = E_OK;
1133 auto conn = RelationalStoreInstance::GetDatabaseConnection(*properties, errCode, false);
1134 if (errCode == -E_ALREADY_OPENED) {
1135 LOGI("[AutoLaunch] GetOneConnection user already openstore by self");
1136 } else if (conn == nullptr) {
1137 LOGE("[AutoLaunch] GetOneConnection GetDatabaseConnection failed errCode:%d", errCode);
1138 }
1139 autoLaunchItem.conn = conn;
1140 return errCode;
1141 }
1142
RegisterLifeCycleCallback(AutoLaunchItem & autoLaunchItem,const std::string & identifier,bool isExt)1143 int AutoLaunch::RegisterLifeCycleCallback(AutoLaunchItem &autoLaunchItem, const std::string &identifier,
1144 bool isExt)
1145 {
1146 int errCode = E_OK;
1147 DatabaseLifeCycleNotifier notifier;
1148 if (isExt) {
1149 notifier = [this](const std::string &identifierExt, const std::string &userId) {
1150 ExtConnectionLifeCycleCallback(identifierExt, userId);
1151 };
1152 } else {
1153 notifier = [this](const std::string &identifierExt, const std::string &userId) {
1154 ConnectionLifeCycleCallback(identifierExt, userId);
1155 };
1156 }
1157 switch (autoLaunchItem.type) {
1158 case DBTypeInner::DB_KV:
1159 errCode = static_cast<IKvDBConnection *>(autoLaunchItem.conn)->RegisterLifeCycleCallback(notifier);
1160 break;
1161 case DBTypeInner::DB_RELATION:
1162 errCode =
1163 static_cast<RelationalStoreConnection *>(autoLaunchItem.conn)->RegisterLifeCycleCallback(notifier);
1164 break;
1165 default:
1166 LOGD("[AutoLaunch] Unknown Type[%d]", static_cast<int>(autoLaunchItem.type));
1167 break;
1168 }
1169 return errCode;
1170 }
1171
PragmaAutoSync(AutoLaunchItem & autoLaunchItem)1172 int AutoLaunch::PragmaAutoSync(AutoLaunchItem &autoLaunchItem)
1173 {
1174 int errCode = E_OK;
1175 if (autoLaunchItem.type != DBTypeInner::DB_KV) {
1176 LOGD("[AutoLaunch] Current Type[%d] Not Support AutoSync Now", static_cast<int>(autoLaunchItem.type));
1177 return errCode;
1178 }
1179
1180 bool enAutoSync = autoLaunchItem.isAutoSync;
1181 errCode = static_cast<SyncAbleKvDBConnection *>(autoLaunchItem.conn)->Pragma(PRAGMA_AUTO_SYNC,
1182 static_cast<void *>(&enAutoSync));
1183 if (errCode != E_OK) {
1184 LOGE("[AutoLaunch] PRAGMA_AUTO_SYNC failed, errCode:%d", errCode);
1185 return errCode;
1186 }
1187 LOGI("[AutoLaunch] set PRAGMA_AUTO_SYNC ok, enAutoSync=%d", enAutoSync);
1188 return errCode;
1189 }
1190
TryCloseKvConnection(AutoLaunchItem & autoLaunchItem)1191 void AutoLaunch::TryCloseKvConnection(AutoLaunchItem &autoLaunchItem)
1192 {
1193 LOGI("[AutoLaunch] TryCloseKvConnection");
1194 if (autoLaunchItem.conn == nullptr) {
1195 LOGI("[AutoLaunch] TryCloseKvConnection conn is nullptr, do nothing");
1196 return;
1197 }
1198 IKvDBConnection *kvConn = static_cast<IKvDBConnection *>(autoLaunchItem.conn);
1199 int errCode = kvConn->RegisterLifeCycleCallback(nullptr);
1200 if (errCode != E_OK) {
1201 LOGE("[AutoLaunch] TryCloseKvConnection RegisterLifeCycleCallback failed errCode:%d", errCode);
1202 }
1203 if (autoLaunchItem.observerHandle != nullptr) {
1204 errCode = kvConn->UnRegisterObserver(autoLaunchItem.observerHandle);
1205 if (errCode != E_OK) {
1206 LOGE("[AutoLaunch] TryCloseKvConnection UnRegisterObserver failed errCode:%d", errCode);
1207 }
1208 autoLaunchItem.observerHandle = nullptr;
1209 }
1210 errCode = KvDBManager::ReleaseDatabaseConnection(kvConn);
1211 if (errCode != E_OK) {
1212 LOGE("[AutoLaunch] TryCloseKvConnection ReleaseDatabaseConnection failed errCode:%d", errCode);
1213 }
1214 }
1215
TryCloseRelationConnection(AutoLaunchItem & autoLaunchItem)1216 void AutoLaunch::TryCloseRelationConnection(AutoLaunchItem &autoLaunchItem)
1217 {
1218 LOGI("[AutoLaunch] TryCloseRelationConnection");
1219 if (autoLaunchItem.conn == nullptr) {
1220 LOGI("[AutoLaunch] TryCloseRelationConnection conn is nullptr, do nothing");
1221 return;
1222 }
1223 RelationalStoreConnection *rdbConn = static_cast<RelationalStoreConnection *>(autoLaunchItem.conn);
1224 int errCode = rdbConn->RegisterLifeCycleCallback(nullptr);
1225 if (errCode != E_OK) {
1226 LOGE("[AutoLaunch] TryCloseRelationConnection RegisterLifeCycleCallback failed errCode:%d", errCode);
1227 }
1228 errCode = rdbConn->Close();
1229 if (errCode != E_OK) {
1230 LOGE("[AutoLaunch] TryCloseRelationConnection close connection failed errCode:%d", errCode);
1231 }
1232 }
1233
EraseAutoLaunchItem(const std::string & identifier,const std::string & userId)1234 void AutoLaunch::EraseAutoLaunchItem(const std::string &identifier, const std::string &userId)
1235 {
1236 std::lock_guard<std::mutex> autoLock(dataLock_);
1237 autoLaunchItemMap_[identifier].erase(userId);
1238 if (autoLaunchItemMap_[identifier].empty()) {
1239 autoLaunchItemMap_.erase(identifier);
1240 }
1241 }
1242
NotifyInvalidParam(const AutoLaunchItem & autoLaunchItem)1243 void AutoLaunch::NotifyInvalidParam(const AutoLaunchItem &autoLaunchItem)
1244 {
1245 if (!autoLaunchItem.notifier) {
1246 return;
1247 }
1248 int retCode = RuntimeContext::GetInstance()->ScheduleTask([autoLaunchItem] {
1249 std::string userId = autoLaunchItem.propertiesPtr->GetStringProp(DBProperties::USER_ID, "");
1250 std::string appId = autoLaunchItem.propertiesPtr->GetStringProp(DBProperties::APP_ID, "");
1251 std::string storeId = autoLaunchItem.propertiesPtr->GetStringProp(DBProperties::STORE_ID, "");
1252 autoLaunchItem.notifier(userId, appId, storeId, INVALID_PARAM);
1253 });
1254 if (retCode != E_OK) {
1255 LOGE("[AutoLaunch] AutoLaunchExt notifier ScheduleTask retCode:%d", retCode);
1256 }
1257 }
1258
CheckAutoLaunchRealPath(const AutoLaunchItem & autoLaunchItem)1259 int AutoLaunch::CheckAutoLaunchRealPath(const AutoLaunchItem &autoLaunchItem)
1260 {
1261 std::string canonicalDir;
1262 std::string dataDir = autoLaunchItem.propertiesPtr->GetStringProp(DBProperties::DATA_DIR, "");
1263 if (!ParamCheckUtils::CheckDataDir(dataDir, canonicalDir)) {
1264 LOGE("[AutoLaunch] CheckDataDir is invalid Auto Launch failed.");
1265 NotifyInvalidParam(autoLaunchItem);
1266 return -E_INVALID_ARGS;
1267 }
1268 autoLaunchItem.propertiesPtr->SetStringProp(DBProperties::DATA_DIR, canonicalDir);
1269 return E_OK;
1270 }
1271
Dump(int fd)1272 void AutoLaunch::Dump(int fd)
1273 {
1274 std::lock_guard<std::mutex> lock(dataLock_);
1275 DBDumpHelper::Dump(fd, "\tenableAutoLaunch info [\n");
1276 for (const auto &[label, userItem] : autoLaunchItemMap_) {
1277 DBDumpHelper::Dump(fd, "\t\tlabel = %s, userId = [\n", DBCommon::TransferStringToHex(label).c_str());
1278 for (const auto &entry : userItem) {
1279 DBDumpHelper::Dump(fd, "\t\t\t%s\n", entry.first.c_str());
1280 }
1281 DBDumpHelper::Dump(fd, "\t\t]\n");
1282 }
1283 DBDumpHelper::Dump(fd, "\t]\n");
1284 }
1285
RegisterKvObserver(AutoLaunchItem & autoLaunchItem,const std::string & identifier,bool isExt)1286 int AutoLaunch::RegisterKvObserver(AutoLaunchItem &autoLaunchItem, const std::string &identifier, bool isExt)
1287 {
1288 std::shared_ptr<KvDBProperties> properties =
1289 std::static_pointer_cast<KvDBProperties>(autoLaunchItem.propertiesPtr);
1290 std::string userId = properties->GetStringProp(KvDBProperties::USER_ID, "");
1291 int errCode;
1292 Key key;
1293 KvDBObserverHandle *observerHandle = nullptr;
1294 IKvDBConnection *kvConn = static_cast<IKvDBConnection *>(autoLaunchItem.conn);
1295 observerHandle = kvConn->RegisterObserver(OBSERVER_CHANGES_FOREIGN, key,
1296 [this, isExt, identifier, userId](const KvDBCommitNotifyData ¬ifyData) {
1297 if (isExt) {
1298 ExtObserverFunc(notifyData, identifier, userId);
1299 } else {
1300 ObserverFunc(notifyData, identifier, userId);
1301 }
1302 }, errCode);
1303 if (errCode != E_OK) {
1304 LOGE("[AutoLaunch] RegisterObserver failed:%d!", errCode);
1305 return errCode;
1306 }
1307 autoLaunchItem.observerHandle = observerHandle;
1308 return errCode;
1309 }
1310
RegisterRelationalObserver(AutoLaunchItem & autoLaunchItem,const std::string & identifier,bool isExt)1311 int AutoLaunch::RegisterRelationalObserver(AutoLaunchItem &autoLaunchItem, const std::string &identifier, bool isExt)
1312 {
1313 if (autoLaunchItem.storeObserver == nullptr) {
1314 return E_OK;
1315 }
1316 RelationalStoreConnection *conn = static_cast<RelationalStoreConnection *>(autoLaunchItem.conn);
1317 (void)conn->RegisterObserverAction(autoLaunchItem.storeObserver, [this, autoLaunchItem, identifier](
1318 const std::string &changedDevice, ChangedData &&changedData, bool isChangedData, Origin origin) {
1319 if (isChangedData && autoLaunchItem.storeObserver) {
1320 LOGD("begin to observer on changed data");
1321 autoLaunchItem.storeObserver->OnChange(origin, changedDevice, std::move(changedData));
1322 return;
1323 }
1324 std::string userId;
1325 std::string appId;
1326 std::string storeId;
1327 AutoLaunchOnChange(changedDevice, userId, appId, storeId, autoLaunchItem);
1328 bool isWriteOpenNotified = false;
1329 AutoLaunchNotifier notifier = nullptr;
1330 {
1331 bool isReturn = false;
1332 TaskHandle handle = ConcurrentAdapter::ScheduleTaskH([this, &identifier, &userId,
1333 ¬ifier, &isWriteOpenNotified, &isReturn] () mutable {
1334 ConcurrentAdapter::AdapterAutoLock(extLock_);
1335 ResFinalizer finalizer([this]() { ConcurrentAdapter::AdapterAutoUnLock(extLock_); });
1336 if (extItemMap_.find(identifier) == extItemMap_.end() ||
1337 extItemMap_[identifier].find(userId) == extItemMap_[identifier].end()) {
1338 LOGE("[AutoLaunch] ExtObserverFunc this identifier not in map");
1339 isReturn = true;
1340 return;
1341 }
1342 notifier = extItemMap_[identifier][userId].notifier;
1343 isWriteOpenNotified = extItemMap_[identifier][userId].isWriteOpenNotified;
1344 extItemMap_[identifier][userId].isWriteOpenNotified = true;
1345 }, nullptr, &extItemMap_);
1346 ADAPTER_WAIT(handle);
1347 if (isReturn) {
1348 return;
1349 }
1350 }
1351 if (!isWriteOpenNotified && notifier != nullptr) {
1352 notifier(userId, appId, storeId, WRITE_OPENED);
1353 }
1354 });
1355 return E_OK;
1356 }
1357
CloseConnection(DBTypeInner type,const DBProperties & properties)1358 void AutoLaunch::CloseConnection(DBTypeInner type, const DBProperties &properties)
1359 {
1360 std::string identifier = properties.GetStringProp(DBProperties::IDENTIFIER_DATA, "");
1361 int closeId = properties.GetIntProp(DBProperties::AUTO_LAUNCH_ID, 0);
1362 TaskHandle handle = ConcurrentAdapter::ScheduleTaskH([this, &identifier, &properties,
1363 closeId, type] () mutable {
1364 ConcurrentAdapter::AdapterAutoLock(extLock_);
1365 ResFinalizer finalizer([this]() { ConcurrentAdapter::AdapterAutoUnLock(extLock_); });
1366 auto itemMapIter = extItemMap_.find(identifier);
1367 if (itemMapIter == extItemMap_.end()) {
1368 std::string dualIdentifier = properties.GetStringProp(DBProperties::DUAL_TUPLE_IDENTIFIER_DATA, "");
1369 itemMapIter = extItemMap_.find(dualIdentifier); // Try find conn in dual tuple mode
1370 if (itemMapIter == extItemMap_.end()) {
1371 LOGD("[AutoLaunch] Abort close because not found id");
1372 return;
1373 }
1374 identifier = dualIdentifier;
1375 }
1376 std::string userId = properties.GetStringProp(DBProperties::USER_ID, "");
1377 auto itemIter = itemMapIter->second.find(userId);
1378 if (itemIter == itemMapIter->second.end()) {
1379 LOGD("[AutoLaunch] Abort close because not found user id");
1380 return;
1381 }
1382 if (itemIter->second.propertiesPtr == nullptr) {
1383 LOGD("[AutoLaunch] Abort close because properties is invalid");
1384 return;
1385 }
1386 int targetId = itemIter->second.propertiesPtr->GetIntProp(DBProperties::AUTO_LAUNCH_ID, 0);
1387 if (closeId != 0 && closeId != targetId) {
1388 LOGD("[AutoLaunch] Abort close because connection has been closed");
1389 return;
1390 }
1391 if (itemIter->second.type != type) {
1392 LOGE("[AutoLaunch] Not same DB type for close connection");
1393 return;
1394 }
1395 LOGI("[AutoLaunch] Force close connection");
1396 TryCloseConnection(itemIter->second);
1397 if (itemIter->second.isWriteOpenNotified) {
1398 CloseNotifier(itemIter->second);
1399 }
1400 LOGI("[AutoLaunch] Force close connection finished");
1401 extItemMap_[identifier].erase(userId);
1402 if (extItemMap_[identifier].size() == 0) {
1403 extItemMap_.erase(identifier);
1404 }
1405 }, nullptr, &extItemMap_);
1406 ADAPTER_WAIT(handle);
1407 }
1408
GetAutoLaunchItemUid(const std::string & identifier,const std::string & originalUserId,bool & handleByCallback)1409 std::string AutoLaunch::GetAutoLaunchItemUid(const std::string &identifier, const std::string &originalUserId,
1410 bool &handleByCallback)
1411 {
1412 std::string userId = originalUserId;
1413 std::lock_guard<std::mutex> autoLock(dataLock_);
1414 if (autoLaunchItemMap_.find(identifier) == autoLaunchItemMap_.end()) {
1415 LOGE("[AutoLaunch] miss match in white list");
1416 handleByCallback = true;
1417 return userId;
1418 }
1419 if (originalUserId.empty() && autoLaunchItemMap_[identifier].size() > 1) {
1420 LOGE("[AutoLaunch] normal tuple mode userId larger than one userId");
1421 handleByCallback = true;
1422 return userId;
1423 }
1424 if (originalUserId.empty() && autoLaunchItemMap_[identifier].size() == 1) {
1425 // normal tuple mode
1426 userId = autoLaunchItemMap_[identifier].begin()->first;
1427 return userId;
1428 }
1429 for (const auto &[uid, item]: autoLaunchItemMap_[identifier]) {
1430 if (item.propertiesPtr == nullptr) {
1431 continue;
1432 }
1433 if (!item.propertiesPtr->GetBoolProp(DBProperties::SYNC_DUAL_TUPLE_MODE, false)) {
1434 userId = uid;
1435 break;
1436 }
1437 }
1438 return userId;
1439 }
1440
ChkAutoLaunchAbort(const std::string & identifier,AutoLaunchItem & autoLaunchItem)1441 bool AutoLaunch::ChkAutoLaunchAbort(const std::string &identifier, AutoLaunchItem &autoLaunchItem)
1442 {
1443 bool abort = false;
1444 do {
1445 int errCode = CheckAutoLaunchRealPath(autoLaunchItem);
1446 if (errCode != E_OK) {
1447 abort = true;
1448 break;
1449 }
1450 errCode = OpenOneConnection(autoLaunchItem);
1451 LOGI("[AutoLaunch] AutoLaunchExtTask GetOneConnection errCode:%d", errCode);
1452 if (autoLaunchItem.conn == nullptr) {
1453 abort = true;
1454 break;
1455 }
1456 errCode = RegisterObserverAndLifeCycleCallback(autoLaunchItem, identifier, true);
1457 if (errCode != E_OK) {
1458 LOGE("[AutoLaunch] AutoLaunchExtTask RegisterObserverAndLifeCycleCallback failed");
1459 TryCloseConnection(autoLaunchItem); // if here failed, do nothing
1460 abort = true;
1461 }
1462 } while (false);
1463 return abort;
1464 }
1465
NotifyAutoLaunch(const std::string & userId,AutoLaunchItem & autoLaunchItem,AutoLaunchNotifier & notifier)1466 void AutoLaunch::NotifyAutoLaunch(const std::string &userId, AutoLaunchItem &autoLaunchItem,
1467 AutoLaunchNotifier ¬ifier)
1468 {
1469 std::string appId = autoLaunchItem.propertiesPtr->GetStringProp(KvDBProperties::APP_ID, "");
1470 std::string storeId = autoLaunchItem.propertiesPtr->GetStringProp(KvDBProperties::STORE_ID, "");
1471 int retCode = RuntimeContext::GetInstance()->ScheduleTask([notifier, userId, appId, storeId] {
1472 LOGI("[AutoLaunch] ExtObserverFunc do user notifier WRITE_OPENED");
1473 notifier(userId, appId, storeId, AutoLaunchStatus::WRITE_OPENED);
1474 });
1475 if (retCode != E_OK) {
1476 LOGE("[AutoLaunch] ExtObserverFunc notifier ScheduleTask retCode:%d", retCode);
1477 }
1478 }
1479
AutoLaunchOnChange(const std::string & changedDevice,std::string & userId,std::string & appId,std::string & storeId,AutoLaunchItem autoLaunchItem)1480 void AutoLaunch::AutoLaunchOnChange(const std::string &changedDevice, std::string &userId, std::string &appId,
1481 std::string &storeId, AutoLaunchItem autoLaunchItem)
1482 {
1483 RelationalStoreChangedDataImpl data(changedDevice);
1484 if (autoLaunchItem.propertiesPtr != nullptr) {
1485 userId = autoLaunchItem.propertiesPtr->GetStringProp(KvDBProperties::USER_ID, "");
1486 appId = autoLaunchItem.propertiesPtr->GetStringProp(DBProperties::APP_ID, "");
1487 storeId = autoLaunchItem.propertiesPtr->GetStringProp(DBProperties::STORE_ID, "");
1488 data.SetStoreProperty({ userId, appId, storeId });
1489 }
1490 if (autoLaunchItem.storeObserver) {
1491 LOGD("begin to observer onchange, changedDevice=%s", STR_MASK(changedDevice));
1492 autoLaunchItem.storeObserver->OnChange(data);
1493 }
1494 }
1495 } // namespace DistributedDB
1496