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