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