1 /*
2 * Copyright (c) 2023 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 #define LOG_TAG "ExtensionCloudServerImpl"
17 #include "cloud_server_impl.h"
18 #include "accesstoken_kit.h"
19 #include "asset_loader_impl.h"
20 #include "cloud_extension.h"
21 #include "cloud_ext_types.h"
22 #include "cloud/subscription.h"
23 #include "error.h"
24 #include "error/general_error.h"
25 #include "extension_util.h"
26 #include "log_print.h"
27 #include "metadata/meta_data_manager.h"
28 #include "utils/anonymous.h"
29
30 namespace OHOS::CloudData {
31 __attribute__((used)) static bool g_isInit = CloudServerImpl::Init();
32 using namespace Security::AccessToken;
33 using DBMetaMgr = DistributedData::MetaDataManager;
34 using Anonymous = DistributedData::Anonymous;
35
Init()36 bool CloudServerImpl::Init()
37 {
38 static CloudServerImpl cloudServerInstance;
39 static std::once_flag onceFlag;
40 std::call_once(onceFlag, [&]() { DistributedData::CloudServer::RegisterCloudInstance(&cloudServerInstance); });
41 return true;
42 }
43
GetServerInfo(int32_t userId,bool needSpaceInfo)44 std::pair<int32_t, DBCloudInfo> CloudServerImpl::GetServerInfo(int32_t userId, bool needSpaceInfo)
45 {
46 DBCloudInfo result;
47 OhCloudExtCloudSync *server = OhCloudExtCloudSyncNew(userId);
48 if (server == nullptr) {
49 return { DBErr::E_ERROR, result };
50 }
51 auto pServer = std::shared_ptr<OhCloudExtCloudSync>(server, [](auto *server) {
52 OhCloudExtCloudSyncFree(server);
53 });
54 OhCloudExtCloudInfo *info = nullptr;
55 auto status = OhCloudExtCloudSyncGetServiceInfo(pServer.get(), &info);
56 if (status != ERRNO_SUCCESS || info == nullptr) {
57 return { DBErr::E_ERROR, result };
58 }
59 auto pInfo = std::shared_ptr<OhCloudExtCloudInfo>(info, [](auto *info) { OhCloudExtCloudInfoFree(info); });
60 status = OhCloudExtCloudInfoGetUser(pInfo.get(), &result.user);
61 if (status != ERRNO_SUCCESS || result.user != userId) {
62 ZLOGE("[IN]user: %{public}d, [OUT]user: %{public}d", userId, result.user);
63 return { DBErr::E_ERROR, result };
64 }
65 unsigned char *id = nullptr;
66 size_t idLen = 0;
67 status = OhCloudExtCloudInfoGetId(pInfo.get(), &id, reinterpret_cast<unsigned int *>(&idLen));
68 if (status != ERRNO_SUCCESS || id == nullptr) {
69 return { DBErr::E_ERROR, result };
70 }
71 result.id = std::string(reinterpret_cast<char *>(id), idLen);
72 if (needSpaceInfo) {
73 unsigned long long totalSpace = 0;
74 OhCloudExtCloudInfoGetTotalSpace(pInfo.get(), &totalSpace);
75 result.totalSpace = totalSpace;
76 unsigned long long remainSpace = 0;
77 OhCloudExtCloudInfoGetRemainSpace(pInfo.get(), &remainSpace);
78 result.remainSpace = remainSpace;
79 }
80 OhCloudExtCloudInfoEnabled(pInfo.get(), &result.enableCloud);
81 OhCloudExtHashMap *briefInfo = nullptr;
82 status = OhCloudExtCloudInfoGetAppInfo(pInfo.get(), &briefInfo);
83 if (status != ERRNO_SUCCESS || briefInfo == nullptr) {
84 return { DBErr::E_ERROR, result };
85 }
86 auto pBriefInfo = std::shared_ptr<OhCloudExtHashMap>(briefInfo, [](auto *briefInfo) {
87 OhCloudExtHashMapFree(briefInfo);
88 });
89 GetAppInfo(pBriefInfo, result);
90 return { DBErr::E_ERROR, result };
91 }
92
GetAppInfo(std::shared_ptr<OhCloudExtHashMap> briefInfo,DBCloudInfo & cloudInfo)93 void CloudServerImpl::GetAppInfo(std::shared_ptr<OhCloudExtHashMap> briefInfo, DBCloudInfo &cloudInfo)
94 {
95 OhCloudExtVector *keys = nullptr;
96 OhCloudExtVector *values = nullptr;
97 auto status = OhCloudExtHashMapIterGetKeyValuePair(briefInfo.get(), &keys, &values);
98 if (status != ERRNO_SUCCESS || keys == nullptr || values == nullptr) {
99 return;
100 }
101 auto pKeys = std::shared_ptr<OhCloudExtVector>(keys, [](auto *keys) { OhCloudExtVectorFree(keys); });
102 auto pValues = std::shared_ptr<OhCloudExtVector>(values, [](auto *values) { OhCloudExtVectorFree(values); });
103 size_t keysLen = 0;
104 OhCloudExtVectorGetLength(pKeys.get(), reinterpret_cast<unsigned int *>(&keysLen));
105 size_t valuesLen = 0;
106 OhCloudExtVectorGetLength(pValues.get(), reinterpret_cast<unsigned int *>(&valuesLen));
107 if (keysLen == 0 || keysLen != valuesLen) {
108 return;
109 }
110 for (size_t i = 0; i < keysLen; i++) {
111 void *key = nullptr;
112 size_t keyLen = 0;
113 status = OhCloudExtVectorGet(pKeys.get(), i, &key, reinterpret_cast<unsigned int *>(&keyLen));
114 if (status != ERRNO_SUCCESS || key == nullptr) {
115 return;
116 }
117 void *value = nullptr;
118 size_t valueLen = 0;
119 status = OhCloudExtVectorGet(pValues.get(), i, &value, reinterpret_cast<unsigned int *>(&valueLen));
120 if (status != ERRNO_SUCCESS || value == nullptr) {
121 return;
122 }
123 std::string bundle(reinterpret_cast<char *>(key), keyLen);
124 OhCloudExtAppInfo *appInfo = reinterpret_cast<OhCloudExtAppInfo *>(value);
125 cloudInfo.apps[bundle] = ExtensionUtil::ConvertAppInfo(appInfo);
126 OhCloudExtAppInfoFree(appInfo);
127 }
128 }
129
GetAppSchema(int32_t userId,const std::string & bundleName)130 std::pair<int32_t, DBSchemaMeta> CloudServerImpl::GetAppSchema(int32_t userId, const std::string &bundleName)
131 {
132 DBSchemaMeta dbSchema;
133 dbSchema.bundleName = bundleName;
134 OhCloudExtCloudSync *server = OhCloudExtCloudSyncNew(userId);
135 if (server == nullptr) {
136 return { DBErr::E_ERROR, dbSchema };
137 }
138 auto pServer = std::shared_ptr<OhCloudExtCloudSync>(server, [](auto *server) {
139 OhCloudExtCloudSyncFree(server);
140 });
141 OhCloudExtSchemaMeta *schema = nullptr;
142 auto status = OhCloudExtCloudSyncGetAppSchema(pServer.get(),
143 reinterpret_cast<const unsigned char *>(bundleName.c_str()), bundleName.size(), &schema);
144 if (status == ERRNO_UNSUPPORTED) {
145 return { DBErr::E_NOT_SUPPORT, dbSchema };
146 }
147 if (status != ERRNO_SUCCESS || schema == nullptr) {
148 return { DBErr::E_ERROR, dbSchema };
149 }
150 auto pSchema = std::shared_ptr<OhCloudExtSchemaMeta>(schema, [](auto *schema) {
151 OhCloudExtSchemaMetaFree(schema);
152 });
153 OhCloudExtSchemaMetaGetVersion(pSchema.get(), &dbSchema.version);
154 OhCloudExtVector *databases = nullptr;
155 status = OhCloudExtSchemaMetaGetDatabases(pSchema.get(), &databases);
156 if (status != ERRNO_SUCCESS || databases == nullptr) {
157 return { DBErr::E_ERROR, dbSchema };
158 }
159 auto pDatabases = std::shared_ptr<OhCloudExtVector>(databases, [](auto *databases) {
160 OhCloudExtVectorFree(databases);
161 });
162 GetDatabases(pDatabases, dbSchema);
163 return { DBErr::E_OK, dbSchema };
164 }
165
GetDatabases(std::shared_ptr<OhCloudExtVector> databases,DBSchemaMeta & dbSchema)166 void CloudServerImpl::GetDatabases(std::shared_ptr<OhCloudExtVector> databases, DBSchemaMeta &dbSchema)
167 {
168 size_t dbsLen = 0;
169 auto status = OhCloudExtVectorGetLength(databases.get(), reinterpret_cast<unsigned int *>(&dbsLen));
170 if (status != ERRNO_SUCCESS || dbsLen == 0) {
171 return;
172 }
173 dbSchema.databases.reserve(dbsLen);
174 for (size_t i = 0; i < dbsLen; i++) {
175 void *database = nullptr;
176 size_t dbLen = 0;
177 status = OhCloudExtVectorGet(databases.get(), i, &database, reinterpret_cast<unsigned int *>(&dbLen));
178 if (status != ERRNO_SUCCESS || database == nullptr) {
179 return;
180 }
181 OhCloudExtDatabase *db = reinterpret_cast<OhCloudExtDatabase *>(database);
182 auto pDb = std::shared_ptr<OhCloudExtDatabase>(db, [](auto *db) { OhCloudExtDatabaseFree(db); });
183 DBMeta dbMeta;
184 unsigned char *name = nullptr;
185 size_t nameLen = 0;
186 OhCloudExtDatabaseGetName(pDb.get(), &name, reinterpret_cast<unsigned int *>(&nameLen));
187 if (name == nullptr) {
188 return;
189 }
190 dbMeta.name = std::string(reinterpret_cast<char *>(name), nameLen);
191 unsigned char *alias = nullptr;
192 size_t aliasLen = 0;
193 OhCloudExtDatabaseGetAlias(pDb.get(), &alias, reinterpret_cast<unsigned int *>(&aliasLen));
194 if (alias == nullptr) {
195 return;
196 }
197 dbMeta.alias = std::string(reinterpret_cast<char *>(alias), aliasLen);
198 OhCloudExtHashMap *tables = nullptr;
199 OhCloudExtDatabaseGetTable(pDb.get(), &tables);
200 if (tables == nullptr) {
201 return;
202 }
203 auto pTables = std::shared_ptr<OhCloudExtHashMap>(tables, [](auto *tables) {
204 OhCloudExtHashMapFree(tables);
205 });
206 GetTables(pTables, dbMeta);
207 dbSchema.databases.emplace_back(std::move(dbMeta));
208 }
209 }
210
GetTables(std::shared_ptr<OhCloudExtHashMap> tables,DBMeta & dbMeta)211 void CloudServerImpl::GetTables(std::shared_ptr<OhCloudExtHashMap> tables, DBMeta &dbMeta)
212 {
213 OhCloudExtVector *keys = nullptr;
214 OhCloudExtVector *values = nullptr;
215 auto status = OhCloudExtHashMapIterGetKeyValuePair(tables.get(), &keys, &values);
216 if (status != ERRNO_SUCCESS || keys == nullptr || values == nullptr) {
217 return;
218 }
219 auto pKeys = std::shared_ptr<OhCloudExtVector>(keys, [](auto *keys) { OhCloudExtVectorFree(keys); });
220 auto pValues = std::shared_ptr<OhCloudExtVector>(values, [](auto *values) { OhCloudExtVectorFree(values); });
221 size_t keysLen = 0;
222 OhCloudExtVectorGetLength(pKeys.get(), reinterpret_cast<unsigned int *>(&keysLen));
223 size_t valuesLen = 0;
224 OhCloudExtVectorGetLength(pValues.get(), reinterpret_cast<unsigned int *>(&valuesLen));
225 if (keysLen == 0 || keysLen != valuesLen) {
226 return;
227 }
228 for (size_t i = 0; i < valuesLen; i++) {
229 void *value = nullptr;
230 size_t valueLen = 0;
231 status = OhCloudExtVectorGet(pValues.get(), i, &value, reinterpret_cast<unsigned int *>(&valueLen));
232 if (status != ERRNO_SUCCESS || value == nullptr) {
233 return;
234 }
235 DBTable dbTable;
236 OhCloudExtTable *table = reinterpret_cast<OhCloudExtTable *>(value);
237 auto pTable = std::shared_ptr<OhCloudExtTable>(table, [](auto *table) { OhCloudExtTableFree(table); });
238 GetTableInfo(pTable, dbTable);
239 OhCloudExtVector *fields = nullptr;
240 status = OhCloudExtTableGetFields(pTable.get(), &fields);
241 if (status != ERRNO_SUCCESS || fields == nullptr) {
242 return;
243 }
244 auto pFields = std::shared_ptr<OhCloudExtVector>(fields, [](auto *fields) {
245 OhCloudExtVectorFree(fields);
246 });
247 GetFields(pFields, dbTable);
248 dbMeta.tables.emplace_back(std::move(dbTable));
249 }
250 }
251
GetTableInfo(std::shared_ptr<OhCloudExtTable> pTable,DBTable & dbTable)252 void CloudServerImpl::GetTableInfo(std::shared_ptr<OhCloudExtTable> pTable, DBTable &dbTable)
253 {
254 unsigned char *tbName = nullptr;
255 size_t tbNameLen = 0;
256 OhCloudExtTableGetName(pTable.get(), &tbName, reinterpret_cast<unsigned int *>(&tbNameLen));
257 if (tbName == nullptr) {
258 return;
259 }
260 dbTable.name = std::string(reinterpret_cast<char *>(tbName), tbNameLen);
261 unsigned char *tbAlias = nullptr;
262 size_t tbAliasLen = 0;
263 OhCloudExtTableGetAlias(pTable.get(), &tbAlias, reinterpret_cast<unsigned int *>(&tbAliasLen));
264 if (tbAlias == nullptr) {
265 return;
266 }
267 dbTable.alias = std::string(reinterpret_cast<char *>(tbAlias), tbAliasLen);
268 }
269
GetFields(std::shared_ptr<OhCloudExtVector> fields,DBTable & dbTable)270 void CloudServerImpl::GetFields(std::shared_ptr<OhCloudExtVector> fields, DBTable &dbTable)
271 {
272 size_t fieldsLen = 0;
273 auto status = OhCloudExtVectorGetLength(fields.get(), reinterpret_cast<unsigned int *>(&fieldsLen));
274 if (status != ERRNO_SUCCESS || fieldsLen == 0) {
275 return;
276 }
277 dbTable.fields.reserve(fieldsLen);
278 for (size_t i = 0; i < fieldsLen; i++) {
279 void *value = nullptr;
280 size_t valueLen = 0;
281 status = OhCloudExtVectorGet(fields.get(), i, &value, reinterpret_cast<unsigned int *>(&valueLen));
282 if (status != ERRNO_SUCCESS || value == nullptr) {
283 return;
284 }
285 OhCloudExtField *field = reinterpret_cast<OhCloudExtField *>(value);
286 auto pField = std::shared_ptr<OhCloudExtField>(field, [](auto *field) { OhCloudExtFieldFree(field); });
287 DBField dbField;
288 unsigned char *colName = nullptr;
289 size_t colLen = 0;
290 OhCloudExtFieldGetColName(pField.get(), &colName, reinterpret_cast<unsigned int *>(&colLen));
291 if (colName == nullptr) {
292 return;
293 }
294 dbField.colName = std::string(reinterpret_cast<char *>(colName), colLen);
295 unsigned char *fdAlias = nullptr;
296 size_t fdAliasLen = 0;
297 OhCloudExtFieldGetAlias(pField.get(), &fdAlias, reinterpret_cast<unsigned int *>(&fdAliasLen));
298 if (fdAlias == nullptr) {
299 return;
300 }
301 dbField.alias = std::string(reinterpret_cast<char *>(fdAlias), fdAliasLen);
302 uint32_t fdtype;
303 OhCloudExtFieldGetTyp(pField.get(), &fdtype);
304 dbField.type = static_cast<int32_t>(fdtype);
305 bool primary = false;
306 OhCloudExtFieldGetPrimary(pField.get(), &primary);
307 dbField.primary = primary;
308 bool nullable = true;
309 OhCloudExtFieldGetNullable(pField.get(), &nullable);
310 dbField.nullable = nullable;
311 dbTable.fields.emplace_back(std::move(dbField));
312 }
313 }
314
Subscribe(int32_t userId,const std::map<std::string,std::vector<DBMeta>> & dbs)315 int32_t CloudServerImpl::Subscribe(int32_t userId, const std::map<std::string, std::vector<DBMeta>> &dbs)
316 {
317 OhCloudExtCloudSync *server = OhCloudExtCloudSyncNew(userId);
318 if (server == nullptr) {
319 return DBErr::E_ERROR;
320 }
321 auto pServer = std::shared_ptr<OhCloudExtCloudSync>(server, [](auto *server) {
322 OhCloudExtCloudSyncFree(server);
323 });
324 OhCloudExtHashMap *databases = OhCloudExtHashMapNew(OhCloudExtRustType::VALUETYPE_VEC_DATABASE);
325 if (databases == nullptr) {
326 return DBErr::E_ERROR;
327 }
328 auto pDatabases = std::shared_ptr<OhCloudExtHashMap>(databases, [](auto *databases) {
329 OhCloudExtHashMapFree(databases);
330 });
331 for (auto &[bundle, db] : dbs) {
332 OhCloudExtVector *database = OhCloudExtVectorNew(OhCloudExtRustType::VALUETYPE_DATABASE);
333 if (database == nullptr) {
334 return DBErr::E_ERROR;
335 }
336 size_t databaseLen = 0;
337 for (auto &item : db) {
338 auto data = ExtensionUtil::Convert(item);
339 if (data.first == nullptr) {
340 return DBErr::E_ERROR;
341 }
342 auto status = OhCloudExtVectorPush(database, data.first, data.second);
343 if (status != ERRNO_SUCCESS) {
344 return DBErr::E_ERROR;
345 }
346 databaseLen += 1;
347 }
348 auto status = OhCloudExtHashMapInsert(pDatabases.get(),
349 const_cast<void *>(reinterpret_cast<const void *>(bundle.c_str())), bundle.size(), database, databaseLen);
350 if (status != ERRNO_SUCCESS) {
351 return DBErr::E_ERROR;
352 }
353 }
354 return DoSubscribe(userId, pServer, pDatabases);
355 }
356
DoSubscribe(int32_t userId,std::shared_ptr<OhCloudExtCloudSync> server,std::shared_ptr<OhCloudExtHashMap> databases)357 int32_t CloudServerImpl::DoSubscribe(int32_t userId, std::shared_ptr<OhCloudExtCloudSync> server,
358 std::shared_ptr<OhCloudExtHashMap> databases)
359 {
360 auto expire = std::chrono::duration_cast<std::chrono::milliseconds>
361 ((std::chrono::system_clock::now() + std::chrono::hours(INTERVAL)).time_since_epoch()).count();
362 OhCloudExtHashMap *relations = nullptr;
363 OhCloudExtVector *errs = nullptr;
364 auto status = OhCloudExtCloudSyncSubscribe(server.get(), databases.get(), expire, &relations, &errs);
365 if (status != ERRNO_SUCCESS || relations == nullptr) {
366 return DBErr::E_ERROR;
367 }
368 auto pRelations = std::shared_ptr<OhCloudExtHashMap>(relations, [](auto *relations) {
369 OhCloudExtHashMapFree(relations);
370 });
371 if (errs != nullptr) {
372 auto pErrs = std::shared_ptr<OhCloudExtVector>(errs, [](auto *errs) { OhCloudExtVectorFree(errs); });
373 size_t errsLen = 0;
374 status = OhCloudExtVectorGetLength(pErrs.get(), reinterpret_cast<unsigned int *>(&errsLen));
375 if (status != ERRNO_SUCCESS || errsLen == 0) {
376 return DBErr::E_ERROR;
377 }
378 for (size_t i = 0; i < errsLen; i++) {
379 void *value = nullptr;
380 size_t valueLen = 0;
381 status = OhCloudExtVectorGet(pErrs.get(), i, &value, reinterpret_cast<unsigned int *>(&valueLen));
382 if (status != ERRNO_SUCCESS || value == nullptr) {
383 return DBErr::E_ERROR;
384 }
385 auto err = *reinterpret_cast<int *>(value);
386 if (err != ERRNO_SUCCESS) {
387 ZLOGE("sub fail, user:%{public}d, err:%{public}d", userId, err);
388 return DBErr::E_ERROR;
389 }
390 }
391 }
392 return SaveSubscription(userId, pRelations, server);
393 }
394
SaveSubscription(int32_t userId,std::shared_ptr<OhCloudExtHashMap> relations,std::shared_ptr<OhCloudExtCloudSync> server)395 int32_t CloudServerImpl::SaveSubscription(int32_t userId, std::shared_ptr<OhCloudExtHashMap> relations,
396 std::shared_ptr<OhCloudExtCloudSync> server)
397 {
398 OhCloudExtCloudInfo *info = nullptr;
399 auto status = OhCloudExtCloudSyncGetServiceInfo(server.get(), &info);
400 if (status != ERRNO_SUCCESS || info == nullptr) {
401 return DBErr::E_ERROR;
402 }
403 auto pInfo = std::shared_ptr<OhCloudExtCloudInfo>(info, [](auto *info) { OhCloudExtCloudInfoFree(info); });
404 unsigned char *id = nullptr;
405 size_t idLen = 0;
406 status = OhCloudExtCloudInfoGetId(pInfo.get(), &id, reinterpret_cast<unsigned int *>(&idLen));
407 if (status != ERRNO_SUCCESS || id == nullptr) {
408 return DBErr::E_ERROR;
409 }
410 std::string accountId(reinterpret_cast<char *>(id), idLen);
411 DBSub sub;
412 sub.userId = userId;
413 DBMetaMgr::GetInstance().LoadMeta(sub.GetKey(), sub, true);
414 if (!sub.id.empty() && sub.id != accountId) {
415 ZLOGE("diff id, [meta]id:%{public}s, [server]id:%{public}s", Anonymous::Change(sub.id).c_str(),
416 Anonymous::Change(accountId).c_str());
417 return DBErr::E_OK;
418 }
419 sub.id = accountId;
420 OhCloudExtVector *keys = nullptr;
421 OhCloudExtVector *values = nullptr;
422 status = OhCloudExtHashMapIterGetKeyValuePair(relations.get(), &keys, &values);
423 if (status != ERRNO_SUCCESS || keys == nullptr || values == nullptr) {
424 return DBErr::E_ERROR;
425 }
426 auto pKeys = std::shared_ptr<OhCloudExtVector>(keys, [](auto *keys) { OhCloudExtVectorFree(keys); });
427 auto pValues = std::shared_ptr<OhCloudExtVector>(values, [](auto *values) { OhCloudExtVectorFree(values); });
428 if (SaveRelation(pKeys, pValues, sub) != DBErr::E_OK) {
429 return DBErr::E_ERROR;
430 }
431 DBMetaMgr::GetInstance().SaveMeta(sub.GetKey(), sub, true);
432 return DBErr::E_OK;
433 }
434
SaveRelation(std::shared_ptr<OhCloudExtVector> keys,std::shared_ptr<OhCloudExtVector> values,DBSub & sub)435 int32_t CloudServerImpl::SaveRelation(std::shared_ptr<OhCloudExtVector> keys,
436 std::shared_ptr<OhCloudExtVector> values, DBSub &sub)
437 {
438 size_t valuesLen = 0;
439 auto status = OhCloudExtVectorGetLength(values.get(), reinterpret_cast<unsigned int *>(&valuesLen));
440 if (status != ERRNO_SUCCESS || valuesLen == 0) {
441 return DBErr::E_ERROR;
442 }
443 for (size_t i = 0; i < valuesLen; i++) {
444 void *value = nullptr;
445 size_t valueLen = 0;
446 OhCloudExtVectorGet(values.get(), i, &value, reinterpret_cast<unsigned int *>(&valueLen));
447 if (value == nullptr) {
448 return DBErr::E_ERROR;
449 }
450 OhCloudExtRelationSet *relationSet = reinterpret_cast<OhCloudExtRelationSet *>(value);
451 auto pRelationSet = std::shared_ptr<OhCloudExtRelationSet>(relationSet, [](auto *relationSet) {
452 OhCloudExtRelationSetFree(relationSet);
453 });
454 unsigned char *bundle = nullptr;
455 size_t bundleLen = 0;
456 OhCloudExtRelationSetGetBundleName(pRelationSet.get(), &bundle, reinterpret_cast<unsigned int *>(&bundleLen));
457 if (bundle == nullptr) {
458 return DBErr::E_ERROR;
459 }
460 unsigned long long expire = 0;
461 status = OhCloudExtRelationSetGetExpireTime(pRelationSet.get(), &expire);
462 if (status != ERRNO_SUCCESS || expire == 0) {
463 return DBErr::E_ERROR;
464 }
465 std::string bundleName(reinterpret_cast<char *>(bundle), bundleLen);
466 sub.expiresTime[bundleName] = static_cast<uint64_t>(expire);
467 OhCloudExtHashMap *relations = nullptr;
468 status = OhCloudExtRelationSetGetRelations(pRelationSet.get(), &relations);
469 if (status != ERRNO_SUCCESS || relations == nullptr) {
470 return DBErr::E_ERROR;
471 }
472 auto pRelations = std::shared_ptr<OhCloudExtHashMap>(relations, [](auto *relations) {
473 OhCloudExtHashMapFree(relations);
474 });
475 DBRelation dbRelation;
476 dbRelation.id = sub.id;
477 dbRelation.bundleName = bundleName;
478 if (GetRelation(pRelations, dbRelation) != DBErr::E_OK) {
479 return DBErr::E_ERROR;
480 }
481 DBMetaMgr::GetInstance().SaveMeta(sub.GetRelationKey(bundleName), dbRelation, true);
482 }
483 return DBErr::E_OK;
484 }
485
GetRelation(std::shared_ptr<OhCloudExtHashMap> relations,DBRelation & dbRelation)486 int32_t CloudServerImpl::GetRelation(std::shared_ptr<OhCloudExtHashMap> relations, DBRelation &dbRelation)
487 {
488 OhCloudExtVector *keys = nullptr;
489 OhCloudExtVector *values = nullptr;
490 auto status = OhCloudExtHashMapIterGetKeyValuePair(relations.get(), &keys, &values);
491 if (status != ERRNO_SUCCESS || keys == nullptr || values == nullptr) {
492 return DBErr::E_ERROR;
493 }
494 auto pKeys = std::shared_ptr<OhCloudExtVector>(keys, [](auto *keys) { OhCloudExtVectorFree(keys); });
495 auto pValues = std::shared_ptr<OhCloudExtVector>(values, [](auto *values) { OhCloudExtVectorFree(values); });
496 size_t keysLen = 0;
497 OhCloudExtVectorGetLength(pKeys.get(), reinterpret_cast<unsigned int *>(&keysLen));
498 size_t valuesLen = 0;
499 OhCloudExtVectorGetLength(pValues.get(), reinterpret_cast<unsigned int *>(&valuesLen));
500 if (keysLen == 0 || keysLen != valuesLen) {
501 return DBErr::E_ERROR;
502 }
503 for (size_t i = 0; i < keysLen; i++) {
504 void *dbName = nullptr;
505 size_t dbNameLen = 0;
506 status = OhCloudExtVectorGet(pKeys.get(), i, &dbName, reinterpret_cast<unsigned int *>(&dbNameLen));
507 if (status != ERRNO_SUCCESS || dbName == nullptr) {
508 return DBErr::E_ERROR;
509 }
510 std::string databaseName(reinterpret_cast<char *>(dbName), dbNameLen);
511 void *subId = nullptr;
512 size_t subIdLen = 0;
513 status = OhCloudExtVectorGet(pValues.get(), i, &subId, reinterpret_cast<unsigned int *>(&subIdLen));
514 if (status != ERRNO_SUCCESS || subId == nullptr) {
515 return DBErr::E_ERROR;
516 }
517 uint64_t subscribeId = *reinterpret_cast<uint64_t *>(subId);
518 dbRelation.relations[std::move(databaseName)] = std::to_string(subscribeId);
519 }
520 return DBErr::E_OK;
521 }
522
Unsubscribe(int32_t userId,const std::map<std::string,std::vector<DBMeta>> & dbs)523 int32_t CloudServerImpl::Unsubscribe(int32_t userId, const std::map<std::string, std::vector<DBMeta>> &dbs)
524 {
525 DBSub sub;
526 sub.userId = userId;
527 DBMetaMgr::GetInstance().LoadMeta(sub.GetKey(), sub, true);
528 if (sub.id.empty()) {
529 return DBErr::E_OK;
530 }
531 OhCloudExtCloudSync *server = OhCloudExtCloudSyncNew(userId);
532 if (server == nullptr) {
533 return DBErr::E_ERROR;
534 }
535 auto pServer = std::shared_ptr<OhCloudExtCloudSync>(server, [](auto *server) { OhCloudExtCloudSyncFree(server); });
536 std::vector<std::string> bundles;
537 OhCloudExtHashMap *subs = OhCloudExtHashMapNew(OhCloudExtRustType::VALUETYPE_VEC_STRING);
538 if (subs == nullptr) {
539 return DBErr::E_ERROR;
540 }
541 auto pSubs = std::shared_ptr<OhCloudExtHashMap>(subs, [](auto *subs) { OhCloudExtHashMapFree(subs); });
542 for (auto &[bundle, databases] : dbs) {
543 DBRelation dbRelation;
544 DBMetaMgr::GetInstance().LoadMeta(DBSub::GetRelationKey(userId, bundle), dbRelation, true);
545 OhCloudExtVector *relation = OhCloudExtVectorNew(OhCloudExtRustType::VALUETYPE_U32);
546 if (relation == nullptr) {
547 return DBErr::E_ERROR;
548 }
549 size_t relationLen = 0;
550 for (auto &database : databases) {
551 auto it = dbRelation.relations.find(database.name);
552 if (it == dbRelation.relations.end()) {
553 continue;
554 }
555 uint32_t subId = static_cast<uint32_t>(std::atoi(it->second.c_str()));
556 if (OhCloudExtVectorPush(relation, &subId, sizeof(uint32_t)) != ERRNO_SUCCESS) {
557 return DBErr::E_ERROR;
558 }
559 relationLen += 1;
560 }
561 auto status = OhCloudExtHashMapInsert(pSubs.get(),
562 const_cast<void *>(reinterpret_cast<const void *>(bundle.c_str())), bundle.size(), relation, relationLen);
563 if (status != ERRNO_SUCCESS) {
564 return DBErr::E_ERROR;
565 }
566 bundles.emplace_back(bundle);
567 }
568 if (DoUnsubscribe(pServer, pSubs, bundles, sub) != DBErr::E_OK) {
569 return DBErr::E_ERROR;
570 }
571 DBMetaMgr::GetInstance().SaveMeta(sub.GetKey(), sub, true);
572 return DBErr::E_OK;
573 }
574
DoUnsubscribe(std::shared_ptr<OhCloudExtCloudSync> server,std::shared_ptr<OhCloudExtHashMap> relations,const std::vector<std::string> & bundles,DBSub & sub)575 int32_t CloudServerImpl::DoUnsubscribe(std::shared_ptr<OhCloudExtCloudSync> server,
576 std::shared_ptr<OhCloudExtHashMap> relations, const std::vector<std::string> &bundles, DBSub &sub)
577 {
578 OhCloudExtVector *errs = nullptr;
579 auto status = OhCloudExtCloudSyncUnsubscribe(server.get(), relations.get(), &errs);
580 if (status != ERRNO_SUCCESS) {
581 return DBErr::E_ERROR;
582 }
583 if (errs != nullptr) {
584 auto pErrs = std::shared_ptr<OhCloudExtVector>(errs, [](auto *errs) { OhCloudExtVectorFree(errs); });
585 size_t errsLen = 0;
586 OhCloudExtVectorGetLength(pErrs.get(), reinterpret_cast<unsigned int *>(&errsLen));
587 if (errsLen != bundles.size()) {
588 return DBErr::E_ERROR;
589 }
590 for (size_t i = 0; i < errsLen; i++) {
591 void *value = nullptr;
592 size_t valueLen = 0;
593 status = OhCloudExtVectorGet(pErrs.get(), i, &value, reinterpret_cast<unsigned int *>(&valueLen));
594 if (status != ERRNO_SUCCESS || value == nullptr) {
595 return DBErr::E_ERROR;
596 }
597 int err = *reinterpret_cast<int *>(value);
598 if (err != ERRNO_SUCCESS) {
599 continue;
600 }
601 sub.expiresTime.erase(bundles[i]);
602 DBMetaMgr::GetInstance().DelMeta(sub.GetRelationKey(bundles[i]), true);
603 }
604 } else {
605 for (size_t i = 0; i < bundles.size(); i++) {
606 sub.expiresTime.erase(bundles[i]);
607 DBMetaMgr::GetInstance().DelMeta(sub.GetRelationKey(bundles[i]), true);
608 }
609 }
610 return DBErr::E_OK;
611 }
612
ConnectAssetLoader(uint32_t tokenId,const DBMeta & dbMeta)613 std::shared_ptr<DBAssetLoader> CloudServerImpl::ConnectAssetLoader(uint32_t tokenId, const DBMeta &dbMeta)
614 {
615 if (AccessTokenKit::GetTokenTypeFlag(tokenId) != TOKEN_HAP) {
616 return nullptr;
617 }
618 HapTokenInfo hapInfo;
619 if (AccessTokenKit::GetHapTokenInfo(tokenId, hapInfo) != RET_SUCCESS) {
620 return nullptr;
621 }
622 auto data = ExtensionUtil::Convert(dbMeta);
623 if (data.first == nullptr) {
624 return nullptr;
625 }
626 OhCloudExtCloudAssetLoader *loader = OhCloudExtCloudAssetLoaderNew(hapInfo.userID,
627 reinterpret_cast<const unsigned char *>(hapInfo.bundleName.c_str()),
628 hapInfo.bundleName.size(), data.first);
629 return loader != nullptr ? std::make_shared<AssetLoaderImpl>(loader) : nullptr;
630 }
631
ConnectAssetLoader(const std::string & bundleName,int user,const DBMeta & dbMeta)632 std::shared_ptr<DBAssetLoader> CloudServerImpl::ConnectAssetLoader(
633 const std::string &bundleName, int user, const DBMeta &dbMeta)
634 {
635 auto data = ExtensionUtil::Convert(dbMeta);
636 if (data.first == nullptr) {
637 return nullptr;
638 }
639 OhCloudExtCloudAssetLoader *loader = OhCloudExtCloudAssetLoaderNew(
640 user, reinterpret_cast<const unsigned char *>(bundleName.c_str()), bundleName.size(), data.first);
641 return loader != nullptr ? std::make_shared<AssetLoaderImpl>(loader) : nullptr;
642 }
643
ConnectCloudDB(uint32_t tokenId,const DBMeta & dbMeta)644 std::shared_ptr<DBCloudDB> CloudServerImpl::ConnectCloudDB(uint32_t tokenId, const DBMeta &dbMeta)
645 {
646 if (AccessTokenKit::GetTokenTypeFlag(tokenId) != TOKEN_HAP) {
647 return nullptr;
648 }
649 HapTokenInfo hapInfo;
650 if (AccessTokenKit::GetHapTokenInfo(tokenId, hapInfo) != RET_SUCCESS) {
651 return nullptr;
652 }
653 auto data = ExtensionUtil::Convert(dbMeta);
654 if (data.first == nullptr) {
655 return nullptr;
656 }
657 OhCloudExtCloudDatabase *cloudDb = OhCloudExtCloudDbNew(hapInfo.userID,
658 reinterpret_cast<const unsigned char *>(hapInfo.bundleName.c_str()),
659 hapInfo.bundleName.size(), data.first);
660 return cloudDb != nullptr ? std::make_shared<CloudDbImpl>(cloudDb) : nullptr;
661 }
662
ConnectCloudDB(const std::string & bundleName,int user,const DBMeta & dbMeta)663 std::shared_ptr<DBCloudDB> CloudServerImpl::ConnectCloudDB(
664 const std::string &bundleName, int user, const DBMeta &dbMeta)
665 {
666 auto data = ExtensionUtil::Convert(dbMeta);
667 if (data.first == nullptr) {
668 return nullptr;
669 }
670 OhCloudExtCloudDatabase *cloudDb = OhCloudExtCloudDbNew(
671 user, reinterpret_cast<const unsigned char *>(bundleName.c_str()), bundleName.size(), data.first);
672 return cloudDb != nullptr ? std::make_shared<CloudDbImpl>(cloudDb) : nullptr;
673 }
674 } // namespace OHOS::CloudData