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