1 /*
2 * Copyright (c) 2025 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 "CloudDbProxy"
17
18 #include "cloud_db_proxy.h"
19
20 #include <cerrno>
21 #include <cstring>
22 #include <securec.h>
23
24 #include "db_error.h"
25 #include "log_print.h"
26
27 namespace OHOS::CollaborationEdit {
28 // batchInsert log field index
29 constexpr int32_t LOG_EQUIP_ID_FIELD_IDX = 0;
30 constexpr int32_t LOG_TIMESTAMP_FIELD_IDX = 1;
31 constexpr int32_t LOG_SYNC_LOG_FIELD_IDX = 2;
32 constexpr int32_t LOG_MAX_FIELD_SIZE = 3;
33
34 // query result field index
35 constexpr uint8_t QRY_RSP_EQUIP_ID_IDX = 0u;
36 constexpr uint8_t QRY_RSP_TIMESTAMP_IDX = 1u;
37 constexpr uint8_t QRY_RSP_SYNC_LOG_IDX = 2u;
38 constexpr uint8_t QRY_RSP_CURSOR_IDX = 3u;
39 constexpr uint8_t QRY_MAX_FIELD_SIZE = 4u;
40
41 const std::string EQUIP_ID = "equipId";
42 const std::string CURSOR = "cursor";
43 const std::string SYNC_LOG_EVENT = "syncLogEvent";
44 const std::string TIMESTAMP = "timestamp";
45
46 constexpr int CURSOR_BASE = 10;
47
48 static const std::map<GRD_QueryConditionTypeE, Predicate> PREDICATE_MAP = {
49 {GRD_QUERY_CONDITION_TYPE_EQUAL_TO, EQUAL_TO},
50 {GRD_QUERY_CONDITION_TYPE_NOT_EQUAL_TO, NOT_EQUAL_TO},
51 {GRD_QUERY_CONDITION_TYPE_GREATER_THAN, GREATER_THAN},
52 {GRD_QUERY_CONDITION_TYPE_LESS_THAN, LESS_THAN},
53 {GRD_QUERY_CONDITION_TYPE_GREATER_THAN_OR_EQUAL_TO, GREATER_THAN_OR_EQUAL_TO},
54 {GRD_QUERY_CONDITION_TYPE_LESS_THAN_OR_EQUAL_TO, LESS_THAN_OR_EQUAL_TO}
55 };
56
57 static const std::map<uint8_t, ExtendFieldParser> QRY_RSP_PARSER_MAP = {
58 {QRY_RSP_EQUIP_ID_IDX, CloudDbProxy::EquipIdParseFunc},
59 {QRY_RSP_TIMESTAMP_IDX, CloudDbProxy::TimestampParseFunc},
60 {QRY_RSP_SYNC_LOG_IDX, CloudDbProxy::SyncLogParseFunc},
61 {QRY_RSP_CURSOR_IDX, CloudDbProxy::CursorParseFunc}
62 };
63
~CloudDbProxy()64 CloudDbProxy::~CloudDbProxy()
65 {
66 if (napiCloudDb_ != nullptr) {
67 delete napiCloudDb_;
68 napiCloudDb_ = nullptr;
69 }
70 }
71
SetNapiCloudDb(NapiCloudDb * napiCloudDb)72 void CloudDbProxy::SetNapiCloudDb(NapiCloudDb *napiCloudDb)
73 {
74 napiCloudDb_ = napiCloudDb;
75 }
76
GetCloudRecord(GRD_CloudRecordT & record,CloudParamsAdapterT & paramsAdapter)77 int32_t CloudDbProxy::GetCloudRecord(GRD_CloudRecordT &record, CloudParamsAdapterT ¶msAdapter)
78 {
79 if (record.fieldSize != LOG_MAX_FIELD_SIZE) {
80 LOG_ERROR("[GetCloudRecord] field size go wrong, size = %{public}d", record.fieldSize);
81 return E_INVALID_ARGS;
82 }
83 GRD_CloudFieldT equipId = record.fields[LOG_EQUIP_ID_FIELD_IDX];
84 paramsAdapter.id.assign(static_cast<char *>(equipId.value));
85
86 GRD_CloudFieldT syncLog = record.fields[LOG_SYNC_LOG_FIELD_IDX];
87 paramsAdapter.record.assign(static_cast<uint8_t *>(syncLog.value),
88 static_cast<uint8_t *>(syncLog.value) + syncLog.valueLen);
89
90 GRD_CloudFieldT timestamp = record.fields[LOG_TIMESTAMP_FIELD_IDX];
91 uint64_t *timestampPtr = static_cast<uint64_t *>(timestamp.value);
92 paramsAdapter.timestamp = *timestampPtr;
93 return E_OK;
94 }
95
FreeExtendFields(GRD_CloudFieldT * fields,uint8_t fieldSize)96 void CloudDbProxy::FreeExtendFields(GRD_CloudFieldT *fields, uint8_t fieldSize)
97 {
98 for (uint8_t i = 0; i < fieldSize; i++) {
99 if (fields[i].key != nullptr) {
100 free(fields[i].key);
101 fields[i].key = nullptr;
102 }
103
104 if (fields[i].value != nullptr) {
105 free(fields[i].value);
106 fields[i].value = nullptr;
107 }
108 }
109 }
110
CreateSingleField(GRD_CloudFieldT & field,ExtendRecordFieldT & srcField)111 int32_t CloudDbProxy::CreateSingleField(GRD_CloudFieldT &field, ExtendRecordFieldT &srcField)
112 {
113 void *fieldVal = malloc(srcField.valueLen);
114 if (fieldVal == nullptr) {
115 LOG_ERROR("alloc field value go wrong");
116 return E_OUT_OF_MEMORY;
117 }
118 (void)memset_s(fieldVal, srcField.valueLen, 0, srcField.valueLen);
119 errno_t err = memcpy_s(fieldVal, srcField.valueLen, srcField.valuePtr, srcField.valueLen);
120 if (err != EOK) {
121 LOG_ERROR("copy field value go wrong, err: %{public}d", err);
122 free(fieldVal);
123 return E_MEMORY_OPERATION_ERROR;
124 }
125
126 char *fieldKey = static_cast<char *>(malloc(srcField.fieldName.length() + 1));
127 if (fieldKey == nullptr) {
128 LOG_ERROR("alloc field key go wrong");
129 free(fieldVal);
130 return E_OUT_OF_MEMORY;
131 }
132 err = strcpy_s(fieldKey, srcField.fieldName.length() + 1, srcField.fieldName.c_str());
133 if (err != EOK) {
134 LOG_ERROR("copy field key go wrong, err: %{public}d", err);
135 free(fieldVal);
136 free(fieldKey);
137 return E_MEMORY_OPERATION_ERROR;
138 }
139 field.key = fieldKey;
140 field.value = fieldVal;
141 field.type = srcField.type;
142 field.valueLen = srcField.valueLen;
143 return E_OK;
144 }
145
ParseExtendField(CloudParamsAdapterT & extend,uint32_t index,GRD_CloudRecordT * records,uint32_t maxRecordSize)146 int32_t CloudDbProxy::ParseExtendField(CloudParamsAdapterT &extend, uint32_t index, GRD_CloudRecordT *records,
147 uint32_t maxRecordSize)
148 {
149 if (index >= maxRecordSize) {
150 LOG_ERROR("index is wrong, index:%{public}u, max:%{public}u", index, maxRecordSize);
151 return E_INVALID_ARGS;
152 }
153 size_t fieldSize = sizeof(GRD_CloudFieldT) * QRY_MAX_FIELD_SIZE;
154 records[index].fields = static_cast<GRD_CloudFieldT *>(malloc(fieldSize));
155 if (records[index].fields == nullptr) {
156 LOG_ERROR("alloc for extend field go wrong");
157 return E_OUT_OF_MEMORY;
158 }
159 (void)memset_s(records[index].fields, fieldSize, 0, fieldSize);
160
161 int32_t ret = E_OK;
162 for (uint8_t i = 0; i < QRY_MAX_FIELD_SIZE; i++) {
163 ExtendRecordFieldT field = {};
164 auto it = QRY_RSP_PARSER_MAP.find(i);
165 if (it == QRY_RSP_PARSER_MAP.end()) {
166 LOG_ERROR("field content index is wrong, index=%{public}u", i);
167 FreeExtendFields(records[index].fields, records[index].fieldSize);
168 free(records[index].fields);
169 records[index].fields = nullptr;
170 return E_INVALID_ARGS;
171 }
172 it->second(extend, field);
173
174 ret = CreateSingleField(records[index].fields[i], field);
175 if (ret != E_OK) {
176 LOG_ERROR("create single field go wrong, index=%{public}u, ret=%{public}d", i, ret);
177 FreeExtendFields(records[index].fields, records[index].fieldSize);
178 free(records[index].fields);
179 records[index].fields = nullptr;
180 return ret;
181 }
182 records[index].fieldSize++;
183 }
184 return E_OK;
185 }
186
ParseExtendVector(GRD_CloudParamsT * cloudParams,std::vector<CloudParamsAdapterT> & extends)187 int32_t CloudDbProxy::ParseExtendVector(GRD_CloudParamsT *cloudParams, std::vector<CloudParamsAdapterT> &extends)
188 {
189 if (cloudParams == nullptr) {
190 LOG_ERROR("cloud params is nullptr");
191 return E_INVALID_ARGS;
192 }
193 if (cloudParams->extends == nullptr || *cloudParams->extends != nullptr || cloudParams->extendSize == nullptr) {
194 LOG_ERROR("extend field is nullptr");
195 return E_INVALID_ARGS;
196 }
197 size_t totalSize = sizeof(GRD_CloudRecordT) * extends.size();
198 *cloudParams->extends = (GRD_CloudRecordT *)malloc(totalSize);
199 if (*cloudParams->extends == nullptr) {
200 LOG_ERROR("alloc extends go wrong");
201 return E_INVALID_ARGS;
202 }
203 (void)memset_s(*cloudParams->extends, totalSize, 0, totalSize);
204
205 int32_t ret = E_OK;
206 for (CloudParamsAdapterT extend : extends) {
207 ret = ParseExtendField(extend, *cloudParams->extendSize, *cloudParams->extends, extends.size());
208 if (ret != E_OK) {
209 LOG_ERROR("parse extend field go wrong, ret=%{public}d", ret);
210 free(*cloudParams->extends);
211 *(cloudParams->extendSize) = 0;
212 return ret;
213 }
214 (*cloudParams->extendSize)++;
215 }
216 return E_OK;
217 }
218
GetCloudParamsVector(GRD_CloudParamsT * cloudParams,std::vector<CloudParamsAdapterT> & cloudParamsVector)219 int32_t CloudDbProxy::GetCloudParamsVector(GRD_CloudParamsT *cloudParams,
220 std::vector<CloudParamsAdapterT> &cloudParamsVector)
221 {
222 if (cloudParams == nullptr) {
223 LOG_ERROR("[GetCloudParamsVector] cloud params is nullptr");
224 return E_INVALID_ARGS;
225 }
226 for (uint32_t i = 0; i < cloudParams->recordSize; i++) {
227 CloudParamsAdapterT paramsAdapter;
228 int32_t ret = GetCloudRecord(cloudParams->records[i], paramsAdapter);
229 if (ret != 0) {
230 LOG_ERROR("[GetCloudParamsVector] get cloud record go wrong, ret = %{public}d", ret);
231 return ret;
232 }
233 cloudParamsVector.push_back(paramsAdapter);
234 }
235 return E_OK;
236 }
237
GetQueryParams(GRD_CloudParamsT * cloudParams,std::vector<QueryConditionT> & queryConditions)238 int32_t CloudDbProxy::GetQueryParams(GRD_CloudParamsT *cloudParams, std::vector<QueryConditionT> &queryConditions)
239 {
240 if (cloudParams == nullptr) {
241 LOG_ERROR("cloud params is nullptr");
242 return E_INVALID_ARGS;
243 }
244 if (cloudParams->records == nullptr || cloudParams->recordSize == 0) {
245 LOG_ERROR("record field is wrong");
246 return E_INVALID_ARGS;
247 }
248
249 GRD_CloudRecordT record = cloudParams->records[0];
250 for (uint8_t i = 0; i < record.fieldSize; i++) {
251 GRD_CloudFieldT field = record.fields[i];
252 QueryConditionT condition;
253 condition.fieldName = std::string(field.key);
254 auto it = PREDICATE_MAP.find(field.condition);
255 if (it == PREDICATE_MAP.end()) {
256 LOG_ERROR("predicate is wrong, field name: %{public}s, predicate = %{public}d", field.key, field.condition);
257 queryConditions.clear();
258 return E_INVALID_ARGS;
259 }
260 condition.predicate = it->second;
261 if (condition.fieldName == CURSOR) {
262 if (field.valueLen <= 1) {
263 condition.fieldValue_num = 0;
264 queryConditions.push_back(condition);
265 continue;
266 }
267 condition.fieldValue_num = GetCursorValue(field);
268 if (condition.fieldValue_num < 0) {
269 queryConditions.clear();
270 return E_INVALID_ARGS;
271 }
272 } else if (condition.fieldName == EQUIP_ID) {
273 condition.fieldValue_str = std::string(static_cast<char *>(field.value));
274 } else {
275 LOG_ERROR("condition field name is wrong, field name: %{public}s", field.key);
276 queryConditions.clear();
277 return E_INVALID_ARGS;
278 }
279 queryConditions.push_back(condition);
280 }
281 return E_OK;
282 }
283
GetCursorValue(GRD_CloudFieldT & field)284 int64_t CloudDbProxy::GetCursorValue(GRD_CloudFieldT &field)
285 {
286 int64_t cursor = -1;
287 if (field.value == nullptr) {
288 LOG_ERROR("field value is null");
289 return cursor;
290 }
291 std::string tmpString;
292 tmpString.resize(field.valueLen);
293 errno_t errNo = memcpy_s(&tmpString[0], field.valueLen, field.value, field.valueLen);
294 if (errNo != EOK) {
295 LOG_ERROR("copy cursor value wrong");
296 return cursor;
297 }
298 errno = 0;
299 cursor = std::strtol(tmpString.c_str(), nullptr, CURSOR_BASE);
300 if (errno == EINVAL) {
301 LOG_ERROR("cursor field is not integer");
302 cursor = -1;
303 }
304 if (errno == ERANGE) {
305 LOG_ERROR("cursor is too long");
306 cursor = -1;
307 }
308 return cursor;
309 }
310
CursorParseFunc(CloudParamsAdapterT & extend,ExtendRecordFieldT & destField)311 void CloudDbProxy::CursorParseFunc(CloudParamsAdapterT &extend, ExtendRecordFieldT &destField)
312 {
313 destField.type = GRD_CLOUD_FIELD_TYPE_STRING;
314 destField.fieldName = CURSOR;
315 destField.valueLen = std::to_string(extend.cursor).length() + 1;
316 destField.fieldValue_str = std::to_string(extend.cursor);
317 destField.valuePtr = reinterpret_cast<const void *>(destField.fieldValue_str.c_str());
318 }
319
EquipIdParseFunc(CloudParamsAdapterT & extend,ExtendRecordFieldT & destField)320 void CloudDbProxy::EquipIdParseFunc(CloudParamsAdapterT &extend, ExtendRecordFieldT &destField)
321 {
322 destField.type = GRD_CLOUD_FIELD_TYPE_STRING;
323 destField.fieldName = EQUIP_ID;
324 destField.valueLen = extend.id.length() + 1;
325 destField.valuePtr = reinterpret_cast<const void *>(extend.id.c_str());
326 }
327
TimestampParseFunc(CloudParamsAdapterT & extend,ExtendRecordFieldT & destField)328 void CloudDbProxy::TimestampParseFunc(CloudParamsAdapterT &extend, ExtendRecordFieldT &destField)
329 {
330 destField.type = GRD_CLOUD_FIELD_TYPE_INT;
331 destField.fieldName = TIMESTAMP;
332 destField.valueLen = sizeof(uint64_t);
333 destField.valuePtr = &extend.timestamp;
334 }
335
SyncLogParseFunc(CloudParamsAdapterT & extend,ExtendRecordFieldT & destField)336 void CloudDbProxy::SyncLogParseFunc(CloudParamsAdapterT &extend, ExtendRecordFieldT &destField)
337 {
338 destField.type = GRD_CLOUD_FIELD_TYPE_BYTES;
339 destField.fieldName = SYNC_LOG_EVENT;
340 destField.valueLen = extend.record.size() * sizeof(uint8_t);
341 destField.valuePtr = reinterpret_cast<const void *>(extend.record.data());
342 }
343
BatchInsert(void * cloudDB,GRD_CloudParamsT * cloudParams)344 int32_t CloudDbProxy::BatchInsert(void *cloudDB, GRD_CloudParamsT *cloudParams)
345 {
346 std::vector<CloudParamsAdapterT> cloudParamsVector;
347 int32_t ret = GetCloudParamsVector(cloudParams, cloudParamsVector);
348 if (ret != E_OK) {
349 LOG_ERROR("[BatchInsert] get cloud params go wrong, ret = %{public}d", ret);
350 return ret;
351 }
352 CloudDbProxy *cloudDbProxy = static_cast<CloudDbProxy *>(cloudDB);
353 return cloudDbProxy->napiCloudDb_->BatchInsert(cloudParamsVector);
354 }
355
Query(void * cloudDB,GRD_CloudParamsT * cloudParams)356 int32_t CloudDbProxy::Query(void *cloudDB, GRD_CloudParamsT *cloudParams)
357 {
358 std::vector<QueryConditionT> queryConditions;
359 int32_t ret = GetQueryParams(cloudParams, queryConditions);
360 if (ret != E_OK) {
361 LOG_ERROR("get cloud params go wrong, ret = %{public}d", ret);
362 return CloudErrorCodeE::E_CLOUD_ERROR;
363 }
364 std::vector<CloudParamsAdapterT> extends;
365 CloudDbProxy *cloudDbProxy = static_cast<CloudDbProxy *>(cloudDB);
366 ret = cloudDbProxy->napiCloudDb_->Query(queryConditions, extends);
367 if (ret == CloudErrorCodeE::E_CLOUD_ERROR) {
368 LOG_ERROR("cloudDb query go wrong, ret = %{public}d", ret);
369 return ret;
370 }
371 if (ret == CloudErrorCodeE::E_QUERY_END) {
372 return ret;
373 }
374 // set query result to cloudParams
375 ret = ParseExtendVector(cloudParams, extends);
376 if (ret != E_OK) {
377 LOG_ERROR("cloudDb query parse result go wrong, ret = %{public}d", ret);
378 return CloudErrorCodeE::E_CLOUD_ERROR;
379 }
380 return CloudErrorCodeE::E_CLOUD_OK;
381 }
382
DownloadAsset(void * cloudDB,const char * equipId,char * path)383 int32_t CloudDbProxy::DownloadAsset(void *cloudDB, const char *equipId, char *path)
384 {
385 CloudDbProxy *cloudDbProxy = static_cast<CloudDbProxy *>(cloudDB);
386 std::string equipIdStr(equipId);
387 std::string pathStr(path);
388 return cloudDbProxy->napiCloudDb_->DownloadAsset(equipIdStr, pathStr);
389 }
390
UploadAsset(void * cloudDB,char * path)391 int32_t CloudDbProxy::UploadAsset(void *cloudDB, char *path)
392 {
393 CloudDbProxy *cloudDbProxy = static_cast<CloudDbProxy *>(cloudDB);
394 std::string pathStr(path);
395 return cloudDbProxy->napiCloudDb_->UploadAsset(pathStr);
396 }
397
DeleteAsset(void * cloudDB,char * path)398 int32_t CloudDbProxy::DeleteAsset(void *cloudDB, char *path)
399 {
400 CloudDbProxy *cloudDbProxy = static_cast<CloudDbProxy *>(cloudDB);
401 std::string pathStr(path);
402 return cloudDbProxy->napiCloudDb_->DeleteAsset(pathStr);
403 }
404
DeleteLocalAsset(void * cloudDB,char * path)405 int32_t CloudDbProxy::DeleteLocalAsset(void *cloudDB, char *path)
406 {
407 CloudDbProxy *cloudDbProxy = static_cast<CloudDbProxy *>(cloudDB);
408 std::string pathStr(path);
409 return cloudDbProxy->napiCloudDb_->DeleteLocalAsset(pathStr);
410 }
411
SendAwarenessData(void * cloudDB,const uint8_t * data,uint32_t dataSize)412 int32_t CloudDbProxy::SendAwarenessData(void *cloudDB, const uint8_t *data, uint32_t dataSize)
413 {
414 return E_OK;
415 }
416
Lock(void * cloudDB,uint32_t * lockTimeMs)417 int32_t CloudDbProxy::Lock(void *cloudDB, uint32_t *lockTimeMs)
418 {
419 return E_OK;
420 }
421
UnLock(void * cloudDB)422 int32_t CloudDbProxy::UnLock(void *cloudDB)
423 {
424 return E_OK;
425 }
426
HeartBeat(void * cloudDB)427 int32_t CloudDbProxy::HeartBeat(void *cloudDB)
428 {
429 return E_OK;
430 }
431
Close(void * cloudDB)432 int32_t CloudDbProxy::Close(void *cloudDB)
433 {
434 return E_OK;
435 }
436 } // namespace OHOS::CollaborationEdit
437