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