• 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(DBProperties::COMPRESS_ON_SYNC, param.option.isNeedCompressOnSync);
1043     if (param.option.isNeedCompressOnSync) {
1044         propertiesPtr->SetIntProp(DBProperties::COMPRESSION_RATE,
1045             ParamCheckUtils::GetValidCompressionRate(param.option.compressionRate));
1046     }
1047     propertiesPtr->SetBoolProp(KvDBProperties::SYNC_DUAL_TUPLE_MODE, param.option.syncDualTupleMode);
1048     propertiesPtr->SetBoolProp(KvDBProperties::READ_ONLY_MODE, false);
1049     propertiesPtr->SetBoolProp(KvDBProperties::SHARED_MODE, false);
1050     DbIdParam dbIdParam = { param.appId, param.userId, param.storeId, param.subUser };
1051     DBCommon::SetDatabaseIds(*propertiesPtr, dbIdParam);
1052     return E_OK;
1053 }
1054 
GetAutoLaunchRelationProperties(const AutoLaunchParam & param,const std::shared_ptr<RelationalDBProperties> & propertiesPtr)1055 int AutoLaunch::GetAutoLaunchRelationProperties(const AutoLaunchParam &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     propertiesPtr->SetBoolProp(DBProperties::COMPRESS_ON_SYNC, param.option.isNeedCompressOnSync);
1075     if (param.option.isNeedCompressOnSync) {
1076         propertiesPtr->SetIntProp(DBProperties::COMPRESSION_RATE,
1077             ParamCheckUtils::GetValidCompressionRate(param.option.compressionRate));
1078     }
1079     return E_OK;
1080 }
1081 
ExtAutoLaunchRequestCallBack(const std::string & identifier,AutoLaunchParam & param,DBTypeInner & openType)1082 int AutoLaunch::ExtAutoLaunchRequestCallBack(const std::string &identifier, AutoLaunchParam &param,
1083     DBTypeInner &openType)
1084 {
1085     std::map<DBTypeInner, AutoLaunchRequestCallback> callbackMap;
1086     TaskHandle handle = ConcurrentAdapter::ScheduleTaskH([this, &callbackMap] () mutable {
1087         ConcurrentAdapter::AdapterAutoLock(extLock_);
1088         ResFinalizer finalizer([this]() { ConcurrentAdapter::AdapterAutoUnLock(extLock_); });
1089         callbackMap = autoLaunchRequestCallbackMap_;
1090         return E_OK;
1091     }, &autoLaunchRequestCallbackMap_);
1092     ADAPTER_WAIT(handle);
1093     if (callbackMap.empty()) {
1094         LOGI("[AutoLaunch] autoLaunchRequestCallbackMap_ is empty");
1095         return -E_NOT_FOUND;
1096     }
1097     bool needOpen = false;
1098     for (const auto &[type, callBack] : callbackMap) {
1099         needOpen = callBack(identifier, param);
1100         if (needOpen) {
1101             openType = type;
1102             break;
1103         }
1104     }
1105 
1106     if (!needOpen) {
1107         LOGI("[AutoLaunch] autoLaunchRequestCallback is not need open");
1108         return -E_NOT_FOUND; // not E_OK is ok for communicator
1109     }
1110     return E_OK;
1111 }
1112 
OpenKvConnection(AutoLaunchItem & autoLaunchItem)1113 int AutoLaunch::OpenKvConnection(AutoLaunchItem &autoLaunchItem)
1114 {
1115     std::shared_ptr<KvDBProperties> properties =
1116         std::static_pointer_cast<KvDBProperties>(autoLaunchItem.propertiesPtr);
1117     int errCode = E_OK;
1118     IKvDBConnection *conn = KvDBManager::GetDatabaseConnection(*properties, errCode, false);
1119     if (errCode == -E_ALREADY_OPENED) {
1120         LOGI("[AutoLaunch] GetOneConnection user already getkvstore by self");
1121     } else if (conn == nullptr) {
1122         LOGE("[AutoLaunch] GetOneConnection GetDatabaseConnection failed errCode:%d", errCode);
1123     }
1124     autoLaunchItem.conn = conn;
1125     return errCode;
1126 }
1127 
OpenRelationalConnection(AutoLaunchItem & autoLaunchItem)1128 int AutoLaunch::OpenRelationalConnection(AutoLaunchItem &autoLaunchItem)
1129 {
1130     std::shared_ptr<RelationalDBProperties> properties =
1131         std::static_pointer_cast<RelationalDBProperties>(autoLaunchItem.propertiesPtr);
1132     int errCode = E_OK;
1133     auto conn = RelationalStoreInstance::GetDatabaseConnection(*properties, errCode, false);
1134     if (errCode == -E_ALREADY_OPENED) {
1135         LOGI("[AutoLaunch] GetOneConnection user already openstore by self");
1136     } else if (conn == nullptr) {
1137         LOGE("[AutoLaunch] GetOneConnection GetDatabaseConnection failed errCode:%d", errCode);
1138     }
1139     autoLaunchItem.conn = conn;
1140     return errCode;
1141 }
1142 
RegisterLifeCycleCallback(AutoLaunchItem & autoLaunchItem,const std::string & identifier,bool isExt)1143 int AutoLaunch::RegisterLifeCycleCallback(AutoLaunchItem &autoLaunchItem, const std::string &identifier,
1144     bool isExt)
1145 {
1146     int errCode = E_OK;
1147     DatabaseLifeCycleNotifier notifier;
1148     if (isExt) {
1149         notifier = [this](const std::string &identifierExt, const std::string &userId) {
1150             ExtConnectionLifeCycleCallback(identifierExt, userId);
1151         };
1152     } else {
1153         notifier = [this](const std::string &identifierExt, const std::string &userId) {
1154             ConnectionLifeCycleCallback(identifierExt, userId);
1155         };
1156     }
1157     switch (autoLaunchItem.type) {
1158         case DBTypeInner::DB_KV:
1159             errCode = static_cast<IKvDBConnection *>(autoLaunchItem.conn)->RegisterLifeCycleCallback(notifier);
1160             break;
1161         case DBTypeInner::DB_RELATION:
1162             errCode =
1163                 static_cast<RelationalStoreConnection *>(autoLaunchItem.conn)->RegisterLifeCycleCallback(notifier);
1164             break;
1165         default:
1166             LOGD("[AutoLaunch] Unknown Type[%d]", static_cast<int>(autoLaunchItem.type));
1167             break;
1168     }
1169     return errCode;
1170 }
1171 
PragmaAutoSync(AutoLaunchItem & autoLaunchItem)1172 int AutoLaunch::PragmaAutoSync(AutoLaunchItem &autoLaunchItem)
1173 {
1174     int errCode = E_OK;
1175     if (autoLaunchItem.type != DBTypeInner::DB_KV) {
1176         LOGD("[AutoLaunch] Current Type[%d] Not Support AutoSync Now", static_cast<int>(autoLaunchItem.type));
1177         return errCode;
1178     }
1179 
1180     bool enAutoSync = autoLaunchItem.isAutoSync;
1181     errCode = static_cast<SyncAbleKvDBConnection *>(autoLaunchItem.conn)->Pragma(PRAGMA_AUTO_SYNC,
1182         static_cast<void *>(&enAutoSync));
1183     if (errCode != E_OK) {
1184         LOGE("[AutoLaunch]  PRAGMA_AUTO_SYNC failed, errCode:%d", errCode);
1185         return errCode;
1186     }
1187     LOGI("[AutoLaunch] set PRAGMA_AUTO_SYNC ok, enAutoSync=%d", enAutoSync);
1188     return errCode;
1189 }
1190 
TryCloseKvConnection(AutoLaunchItem & autoLaunchItem)1191 void AutoLaunch::TryCloseKvConnection(AutoLaunchItem &autoLaunchItem)
1192 {
1193     LOGI("[AutoLaunch] TryCloseKvConnection");
1194     if (autoLaunchItem.conn == nullptr) {
1195         LOGI("[AutoLaunch] TryCloseKvConnection conn is nullptr, do nothing");
1196         return;
1197     }
1198     IKvDBConnection *kvConn = static_cast<IKvDBConnection *>(autoLaunchItem.conn);
1199     int errCode = kvConn->RegisterLifeCycleCallback(nullptr);
1200     if (errCode != E_OK) {
1201         LOGE("[AutoLaunch] TryCloseKvConnection RegisterLifeCycleCallback failed errCode:%d", errCode);
1202     }
1203     if (autoLaunchItem.observerHandle != nullptr) {
1204         errCode = kvConn->UnRegisterObserver(autoLaunchItem.observerHandle);
1205         if (errCode != E_OK) {
1206             LOGE("[AutoLaunch] TryCloseKvConnection UnRegisterObserver failed errCode:%d", errCode);
1207         }
1208         autoLaunchItem.observerHandle = nullptr;
1209     }
1210     errCode = KvDBManager::ReleaseDatabaseConnection(kvConn);
1211     if (errCode != E_OK) {
1212         LOGE("[AutoLaunch] TryCloseKvConnection ReleaseDatabaseConnection failed errCode:%d", errCode);
1213     }
1214 }
1215 
TryCloseRelationConnection(AutoLaunchItem & autoLaunchItem)1216 void AutoLaunch::TryCloseRelationConnection(AutoLaunchItem &autoLaunchItem)
1217 {
1218     LOGI("[AutoLaunch] TryCloseRelationConnection");
1219     if (autoLaunchItem.conn == nullptr) {
1220         LOGI("[AutoLaunch] TryCloseRelationConnection conn is nullptr, do nothing");
1221         return;
1222     }
1223     RelationalStoreConnection *rdbConn = static_cast<RelationalStoreConnection *>(autoLaunchItem.conn);
1224     int errCode = rdbConn->RegisterLifeCycleCallback(nullptr);
1225     if (errCode != E_OK) {
1226         LOGE("[AutoLaunch] TryCloseRelationConnection RegisterLifeCycleCallback failed errCode:%d", errCode);
1227     }
1228     errCode = rdbConn->Close();
1229     if (errCode != E_OK) {
1230         LOGE("[AutoLaunch] TryCloseRelationConnection close connection failed errCode:%d", errCode);
1231     }
1232 }
1233 
EraseAutoLaunchItem(const std::string & identifier,const std::string & userId)1234 void AutoLaunch::EraseAutoLaunchItem(const std::string &identifier, const std::string &userId)
1235 {
1236     std::lock_guard<std::mutex> autoLock(dataLock_);
1237     autoLaunchItemMap_[identifier].erase(userId);
1238     if (autoLaunchItemMap_[identifier].empty()) {
1239         autoLaunchItemMap_.erase(identifier);
1240     }
1241 }
1242 
NotifyInvalidParam(const AutoLaunchItem & autoLaunchItem)1243 void AutoLaunch::NotifyInvalidParam(const AutoLaunchItem &autoLaunchItem)
1244 {
1245     if (!autoLaunchItem.notifier) {
1246         return;
1247     }
1248     int retCode = RuntimeContext::GetInstance()->ScheduleTask([autoLaunchItem] {
1249         std::string userId = autoLaunchItem.propertiesPtr->GetStringProp(DBProperties::USER_ID, "");
1250         std::string appId = autoLaunchItem.propertiesPtr->GetStringProp(DBProperties::APP_ID, "");
1251         std::string storeId = autoLaunchItem.propertiesPtr->GetStringProp(DBProperties::STORE_ID, "");
1252         autoLaunchItem.notifier(userId, appId, storeId, INVALID_PARAM);
1253     });
1254     if (retCode != E_OK) {
1255         LOGE("[AutoLaunch] AutoLaunchExt notifier ScheduleTask retCode:%d", retCode);
1256     }
1257 }
1258 
CheckAutoLaunchRealPath(const AutoLaunchItem & autoLaunchItem)1259 int AutoLaunch::CheckAutoLaunchRealPath(const AutoLaunchItem &autoLaunchItem)
1260 {
1261     std::string canonicalDir;
1262     std::string dataDir = autoLaunchItem.propertiesPtr->GetStringProp(DBProperties::DATA_DIR, "");
1263     if (!ParamCheckUtils::CheckDataDir(dataDir, canonicalDir)) {
1264         LOGE("[AutoLaunch] CheckDataDir is invalid Auto Launch failed.");
1265         NotifyInvalidParam(autoLaunchItem);
1266         return -E_INVALID_ARGS;
1267     }
1268     autoLaunchItem.propertiesPtr->SetStringProp(DBProperties::DATA_DIR, canonicalDir);
1269     return E_OK;
1270 }
1271 
Dump(int fd)1272 void AutoLaunch::Dump(int fd)
1273 {
1274     std::lock_guard<std::mutex> lock(dataLock_);
1275     DBDumpHelper::Dump(fd, "\tenableAutoLaunch info [\n");
1276     for (const auto &[label, userItem] : autoLaunchItemMap_) {
1277         DBDumpHelper::Dump(fd, "\t\tlabel = %s, userId = [\n", DBCommon::TransferStringToHex(label).c_str());
1278         for (const auto &entry : userItem) {
1279             DBDumpHelper::Dump(fd, "\t\t\t%s\n", entry.first.c_str());
1280         }
1281         DBDumpHelper::Dump(fd, "\t\t]\n");
1282     }
1283     DBDumpHelper::Dump(fd, "\t]\n");
1284 }
1285 
RegisterKvObserver(AutoLaunchItem & autoLaunchItem,const std::string & identifier,bool isExt)1286 int AutoLaunch::RegisterKvObserver(AutoLaunchItem &autoLaunchItem, const std::string &identifier, bool isExt)
1287 {
1288     std::shared_ptr<KvDBProperties> properties =
1289         std::static_pointer_cast<KvDBProperties>(autoLaunchItem.propertiesPtr);
1290     std::string userId = properties->GetStringProp(KvDBProperties::USER_ID, "");
1291     int errCode;
1292     Key key;
1293     KvDBObserverHandle *observerHandle = nullptr;
1294     IKvDBConnection *kvConn = static_cast<IKvDBConnection *>(autoLaunchItem.conn);
1295     observerHandle = kvConn->RegisterObserver(OBSERVER_CHANGES_FOREIGN, key,
1296         [this, isExt, identifier, userId](const KvDBCommitNotifyData &notifyData) {
1297             if (isExt) {
1298                 ExtObserverFunc(notifyData, identifier, userId);
1299             } else {
1300                 ObserverFunc(notifyData, identifier, userId);
1301             }
1302         }, errCode);
1303     if (errCode != E_OK) {
1304         LOGE("[AutoLaunch] RegisterObserver failed:%d!", errCode);
1305         return errCode;
1306     }
1307     autoLaunchItem.observerHandle = observerHandle;
1308     return errCode;
1309 }
1310 
RegisterRelationalObserver(AutoLaunchItem & autoLaunchItem,const std::string & identifier,bool isExt)1311 int AutoLaunch::RegisterRelationalObserver(AutoLaunchItem &autoLaunchItem, const std::string &identifier, bool isExt)
1312 {
1313     if (autoLaunchItem.storeObserver == nullptr) {
1314         return E_OK;
1315     }
1316     RelationalStoreConnection *conn = static_cast<RelationalStoreConnection *>(autoLaunchItem.conn);
1317     (void)conn->RegisterObserverAction(autoLaunchItem.storeObserver, [this, autoLaunchItem, identifier](
1318         const std::string &changedDevice, ChangedData &&changedData, bool isChangedData, Origin origin) {
1319         if (isChangedData && autoLaunchItem.storeObserver) {
1320             LOGD("begin to observer on changed data");
1321             autoLaunchItem.storeObserver->OnChange(origin, changedDevice, std::move(changedData));
1322             return;
1323         }
1324         std::string userId;
1325         std::string appId;
1326         std::string storeId;
1327         AutoLaunchOnChange(changedDevice, userId, appId, storeId, autoLaunchItem);
1328         bool isWriteOpenNotified = false;
1329         AutoLaunchNotifier notifier = nullptr;
1330         {
1331             bool isReturn = false;
1332             TaskHandle handle = ConcurrentAdapter::ScheduleTaskH([this, &identifier, &userId,
1333                 &notifier, &isWriteOpenNotified, &isReturn] () mutable {
1334                 ConcurrentAdapter::AdapterAutoLock(extLock_);
1335                 ResFinalizer finalizer([this]() { ConcurrentAdapter::AdapterAutoUnLock(extLock_); });
1336                 if (extItemMap_.find(identifier) == extItemMap_.end() ||
1337                     extItemMap_[identifier].find(userId) == extItemMap_[identifier].end()) {
1338                     LOGE("[AutoLaunch] ExtObserverFunc this identifier not in map");
1339                     isReturn = true;
1340                     return;
1341                 }
1342                 notifier = extItemMap_[identifier][userId].notifier;
1343                 isWriteOpenNotified = extItemMap_[identifier][userId].isWriteOpenNotified;
1344                 extItemMap_[identifier][userId].isWriteOpenNotified = true;
1345             }, nullptr, &extItemMap_);
1346             ADAPTER_WAIT(handle);
1347             if (isReturn) {
1348                 return;
1349             }
1350         }
1351         if (!isWriteOpenNotified && notifier != nullptr) {
1352             notifier(userId, appId, storeId, WRITE_OPENED);
1353         }
1354     });
1355     return E_OK;
1356 }
1357 
CloseConnection(DBTypeInner type,const DBProperties & properties)1358 void AutoLaunch::CloseConnection(DBTypeInner type, const DBProperties &properties)
1359 {
1360     std::string identifier = properties.GetStringProp(DBProperties::IDENTIFIER_DATA, "");
1361     int closeId = properties.GetIntProp(DBProperties::AUTO_LAUNCH_ID, 0);
1362     TaskHandle handle = ConcurrentAdapter::ScheduleTaskH([this, &identifier, &properties,
1363         closeId, type] () mutable {
1364         ConcurrentAdapter::AdapterAutoLock(extLock_);
1365         ResFinalizer finalizer([this]() { ConcurrentAdapter::AdapterAutoUnLock(extLock_); });
1366         auto itemMapIter = extItemMap_.find(identifier);
1367         if (itemMapIter == extItemMap_.end()) {
1368             std::string dualIdentifier = properties.GetStringProp(DBProperties::DUAL_TUPLE_IDENTIFIER_DATA, "");
1369             itemMapIter = extItemMap_.find(dualIdentifier); // Try find conn in dual tuple mode
1370             if (itemMapIter == extItemMap_.end()) {
1371                 LOGD("[AutoLaunch] Abort close because not found id");
1372                 return;
1373             }
1374             identifier = dualIdentifier;
1375         }
1376         std::string userId = properties.GetStringProp(DBProperties::USER_ID, "");
1377         auto itemIter = itemMapIter->second.find(userId);
1378         if (itemIter == itemMapIter->second.end()) {
1379             LOGD("[AutoLaunch] Abort close because not found user id");
1380             return;
1381         }
1382         if (itemIter->second.propertiesPtr == nullptr) {
1383             LOGD("[AutoLaunch] Abort close because properties is invalid");
1384             return;
1385         }
1386         int targetId = itemIter->second.propertiesPtr->GetIntProp(DBProperties::AUTO_LAUNCH_ID, 0);
1387         if (closeId != 0 && closeId != targetId) {
1388             LOGD("[AutoLaunch] Abort close because connection has been closed");
1389             return;
1390         }
1391         if (itemIter->second.type != type) {
1392             LOGE("[AutoLaunch] Not same DB type for close connection");
1393             return;
1394         }
1395         LOGI("[AutoLaunch] Force close connection");
1396         TryCloseConnection(itemIter->second);
1397         if (itemIter->second.isWriteOpenNotified) {
1398             CloseNotifier(itemIter->second);
1399         }
1400         LOGI("[AutoLaunch] Force close connection finished");
1401         extItemMap_[identifier].erase(userId);
1402         if (extItemMap_[identifier].size() == 0) {
1403             extItemMap_.erase(identifier);
1404         }
1405     }, nullptr, &extItemMap_);
1406     ADAPTER_WAIT(handle);
1407 }
1408 
GetAutoLaunchItemUid(const std::string & identifier,const std::string & originalUserId,bool & handleByCallback)1409 std::string AutoLaunch::GetAutoLaunchItemUid(const std::string &identifier, const std::string &originalUserId,
1410     bool &handleByCallback)
1411 {
1412     std::string userId = originalUserId;
1413     std::lock_guard<std::mutex> autoLock(dataLock_);
1414     if (autoLaunchItemMap_.find(identifier) == autoLaunchItemMap_.end()) {
1415         LOGE("[AutoLaunch] miss match in white list");
1416         handleByCallback = true;
1417         return userId;
1418     }
1419     if (originalUserId.empty() && autoLaunchItemMap_[identifier].size() > 1) {
1420         LOGE("[AutoLaunch] normal tuple mode userId larger than one userId");
1421         handleByCallback = true;
1422         return userId;
1423     }
1424     if (originalUserId.empty() && autoLaunchItemMap_[identifier].size() == 1) {
1425         // normal tuple mode
1426         userId = autoLaunchItemMap_[identifier].begin()->first;
1427         return userId;
1428     }
1429     for (const auto &[uid, item]: autoLaunchItemMap_[identifier]) {
1430         if (item.propertiesPtr == nullptr) {
1431             continue;
1432         }
1433         if (!item.propertiesPtr->GetBoolProp(DBProperties::SYNC_DUAL_TUPLE_MODE, false)) {
1434             userId = uid;
1435             break;
1436         }
1437     }
1438     return userId;
1439 }
1440 
ChkAutoLaunchAbort(const std::string & identifier,AutoLaunchItem & autoLaunchItem)1441 bool AutoLaunch::ChkAutoLaunchAbort(const std::string &identifier, AutoLaunchItem &autoLaunchItem)
1442 {
1443     bool abort = false;
1444     do {
1445         int errCode = CheckAutoLaunchRealPath(autoLaunchItem);
1446         if (errCode != E_OK) {
1447             abort = true;
1448             break;
1449         }
1450         errCode = OpenOneConnection(autoLaunchItem);
1451         LOGI("[AutoLaunch] AutoLaunchExtTask GetOneConnection errCode:%d", errCode);
1452         if (autoLaunchItem.conn == nullptr) {
1453             abort = true;
1454             break;
1455         }
1456         errCode = RegisterObserverAndLifeCycleCallback(autoLaunchItem, identifier, true);
1457         if (errCode != E_OK) {
1458             LOGE("[AutoLaunch] AutoLaunchExtTask RegisterObserverAndLifeCycleCallback failed");
1459             TryCloseConnection(autoLaunchItem); // if here failed, do nothing
1460             abort = true;
1461         }
1462     } while (false);
1463     return abort;
1464 }
1465 
NotifyAutoLaunch(const std::string & userId,AutoLaunchItem & autoLaunchItem,AutoLaunchNotifier & notifier)1466 void AutoLaunch::NotifyAutoLaunch(const std::string &userId, AutoLaunchItem &autoLaunchItem,
1467     AutoLaunchNotifier &notifier)
1468 {
1469     std::string appId = autoLaunchItem.propertiesPtr->GetStringProp(KvDBProperties::APP_ID, "");
1470     std::string storeId = autoLaunchItem.propertiesPtr->GetStringProp(KvDBProperties::STORE_ID, "");
1471     int retCode = RuntimeContext::GetInstance()->ScheduleTask([notifier, userId, appId, storeId] {
1472         LOGI("[AutoLaunch] ExtObserverFunc do user notifier WRITE_OPENED");
1473         notifier(userId, appId, storeId, AutoLaunchStatus::WRITE_OPENED);
1474     });
1475     if (retCode != E_OK) {
1476         LOGE("[AutoLaunch] ExtObserverFunc notifier ScheduleTask retCode:%d", retCode);
1477     }
1478 }
1479 
AutoLaunchOnChange(const std::string & changedDevice,std::string & userId,std::string & appId,std::string & storeId,AutoLaunchItem autoLaunchItem)1480 void AutoLaunch::AutoLaunchOnChange(const std::string &changedDevice, std::string &userId, std::string &appId,
1481     std::string &storeId, AutoLaunchItem autoLaunchItem)
1482 {
1483     RelationalStoreChangedDataImpl data(changedDevice);
1484     if (autoLaunchItem.propertiesPtr != nullptr) {
1485         userId = autoLaunchItem.propertiesPtr->GetStringProp(KvDBProperties::USER_ID, "");
1486         appId = autoLaunchItem.propertiesPtr->GetStringProp(DBProperties::APP_ID, "");
1487         storeId = autoLaunchItem.propertiesPtr->GetStringProp(DBProperties::STORE_ID, "");
1488         data.SetStoreProperty({ userId, appId, storeId });
1489     }
1490     if (autoLaunchItem.storeObserver) {
1491         LOGD("begin to observer onchange, changedDevice=%s", STR_MASK(changedDevice));
1492         autoLaunchItem.storeObserver->OnChange(data);
1493     }
1494 }
1495 } // namespace DistributedDB
1496