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