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