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 ¬ifyData, 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(¬ifyData);
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 ¬ifyData, 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(¬ifyData);
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 ¬ifier = 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 ¶m, 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 ¶m,
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 ¶m,
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 ¶m, 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