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