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