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