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