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 #include "cloud_disk_data_handler.h"
17
18 #include <cwchar>
19 #include <dirent.h>
20 #include <fcntl.h>
21 #include <map>
22 #include <string>
23 #include <sys/ioctl.h>
24 #include <sys/stat.h>
25 #include <tuple>
26 #include <unistd.h>
27 #include "cloud_disk_data_const.h"
28 #include "clouddisk_db_const.h"
29 #include "cloud_file_utils.h"
30 #include "data_sync_const.h"
31 #include "dfs_error.h"
32 #include "directory_ex.h"
33 #include "dk_record.h"
34 #include "errors.h"
35 #include "file_column.h"
36 #include "sandbox_helper.h"
37 #include "utils_log.h"
38
39 namespace OHOS {
40 namespace FileManagement {
41 namespace CloudSync {
42 using namespace std;
43 using namespace NativeRdb;
44 using namespace DriveKit;
45 using namespace CloudDisk;
46 using namespace Media;
47 using FC = CloudDisk::FileColumn;
CloudDiskDataHandler(int32_t userId,const string & bundleName,std::shared_ptr<RdbStore> rdb,shared_ptr<bool> stopFlag)48 CloudDiskDataHandler::CloudDiskDataHandler(int32_t userId, const string &bundleName,
49 std::shared_ptr<RdbStore> rdb, shared_ptr<bool> stopFlag)
50 : RdbDataHandler(userId, bundleName, FC::FILES_TABLE, rdb, stopFlag), userId_(userId), bundleName_(bundleName)
51 {
52 }
GetFetchCondition(FetchCondition & cond)53 void CloudDiskDataHandler::GetFetchCondition(FetchCondition &cond)
54 {
55 cond.limitRes = PULL_LIMIT_SIZE;
56 cond.recordType = recordType_;
57 cond.desiredKeys = desiredKeys_;
58 cond.fullKeys = desiredKeys_;
59 }
UTCTimeMilliSeconds()60 int64_t CloudDiskDataHandler::UTCTimeMilliSeconds()
61 {
62 struct timespec t;
63 clock_gettime(CLOCK_REALTIME, &t);
64 return t.tv_sec * SECOND_TO_MILLISECOND + t.tv_nsec / MILLISECOND_TO_NANOSECOND;
65 }
66
GetRetryRecords(std::vector<DriveKit::DKRecordId> & records)67 int32_t CloudDiskDataHandler::GetRetryRecords(std::vector<DriveKit::DKRecordId> &records)
68 {
69 NativeRdb::AbsRdbPredicates retryPredicates = NativeRdb::AbsRdbPredicates(FC::FILES_TABLE);
70 retryPredicates.SetWhereClause(FC::DIRTY_TYPE + " = ? ");
71 retryPredicates.SetWhereArgs({to_string(static_cast<int32_t>(DirtyType::TYPE_RETRY))});
72 retryPredicates.Limit(PULL_LIMIT_SIZE);
73 auto results = Query(retryPredicates, {FC::CLOUD_ID});
74 if (results == nullptr) {
75 LOGE("get nullptr modified result");
76 return E_RDB;
77 }
78
79 while (results->GoToNextRow() == 0) {
80 string record;
81 int ret = DataConvertor::GetString(FC::CLOUD_ID, record, *results);
82 if (ret == E_OK) {
83 records.emplace_back(record);
84 }
85 }
86 return E_OK;
87 }
88
IsLocalDirty(NativeRdb::ResultSet & local)89 static bool IsLocalDirty(NativeRdb::ResultSet &local)
90 {
91 int dirty;
92 int ret = DataConvertor::GetInt(FC::DIRTY_TYPE, dirty, local);
93 if (ret != E_OK) {
94 LOGE("Get dirty int failed");
95 return false;
96 }
97 return (dirty == static_cast<int32_t>(DirtyType::TYPE_MDIRTY)) ||
98 (dirty == static_cast<int32_t>(DirtyType::TYPE_FDIRTY)) ||
99 (dirty == static_cast<int32_t>(DirtyType::TYPE_DELETED));
100 }
FileIsRecycled(NativeRdb::ResultSet & local)101 static bool FileIsRecycled(NativeRdb::ResultSet &local)
102 {
103 int64_t recycledTime = 0;
104 int ret = DataConvertor::GetLong(FC::FILE_TIME_RECYCLED, recycledTime, local);
105 if (ret != E_OK) {
106 LOGE("Get local recycled failed");
107 return false;
108 }
109 return recycledTime > 0;
110 }
FileIsLocal(NativeRdb::ResultSet & local)111 static bool FileIsLocal(NativeRdb::ResultSet &local)
112 {
113 int32_t position = 0;
114 int32_t ret = DataConvertor::GetInt(FC::POSITION, position, local);
115 if (ret != E_OK) {
116 LOGE("Get local position failed");
117 return false;
118 }
119
120 return position != static_cast<int32_t>(POSITION_CLOUD);
121 }
122
HandleCreateConvertErr(int32_t err,NativeRdb::ResultSet & resultSet)123 void CloudDiskDataHandler::HandleCreateConvertErr(int32_t err, NativeRdb::ResultSet &resultSet)
124 {
125 string cloudId;
126 int32_t ret = createConvertor_.GetString(FC::CLOUD_ID, cloudId, resultSet);
127 if (ret != E_OK) {
128 LOGE("get create cloudId err, %{public}d", ret);
129 return;
130 }
131 createFailSet_.push_back(cloudId);
132 }
133
HandleFdirtyConvertErr(int32_t err,NativeRdb::ResultSet & resultSet)134 void CloudDiskDataHandler::HandleFdirtyConvertErr(int32_t err, NativeRdb::ResultSet &resultSet)
135 {
136 string cloudId;
137 int32_t ret = fdirtyConvertor_.GetString(FC::CLOUD_ID, cloudId, resultSet);
138 if (ret != E_OK) {
139 LOGE("get fdirty cloudId err, %{public}d", ret);
140 return;
141 }
142 modifyFailSet_.push_back(cloudId);
143 }
144
QueryLocalByCloudId(const vector<string> & recordIds)145 tuple<shared_ptr<NativeRdb::ResultSet>, map<string, int>> CloudDiskDataHandler::QueryLocalByCloudId(
146 const vector<string> &recordIds)
147 {
148 NativeRdb::AbsRdbPredicates predicates = NativeRdb::AbsRdbPredicates(FC::FILES_TABLE);
149 predicates.In(FC::CLOUD_ID, recordIds);
150 auto resultSet = Query(predicates, FC::PULL_QUERY_COLUMNS);
151 auto recordIdRowIdMap = map<string, int>();
152 if (resultSet == nullptr) {
153 LOGE("get nullptr created result");
154 return {nullptr, std::move(recordIdRowIdMap)};
155 }
156 int rowCount = 0;
157 int ret = resultSet->GetRowCount(rowCount);
158 if (ret != 0 || rowCount < 0) {
159 LOGE("result set get row count err %{public}d, rowCount %{public}d", ret, rowCount);
160 return {nullptr, std::move(recordIdRowIdMap)};
161 }
162 int columnIndex = 0;
163 resultSet->GetColumnIndex(FC::CLOUD_ID, columnIndex);
164 for (int rowId = 0; rowId < rowCount; ++rowId) {
165 resultSet->GoToNextRow();
166 string recordId = "";
167 resultSet->GetString(columnIndex, recordId);
168 recordIdRowIdMap.insert(make_pair(recordId, rowId));
169 }
170 return {std::move(resultSet), std::move(recordIdRowIdMap)};
171 }
172
OnFetchRecords(shared_ptr<vector<DKRecord>> & records,OnFetchParams & params)173 int32_t CloudDiskDataHandler::OnFetchRecords(shared_ptr<vector<DKRecord>> &records, OnFetchParams ¶ms)
174 {
175 LOGI("on fetch %{public}zu records", records->size());
176 int32_t ret = E_OK;
177 auto recordIds = vector<string>();
178 for (auto &record : *records) {
179 recordIds.push_back(record.GetRecordId());
180 }
181 auto [resultSet, recordIdRowIdMap] = QueryLocalByCloudId(recordIds);
182 if (resultSet == nullptr) {
183 return E_RDB;
184 }
185 for (auto &record : *records) {
186 if ((recordIdRowIdMap.find(record.GetRecordId()) == recordIdRowIdMap.end()) && !record.GetIsDelete()) {
187 ret = PullRecordInsert(record, params);
188 } else if (recordIdRowIdMap.find(record.GetRecordId()) != recordIdRowIdMap.end()) {
189 resultSet->GoToRow(recordIdRowIdMap.at(record.GetRecordId()));
190 if (record.GetIsDelete()) {
191 ret = PullRecordDelete(record, *resultSet);
192 } else {
193 ret = PullRecordUpdate(record, *resultSet, params);
194 }
195 }
196 if (ret != E_OK) {
197 LOGE("recordId %s error %{public}d", record.GetRecordId().c_str(), ret);
198 if (ret == E_RDB) {
199 break;
200 }
201 ret = E_OK;
202 }
203 }
204 return ret;
205 }
206
PullRecordInsert(DKRecord & record,OnFetchParams & params)207 int32_t CloudDiskDataHandler::PullRecordInsert(DKRecord &record, OnFetchParams ¶ms)
208 {
209 RETURN_ON_ERR(IsStop());
210 LOGI("insert of record %{public}s", record.GetRecordId().c_str());
211
212 /* check local file conflict */
213 int32_t ret = PullRecordConflict(record);
214 if (ret != E_OK) {
215 LOGE("MetaFile Conflict failed %{public}d", ret);
216 return ret;
217 }
218 ValuesBucket values;
219 ret = localConvertor_.Convert(record, values);
220 if (ret != E_OK) {
221 LOGE("record to valuebucket failed, ret=%{public}d", ret);
222 return ret;
223 }
224 int64_t rowId;
225 values.PutInt(FC::POSITION, POSITION_CLOUD);
226 values.PutInt(FC::DIRTY_TYPE, static_cast<int32_t>(DirtyType::TYPE_SYNCED));
227 params.insertFiles.push_back(values);
228 ret = Insert(rowId, FC::FILES_TABLE, values);
229 return E_OK;
230 }
231
PullRecordConflict(DKRecord & record)232 int32_t CloudDiskDataHandler::PullRecordConflict(DKRecord &record)
233 {
234 int32_t ret = E_OK;
235 DKRecordData data;
236 record.GetRecordData(data);
237 if (data.find(DK_FILE_NAME) == data.end() || data.find(DK_DIRECTLY_RECYCLED) == data.end()) {
238 return E_INVALID_ARGS;
239 }
240 string fullName = "";
241 int64_t recycledTime = 0;
242 string parentId = localConvertor_.GetParentCloudId(data);
243 data[DK_FILE_NAME].GetString(fullName);
244 data[DK_FILE_TIME_RECYCLED].GetLong(recycledTime);
245 if (recycledTime > 0) {
246 return E_OK;
247 }
248 size_t lastDot = fullName.rfind('.');
249 if (lastDot == std::string::npos) {
250 lastDot = fullName.length();
251 }
252 string fileName = fullName.substr(0, lastDot);
253 NativeRdb::AbsRdbPredicates predicates = NativeRdb::AbsRdbPredicates(FC::FILES_TABLE);
254 predicates.EqualTo(FC::PARENT_CLOUD_ID, parentId);
255 predicates.EqualTo(FC::FILE_TIME_RECYCLED, 0);
256 predicates.NotEqualTo(FC::CLOUD_ID, record.GetRecordId());
257 predicates.Like(FC::FILE_NAME, fileName + "%");
258 auto resultSet = Query(predicates, {FC::CLOUD_ID, FC::FILE_NAME});
259 ret = HandleConflict(resultSet, fullName, lastDot);
260 return ret;
261 }
262
HandleConflict(const std::shared_ptr<NativeRdb::ResultSet> resultSet,string & fullName,const int & lastDot)263 int32_t CloudDiskDataHandler::HandleConflict(const std::shared_ptr<NativeRdb::ResultSet> resultSet,
264 string &fullName,
265 const int &lastDot)
266 {
267 if (resultSet == nullptr) {
268 LOGE(" resultSet is null");
269 return E_RDB;
270 }
271 int32_t count = 0;
272 int32_t ret = resultSet->GetRowCount(count);
273 if (ret != E_OK || count < 0) {
274 return E_RDB;
275 }
276 if (count == 0) {
277 return E_OK;
278 }
279 string renameFileCloudId = "";
280 ret = FindRenameFile(resultSet, renameFileCloudId, fullName, lastDot);
281 if (ret != E_OK) {
282 LOGW("try to rename too many times");
283 return E_INVAL_ARG;
284 }
285 if (!renameFileCloudId.empty()) {
286 ret = ConflictReName(renameFileCloudId, fullName);
287 } else {
288 LOGD("no same name");
289 }
290 return ret;
291 }
292
FindRenameFile(const std::shared_ptr<NativeRdb::ResultSet> resultSet,string & renameFileCloudId,string & fullName,const int & lastDot)293 int32_t CloudDiskDataHandler::FindRenameFile(const std::shared_ptr<NativeRdb::ResultSet> resultSet,
294 string &renameFileCloudId,
295 string &fullName,
296 const int &lastDot)
297 {
298 string fileName = fullName.substr(0, lastDot);
299 string extension = fullName.substr(lastDot);
300 string dbFileName = "";
301 int32_t renameTimes = 0;
302 bool findSameFile = true;
303 while (findSameFile) {
304 renameTimes++;
305 findSameFile = false;
306 resultSet->GoToFirstRow();
307 string dbFileCloudId = "";
308 do {
309 DataConvertor::GetString(FC::FILE_NAME, dbFileName, *resultSet);
310 if (fullName == dbFileName) {
311 LOGD("find same name file try to rename");
312 fullName = fileName + "(" + to_string(renameTimes) + ")" + extension;
313 DataConvertor::GetString(FC::CLOUD_ID, dbFileCloudId, *resultSet);
314 findSameFile = true;
315 break;
316 }
317 } while (resultSet->GoToNextRow() == 0);
318 if (fullName == fileName + extension) {
319 renameFileCloudId = dbFileCloudId;
320 }
321 if (renameTimes >= MAX_RENAME) {
322 break;
323 }
324 }
325 if (findSameFile) {
326 LOGW("try to rename too many times");
327 return E_INVAL_ARG;
328 }
329 return E_OK;
330 }
331
ConflictReName(const string & cloudId,string newFileName)332 int32_t CloudDiskDataHandler::ConflictReName(const string &cloudId, string newFileName)
333 {
334 LOGD("do conflict rename, new fileName is %{public}s", newFileName.c_str());
335 ValuesBucket values;
336 values.PutString(FC::FILE_NAME, newFileName);
337 int32_t changedRows;
338 string whereClause = FC::CLOUD_ID + " = ?";
339 vector<string> whereArgs = {cloudId};
340 values.PutLong(FileColumn::META_TIME_EDITED, UTCTimeMilliSeconds());
341 int32_t ret = Update(changedRows, values, whereClause, whereArgs);
342 if (ret != E_OK) {
343 LOGE("update db, rename fail");
344 return E_RDB;
345 }
346 return E_OK;
347 }
348
IsFileContentNull(const DKRecordData & data,NativeRdb::ResultSet & local)349 static bool IsFileContentNull(const DKRecordData &data, NativeRdb::ResultSet &local)
350 {
351 int64_t recordFileSize = -1;
352 int64_t localFileSize = -1;
353 if (data.find(DK_FILE_SIZE) == data.end() ||
354 data.at(DK_FILE_SIZE).GetLong(recordFileSize) != DKLocalErrorCode::NO_ERROR) {
355 LOGE("extract recordFileSize error");
356 return false;
357 }
358 int32_t ret = DataConvertor::GetLong(FC::FILE_SIZE, localFileSize, local);
359 if (ret != E_OK) {
360 LOGE("extract localFileSize error");
361 return false;
362 }
363 return (localFileSize == 0 && recordFileSize == 0);
364 }
365
IsFileContentChanged(const DKRecord & record,NativeRdb::ResultSet & local,bool & isChange)366 static int32_t IsFileContentChanged(const DKRecord &record, NativeRdb::ResultSet &local, bool &isChange)
367 {
368 DKRecordData data;
369 record.GetRecordData(data);
370 string fileType;
371 if (data.find(DK_IS_DIRECTORY) == data.end() ||
372 data.at(DK_IS_DIRECTORY).GetString(fileType) != DKLocalErrorCode::NO_ERROR) {
373 LOGE("extract type error");
374 return E_INVAL_ARG;
375 }
376 if (fileType == "directory") {
377 return E_OK;
378 }
379 if (IsFileContentNull(data, local)) {
380 return E_OK;
381 }
382 int64_t localEditTime = 0;
383 int64_t recordEditTime = 0;
384 if (data.find(DK_FILE_ATTRIBUTES) == data.end()) {
385 LOGW("record data cannot find attributes");
386 recordEditTime = static_cast<int64_t>(record.GetEditedTime());
387 } else {
388 DriveKit::DKRecordFieldMap attributes;
389 data[DK_FILE_ATTRIBUTES].GetRecordMap(attributes);
390 if (attributes[DK_FILE_TIME_EDITED].GetLong(recordEditTime) != DKLocalErrorCode::NO_ERROR) {
391 LOGW("attributes cannot find file time edited");
392 recordEditTime = static_cast<int64_t>(record.GetEditedTime());
393 }
394 }
395 int32_t ret = DataConvertor::GetLong(FC::FILE_TIME_EDITED, localEditTime, local);
396 if (ret != E_OK) {
397 return ret;
398 }
399 string localFileSha256;
400 string recordFileSha256;
401 if (data.find(DK_FILE_SHA256) == data.end() ||
402 data.at(DK_FILE_SHA256).GetString(recordFileSha256) != DKLocalErrorCode::NO_ERROR) {
403 LOGW("record data cannot find sha256");
404 return E_INVAL_ARG;
405 }
406 ret = DataConvertor::GetString(FC::FILE_SHA256, localFileSha256, local);
407 if (ret != E_OK) {
408 return ret;
409 }
410 isChange = ((localEditTime != recordEditTime) && (localFileSha256 != recordFileSha256));
411 return E_OK;
412 }
413
PullRecordUpdate(DKRecord & record,NativeRdb::ResultSet & local,OnFetchParams & params)414 int32_t CloudDiskDataHandler::PullRecordUpdate(DKRecord &record, NativeRdb::ResultSet &local, OnFetchParams ¶ms)
415 {
416 RETURN_ON_ERR(IsStop());
417 int32_t ret = E_OK;
418 LOGI("update of record %s", record.GetRecordId().c_str());
419 if (IsLocalDirty(local)) {
420 LOGI("local record dirty, ignore cloud update");
421 return E_OK;
422 }
423 ValuesBucket values;
424 ret = localConvertor_.Convert(record, values);
425 if (ret != E_OK) {
426 return ret;
427 }
428 bool isFileContentChanged = false;
429 ret = IsFileContentChanged(record, local, isFileContentChanged);
430 if (ret != E_OK) {
431 return ret;
432 }
433 if (FileIsLocal(local)) {
434 string localPath = CloudFileUtils::GetLocalFilePath(record.GetRecordId(), bundleName_, userId_);
435 if (CloudFileUtils::LocalWriteOpen(localPath)) {
436 return SetRetry(record.GetRecordId());
437 }
438 if (isFileContentChanged) {
439 LOGD("cloud file content changed, %s", record.GetRecordId().c_str());
440 ret = unlink(localPath.c_str());
441 if (ret != 0) {
442 LOGE("unlink local failed, errno %{public}d", errno);
443 }
444 values.PutInt(FC::POSITION, static_cast<int32_t>(POSITION_CLOUD));
445 }
446 }
447 LOGD("cloud file changed, %s", record.GetRecordId().c_str());
448 ret = PullRecordConflict(record);
449 if (ret != E_OK) {
450 LOGE("MetaFile Conflict failed %{public}d", ret);
451 return E_RDB;
452 }
453 /* update rdb */
454 values.PutInt(FC::DIRTY_TYPE, static_cast<int32_t>(DirtyTypes::TYPE_SYNCED));
455 int32_t changedRows;
456 string whereClause = FC::CLOUD_ID + " = ?";
457 ret = Update(changedRows, values, whereClause, {record.GetRecordId()});
458 if (ret != E_OK) {
459 LOGE("rdb update failed, err=%{public}d", ret);
460 return E_RDB;
461 }
462 LOGD("update of record success, change %{public}d row", changedRows);
463 return E_OK;
464 }
465
PullRecordDelete(DKRecord & record,NativeRdb::ResultSet & local)466 int32_t CloudDiskDataHandler::PullRecordDelete(DKRecord &record, NativeRdb::ResultSet &local)
467 {
468 LOGI("delete of record %s", record.GetRecordId().c_str());
469 bool isLocal = FileIsLocal(local);
470 string path = CloudFileUtils::GetLocalFilePath(record.GetRecordId(), bundleName_, userId_);
471 if (FileIsRecycled(local) || !isLocal) {
472 if (isLocal) {
473 LOGI("force delete instead");
474 int32_t ret = unlink(path.c_str());
475 if (ret != 0) {
476 LOGE("unlink local failed, errno %{public}d", errno);
477 }
478 }
479 int32_t deletedRows;
480 int32_t ret = Delete(deletedRows, FC::CLOUD_ID + " = ?", {record.GetRecordId()});
481 if (ret != E_OK) {
482 LOGE("delete in rdb failed, ret:%{public}d", ret);
483 return E_INVAL_ARG;
484 }
485 return E_OK;
486 }
487 if (IsLocalDirty(local)) {
488 LOGI("local record dirty, ignore cloud delete");
489 int32_t changedRows = -1;
490 ValuesBucket values;
491 values.PutInt(FC::VERSION, static_cast<int32_t>(record.GetVersion()));
492 string whereClause = FC::CLOUD_ID + " = ?";
493 int32_t ret = Update(changedRows, values, whereClause, {record.GetRecordId()});
494 if (ret != E_OK) {
495 LOGE("Update in rdb failed, ret:%{public}d", ret);
496 return ret;
497 }
498 }
499
500 if (CloudDisk::CloudFileUtils::LocalWriteOpen(path)) {
501 return SetRetry(record.GetRecordId());
502 }
503 return RecycleFile(record.GetRecordId());
504 }
505
RecycleFile(const string & recordId)506 int CloudDiskDataHandler::RecycleFile(const string &recordId)
507 {
508 LOGI("recycle of record %s", recordId.c_str());
509 ValuesBucket values;
510 values.PutInt(FC::DIRTY_TYPE, static_cast<int32_t>(DirtyType::TYPE_NEW));
511 values.PutInt(FC::OPERATE_TYPE, static_cast<int32_t>(CloudDisk::OperationType::DELETE));
512 values.PutInt(FC::POSITION, POSITION_LOCAL);
513 values.PutLong(FC::FILE_TIME_RECYCLED, UTCTimeMilliSeconds());
514 values.PutLong(FC::VERSION, 0);
515 int32_t changedRows;
516 string whereClause = FC::CLOUD_ID + " = ?";
517 int ret = Update(changedRows, values, whereClause, {recordId});
518 if (ret != E_OK) {
519 LOGE("rdb update failed, err=%{public}d", ret);
520 return E_RDB;
521 }
522 return E_OK;
523 }
524
SetRetry(const string & recordId)525 int CloudDiskDataHandler::SetRetry(const string &recordId)
526 {
527 LOGI("set retry of record %s", recordId.c_str());
528 int updateRows;
529 ValuesBucket values;
530 values.PutInt(FC::DIRTY_TYPE, static_cast<int32_t>(DirtyType::TYPE_RETRY));
531 string whereClause = FC::CLOUD_ID + " = ?";
532 int32_t ret = Update(updateRows, values, whereClause, {recordId});
533 if (ret != E_OK) {
534 LOGE("update retry flag failed, ret=%{public}d", ret);
535 return E_RDB;
536 }
537 return E_OK;
538 }
539
GetCheckRecords(vector<DriveKit::DKRecordId> & checkRecords,const shared_ptr<std::vector<DriveKit::DKRecord>> & records)540 int32_t CloudDiskDataHandler::GetCheckRecords(vector<DriveKit::DKRecordId> &checkRecords,
541 const shared_ptr<std::vector<DriveKit::DKRecord>> &records)
542 {
543 auto recordIds = vector<string>();
544 shared_ptr<std::vector<DriveKit::DKRecord>> fetchRecords = make_shared<std::vector<DriveKit::DKRecord>>();
545 for (const auto &record : *records) {
546 fetchRecords->emplace_back(record);
547 }
548 auto [resultSet, recordIdRowIdMap] = QueryLocalByCloudId(recordIds);
549 if (resultSet == nullptr) {
550 return E_RDB;
551 }
552 for (const auto &record : *records) {
553 if ((recordIdRowIdMap.find(record.GetRecordId()) == recordIdRowIdMap.end()) && !record.GetIsDelete()) {
554 fetchRecords->emplace_back(record);
555 } else if (recordIdRowIdMap.find(record.GetRecordId()) != recordIdRowIdMap.end()) {
556 resultSet->GoToRow(recordIdRowIdMap.at(record.GetRecordId()));
557 int64_t version = 0;
558 DataConvertor::GetLong(FC::VERSION, version, *resultSet);
559 if (record.GetVersion() != static_cast<unsigned long>(version) &&
560 (!IsLocalDirty(*resultSet) || record.GetIsDelete())) {
561 fetchRecords->emplace_back(record);
562 }
563 } else {
564 LOGE("recordId %s has multiple file in db!", record.GetRecordId().c_str());
565 }
566 }
567 OnFetchParams params;
568 OnFetchRecords(fetchRecords, params);
569 return E_OK;
570 }
571
Clean(const int action)572 int32_t CloudDiskDataHandler::Clean(const int action)
573 {
574 LOGD("Enter function CloudDiskDataHandler::Clean");
575 CloudPrefImpl cloudPrefImpl(userId_, bundleName_, FileColumn::FILES_TABLE);
576 cloudPrefImpl.Delete("rootId");
577 localConvertor_.SetRootId("");
578 createConvertor_.SetRootId("");
579 deleteConvertor_.SetRootId("");
580 mdirtyConvertor_.SetRootId("");
581 fdirtyConvertor_.SetRootId("");
582 RETURN_ON_ERR(CleanCloudRecord(action));
583 return E_OK;
584 }
585
CleanCloudRecord(const int32_t action)586 int32_t CloudDiskDataHandler::CleanCloudRecord(const int32_t action)
587 {
588 int32_t ret = E_OK;
589 NativeRdb::AbsRdbPredicates cleanPredicates = NativeRdb::AbsRdbPredicates(FC::FILES_TABLE);
590 cleanPredicates.EqualTo(FC::POSITION, static_cast<int32_t>(POSITION_LOCAL));
591 cleanPredicates.Or()->EqualTo(FC::POSITION, static_cast<int32_t>(POSITION_BOTH));
592 cleanPredicates.Limit(BATCH_LIMIT_SIZE);
593 int32_t count = 0;
594 vector<NativeRdb::ValueObject> deleteIds;
595 string cloudId = "";
596 do {
597 auto resultSet = Query(cleanPredicates, {FC::CLOUD_ID});
598 ret = resultSet->GetRowCount(count);
599 if (ret != E_OK) {
600 LOGE("get row count error , res: %{public}d", ret);
601 break;
602 }
603 while (resultSet->GoToNextRow() == 0) {
604 ret = DataConvertor::GetString(FC::CLOUD_ID, cloudId, *resultSet);
605 string localPath = CloudFileUtils::GetLocalFilePath(cloudId, bundleName_, userId_);
606 if (ret != E_OK) {
607 LOGE("Get path wrong");
608 return E_INVAL_ARG;
609 }
610 if (unlink(localPath.c_str()) != 0) {
611 LOGE("unlink local failed, errno %{public}d", errno);
612 }
613 deleteIds.emplace_back(cloudId);
614 }
615 BatchDetete(FC::FILES_TABLE, FC::CLOUD_ID, deleteIds);
616 deleteIds.clear();
617 } while (count != 0);
618 int32_t deletedRows;
619 ret = Delete(deletedRows, "", {});
620 return ret;
621 }
622
OnDownloadAssets(const std::map<DriveKit::DKDownloadAsset,DriveKit::DKDownloadResult> & resultMap)623 int32_t CloudDiskDataHandler::OnDownloadAssets(
624 const std::map<DriveKit::DKDownloadAsset, DriveKit::DKDownloadResult> &resultMap)
625 {
626 return E_OK;
627 }
GetCreatedRecords(vector<DKRecord> & records)628 int32_t CloudDiskDataHandler::GetCreatedRecords(vector<DKRecord> &records)
629 {
630 while (records.size() == 0) {
631 NativeRdb::AbsRdbPredicates createPredicates = NativeRdb::AbsRdbPredicates(FC::FILES_TABLE);
632 createPredicates
633 .EqualTo(FC::DIRTY_TYPE, to_string(static_cast<int32_t>(CloudDisk::DirtyType::TYPE_NEW)))
634 ->And()->EqualTo(FC::FILE_TIME_RECYCLED, "0");
635 if (!createFailSet_.empty()) {
636 createPredicates.And()->NotIn(FC::CLOUD_ID, createFailSet_);
637 }
638 createPredicates.OrderByDesc(FC::IS_DIRECTORY);
639 createPredicates.OrderByAsc(FC::FILE_TIME_ADDED);
640 createPredicates.OrderByAsc(FC::FILE_SIZE);
641 createPredicates.Limit(LIMIT_SIZE);
642 auto results = Query(createPredicates, FileColumn::DISK_CLOUD_SYNC_COLUMNS);
643 if (results == nullptr) {
644 LOGE("get nullptr created result");
645 return E_RDB;
646 }
647 int32_t ret = createConvertor_.ResultSetToRecords(move(results), records);
648 if (ret != E_OK) {
649 if (ret == E_STOP) {
650 return E_OK;
651 }
652 LOGE("result set to records err %{public}d", ret);
653 return ret;
654 }
655 }
656 return E_OK;
657 }
GetDeletedRecords(vector<DKRecord> & records)658 int32_t CloudDiskDataHandler::GetDeletedRecords(vector<DKRecord> &records)
659 {
660 NativeRdb::AbsRdbPredicates deletePredicates = NativeRdb::AbsRdbPredicates(FC::FILES_TABLE);
661 deletePredicates
662 .EqualTo(FC::DIRTY_TYPE, to_string(static_cast<int32_t>(CloudDisk::DirtyType::TYPE_DELETED)));
663 if (!modifyFailSet_.empty()) {
664 deletePredicates.And()->NotIn(FC::CLOUD_ID, modifyFailSet_);
665 }
666 deletePredicates.Limit(DELETE_BATCH_NUM);
667 auto results = Query(deletePredicates, FileColumn::DISK_CLOUD_SYNC_COLUMNS);
668 if (results == nullptr) {
669 LOGE("get nullptr deleted result");
670 return E_RDB;
671 }
672 int ret = deleteConvertor_.ResultSetToRecords(move(results), records);
673 if (ret != E_OK) {
674 LOGE("result set to records err %{public}d", ret);
675 return ret;
676 }
677 return E_OK;
678 }
GetMetaModifiedRecords(vector<DKRecord> & records)679 int32_t CloudDiskDataHandler::GetMetaModifiedRecords(vector<DKRecord> &records)
680 {
681 NativeRdb::AbsRdbPredicates updatePredicates = NativeRdb::AbsRdbPredicates(FC::FILES_TABLE);
682 updatePredicates
683 .EqualTo(FC::DIRTY_TYPE, to_string(static_cast<int32_t>(CloudDisk::DirtyType::TYPE_MDIRTY)));
684 if (!modifyFailSet_.empty()) {
685 updatePredicates.And()->NotIn(FC::CLOUD_ID, modifyFailSet_);
686 }
687 updatePredicates.Limit(MODIFY_BATCH_NUM);
688 auto results = Query(updatePredicates, FileColumn::DISK_CLOUD_SYNC_COLUMNS);
689 if (results == nullptr) {
690 LOGE("get nullptr meta modified result");
691 return E_RDB;
692 }
693 int ret = mdirtyConvertor_.ResultSetToRecords(move(results), records);
694 if (ret != E_OK) {
695 LOGE("meta modified result set to records err %{public}d", ret);
696 return ret;
697 }
698 return E_OK;
699 }
GetFileModifiedRecords(vector<DKRecord> & records)700 int32_t CloudDiskDataHandler::GetFileModifiedRecords(vector<DKRecord> &records)
701 {
702 while (records.size() == 0) {
703 NativeRdb::AbsRdbPredicates updatePredicates = NativeRdb::AbsRdbPredicates(FC::FILES_TABLE);
704 updatePredicates
705 .EqualTo(FC::DIRTY_TYPE, to_string(static_cast<int32_t>(CloudDisk::DirtyType::TYPE_FDIRTY)));
706 if (!modifyFailSet_.empty()) {
707 updatePredicates.And()->NotIn(FC::CLOUD_ID, modifyFailSet_);
708 }
709 updatePredicates.OrderByAsc(FC::FILE_SIZE);
710 updatePredicates.Limit(LIMIT_SIZE);
711 auto results = Query(updatePredicates, FileColumn::DISK_CLOUD_SYNC_COLUMNS);
712 if (results == nullptr) {
713 LOGE("get nullptr file modified result");
714 return E_RDB;
715 }
716 int32_t ret = fdirtyConvertor_.ResultSetToRecords(move(results), records);
717 if (ret != E_OK) {
718 if (ret == E_STOP) {
719 return E_OK;
720 }
721 LOGE("file modified result set to records err %{public}d", ret);
722 return ret;
723 }
724 }
725 return E_OK;
726 }
727
OnCreateRecords(const map<DKRecordId,DKRecordOperResult> & map)728 int32_t CloudDiskDataHandler::OnCreateRecords(const map<DKRecordId, DKRecordOperResult> &map)
729 {
730 unordered_map<string, LocalInfo> localMap;
731 int32_t ret = GetLocalInfo(map, localMap, FC::CLOUD_ID);
732 if (ret != E_OK) {
733 LOGE("get created local match info err %{public}d", ret);
734 return ret;
735 }
736 for (auto &entry : map) {
737 int32_t err;
738 const DKRecordOperResult &result = entry.second;
739 if (result.IsSuccess()) {
740 err = OnCreateRecordSuccess(entry, localMap);
741 } else {
742 err = OnRecordFailed(entry);
743 }
744 if (err != E_OK) {
745 createFailSet_.push_back(entry.first);
746 LOGE("create record fail, cloud id: %{private}s", entry.first.c_str());
747 }
748 GetReturn(err, ret);
749 }
750 return ret;
751 }
OnDeleteRecords(const map<DKRecordId,DKRecordOperResult> & map)752 int32_t CloudDiskDataHandler::OnDeleteRecords(const map<DKRecordId, DKRecordOperResult> &map)
753 {
754 int32_t ret = E_OK;
755 for (auto &entry : map) {
756 const DKRecordOperResult &result = entry.second;
757 int32_t err;
758 if (result.IsSuccess()) {
759 err = OnDeleteRecordSuccess(entry);
760 } else {
761 err = OnRecordFailed(entry);
762 }
763 if (err != E_OK) {
764 modifyFailSet_.push_back(entry.first);
765 LOGE("delete record fail, cloud id: %{private}s", entry.first.c_str());
766 }
767 GetReturn(err, ret);
768 }
769 return ret;
770 }
OnModifyMdirtyRecords(const map<DKRecordId,DKRecordOperResult> & map)771 int32_t CloudDiskDataHandler::OnModifyMdirtyRecords(const map<DKRecordId, DKRecordOperResult> &map)
772 {
773 unordered_map<string, LocalInfo> localMap;
774 int32_t ret = GetLocalInfo(map, localMap, FC::CLOUD_ID);
775 if (ret != E_OK) {
776 LOGE("get meta modified local match info err %{public}d", ret);
777 return ret;
778 }
779 for (auto &entry : map) {
780 int32_t err;
781 const DKRecordOperResult &result = entry.second;
782 if (result.IsSuccess()) {
783 err = OnModifyRecordSuccess(entry, localMap);
784 } else {
785 err = OnRecordFailed(entry);
786 }
787 if (err != E_OK) {
788 modifyFailSet_.push_back(entry.first);
789 LOGE("modify mdirty record fail, cloud id: %{private}s", entry.first.c_str());
790 }
791 GetReturn(err, ret);
792 }
793 return ret;
794 }
OnModifyFdirtyRecords(const map<DKRecordId,DKRecordOperResult> & map)795 int32_t CloudDiskDataHandler::OnModifyFdirtyRecords(const map<DKRecordId, DKRecordOperResult> &map)
796 {
797 unordered_map<string, LocalInfo> localMap;
798 int32_t ret = GetLocalInfo(map, localMap, FC::CLOUD_ID);
799 if (ret != E_OK) {
800 LOGE("get file modified local match info err %{public}d", ret);
801 return ret;
802 }
803 for (auto &entry : map) {
804 int32_t err;
805 const DKRecordOperResult &result = entry.second;
806 if (result.IsSuccess()) {
807 err = OnModifyRecordSuccess(entry, localMap);
808 } else {
809 err = OnRecordFailed(entry);
810 }
811 if (err != E_OK) {
812 modifyFailSet_.push_back(entry.first);
813 LOGE("modify fdirty record fail, cloud id: %{private}s", entry.first.c_str());
814 }
815 GetReturn(err, ret);
816 }
817 return ret;
818 }
OnDownloadAssets(const DriveKit::DKDownloadAsset & asset)819 int32_t CloudDiskDataHandler::OnDownloadAssets(const DriveKit::DKDownloadAsset &asset)
820 {
821 return E_OK;
822 }
UpdateFileAsset(DKRecordData data,ValuesBucket & values)823 static int32_t UpdateFileAsset(DKRecordData data, ValuesBucket &values)
824 {
825 DriveKit::DKAsset content;
826 if (data.find(DK_FILE_CONTENT) == data.end()) {
827 LOGE("record data cannot find content");
828 return E_INVAL_ARG;
829 }
830 DKLocalErrorCode ret = data[DK_FILE_CONTENT].GetAsset(content);
831 if (ret != DKLocalErrorCode::NO_ERROR) {
832 LOGE("record field get content fail, ret %{public}d", ret);
833 return E_INVAL_ARG;
834 }
835 int64_t fileSize = static_cast<int64_t>(content.size);
836 string sha256 = content.hash;
837 values.PutLong(FC::FILE_SIZE, fileSize);
838 values.PutString(FC::FILE_SHA256, sha256);
839 return E_OK;
840 }
OnCreateRecordSuccess(const pair<DKRecordId,DKRecordOperResult> & entry,const unordered_map<string,LocalInfo> & localMap)841 int32_t CloudDiskDataHandler::OnCreateRecordSuccess(
842 const pair<DKRecordId, DKRecordOperResult> &entry,
843 const unordered_map<string, LocalInfo> &localMap)
844 {
845 auto record = entry.second.GetDKRecord();
846 if (localMap.find(entry.first) == localMap.end()) {
847 return E_OK;
848 }
849 DKRecordData data;
850 record.GetRecordData(data);
851 ValuesBucket valuesBucket;
852 if (UpdateFileAsset(data, valuesBucket)) {
853 LOGE("update file content fail");
854 }
855 valuesBucket.PutInt(FC::POSITION, POSITION_BOTH);
856 valuesBucket.PutLong(FC::VERSION, record.GetVersion());
857 if (IsTimeChanged(record, localMap, entry.first, FC::FILE_TIME_EDITED)) {
858 valuesBucket.PutInt(FC::DIRTY_TYPE, static_cast<int32_t>(CloudDisk::DirtyType::TYPE_FDIRTY));
859 } else if (IsTimeChanged(record, localMap, entry.first, FC::META_TIME_EDITED)) {
860 valuesBucket.PutInt(FC::DIRTY_TYPE, static_cast<int32_t>(CloudDisk::DirtyType::TYPE_MDIRTY));
861 } else {
862 valuesBucket.PutInt(FC::DIRTY_TYPE, static_cast<int32_t>(CloudDisk::DirtyType::TYPE_SYNCED));
863 }
864 int32_t changedRows;
865 int32_t ret = Update(changedRows, valuesBucket, FC::CLOUD_ID + " = ?", { entry.first });
866 if (ret != E_OK) {
867 LOGE("on create records update synced err %{public}d, cloudId %{private}s", ret, entry.first.c_str());
868 return ret;
869 }
870 return E_OK;
871 }
OnDeleteRecordSuccess(const std::pair<DKRecordId,DKRecordOperResult> & entry)872 int32_t CloudDiskDataHandler::OnDeleteRecordSuccess(const std::pair<DKRecordId, DKRecordOperResult> &entry)
873 {
874 int32_t deletedRows;
875 int32_t ret = Delete(deletedRows, FC::CLOUD_ID + " = ?", { entry.first });
876 if (ret != E_OK) {
877 LOGE("on delete records update err %{public}d, cloudId %{private}s", ret, entry.first.c_str());
878 return ret;
879 }
880 return E_OK;
881 }
OnModifyRecordSuccess(const pair<DKRecordId,DKRecordOperResult> & entry,const unordered_map<string,LocalInfo> & localMap)882 int32_t CloudDiskDataHandler::OnModifyRecordSuccess(
883 const pair<DKRecordId, DKRecordOperResult> &entry,
884 const unordered_map<string, LocalInfo> &localMap)
885 {
886 auto record = entry.second.GetDKRecord();
887 DKRecordData data;
888 record.GetRecordData(data);
889 if (data.find(DK_FILE_ATTRIBUTES) == data.end()) {
890 LOGE("record data cannot find attributes");
891 return E_INVAL_ARG;
892 }
893 DriveKit::DKRecordFieldMap attributes;
894 data[DK_FILE_ATTRIBUTES].GetRecordMap(attributes);
895 if (attributes.find(DK_META_TIME_EDITED) == attributes.end()) {
896 LOGE("attributes cannot find meta time edited");
897 return E_INVAL_ARG;
898 }
899 int64_t meta_date_modified;
900 if (attributes[DK_META_TIME_EDITED].GetLong(meta_date_modified) != DKLocalErrorCode::NO_ERROR) {
901 LOGE("obtain meta time edited error, cloudId %{private}s", entry.first.c_str());
902 return E_INVAL_ARG;
903 }
904 if (localMap.find(entry.first) == localMap.end()) {
905 return E_OK;
906 }
907 ValuesBucket valuesBucket;
908 if (UpdateFileAsset(data, valuesBucket)) { LOGE("update file content fail"); }
909 int32_t changedRows;
910 valuesBucket.PutLong(FC::VERSION, record.GetVersion());
911 if (IsTimeChanged(record, localMap, entry.first, FC::FILE_TIME_EDITED)) {
912 valuesBucket.PutInt(FC::DIRTY_TYPE, static_cast<int32_t>(CloudDisk::DirtyType::TYPE_FDIRTY));
913 } else if (IsTimeChanged(record, localMap, entry.first, FC::META_TIME_EDITED)) {
914 valuesBucket.PutInt(FC::DIRTY_TYPE, static_cast<int32_t>(CloudDisk::DirtyType::TYPE_MDIRTY));
915 } else {
916 valuesBucket.PutInt(FC::DIRTY_TYPE, static_cast<int32_t>(CloudDisk::DirtyType::TYPE_SYNCED));
917 }
918 int32_t ret = Update(changedRows, valuesBucket, FC::CLOUD_ID + " = ?", { entry.first });
919 if (ret != E_OK) {
920 LOGE("on meta modify records update synced err %{public}d, cloudId %{private}s", ret, entry.first.c_str());
921 valuesBucket.Clear();
922 valuesBucket.PutLong(FC::VERSION, record.GetVersion());
923 ret = Update(changedRows, valuesBucket, FC::CLOUD_ID + " = ?", { entry.first });
924 if (ret != E_OK) {
925 LOGE("update meta record version err %{public}d, cloudId %{private}s", ret, entry.first.c_str());
926 return ret;
927 }
928 }
929 return E_OK;
930 }
IsTimeChanged(const DriveKit::DKRecord & record,const unordered_map<string,LocalInfo> & localMap,const string & cloudId,const string & type)931 bool CloudDiskDataHandler::IsTimeChanged(const DriveKit::DKRecord &record,
932 const unordered_map<string, LocalInfo> &localMap, const string &cloudId, const string &type)
933 {
934 int64_t cloudTime = 0;
935 int64_t localTime = 0;
936 auto it = localMap.find(cloudId);
937 if (it == localMap.end()) {
938 return true;
939 }
940 DKRecordData data;
941 record.GetRecordData(data);
942 if (data.find(DK_FILE_ATTRIBUTES) == data.end()) {
943 LOGE("record data cannot find attributes");
944 return false;
945 }
946 DriveKit::DKRecordFieldMap attributes;
947 data[DK_FILE_ATTRIBUTES].GetRecordMap(attributes);
948 if (type == FC::FILE_TIME_EDITED) {
949 localTime = it->second.fdirtyTime;
950 if (attributes[DK_FILE_TIME_EDITED].GetLong(cloudTime) != DKLocalErrorCode::NO_ERROR) {
951 LOGE("obtain file time edited error, cloudId %{private}s", cloudId.c_str());
952 return false;
953 }
954 } else {
955 localTime = it->second.mdirtyTime;
956 if (attributes[DK_META_TIME_EDITED].GetLong(cloudTime) != DKLocalErrorCode::NO_ERROR) {
957 LOGE("obtain meta time edited error, cloudId %{private}s", cloudId.c_str());
958 return false;
959 }
960 }
961 if (localTime == cloudTime) {
962 return false;
963 }
964 return true;
965 }
GetLocalInfo(const map<DKRecordId,DKRecordOperResult> & map,unordered_map<string,LocalInfo> & infoMap,const string & type)966 int32_t CloudDiskDataHandler::GetLocalInfo(const map<DKRecordId, DKRecordOperResult> &map,
967 unordered_map<string, LocalInfo> &infoMap, const string &type)
968 {
969 vector<string> cloudId;
970 if (type != FC::CLOUD_ID) {
971 LOGE("query type for getting local info is invalid, %{public}s", type.c_str());
972 return E_UNKNOWN;
973 }
974 for (auto &entry : map) {
975 cloudId.push_back(entry.first);
976 }
977 NativeRdb::AbsRdbPredicates createPredicates = NativeRdb::AbsRdbPredicates(FC::FILES_TABLE);
978 createPredicates.NotEqualTo(FC::DIRTY_TYPE, to_string(static_cast<int32_t>(CloudDisk::DirtyType::TYPE_DELETED)))
979 ->And()->In(type, cloudId);
980 auto resultSet = Query(createPredicates, FileColumn::DISK_ON_UPLOAD_COLUMNS);
981 if (resultSet == nullptr) {
982 LOGE("query rdb err");
983 return E_RDB;
984 }
985 return BuildInfoMap(move(resultSet), infoMap, type);
986 }
BuildInfoMap(const shared_ptr<NativeRdb::ResultSet> resultSet,unordered_map<string,LocalInfo> & infoMap,const string & type)987 int32_t CloudDiskDataHandler::BuildInfoMap(const shared_ptr<NativeRdb::ResultSet> resultSet,
988 unordered_map<string, LocalInfo> &infoMap, const string &type)
989 {
990 int32_t idIndex = -1;
991 int32_t mTimeIndex = -1;
992 int32_t metaTimeIndex = -1;
993 RETURN_ON_ERR(resultSet->GetColumnIndex(type, idIndex));
994 RETURN_ON_ERR(resultSet->GetColumnIndex(FC::FILE_TIME_EDITED, mTimeIndex));
995 RETURN_ON_ERR(resultSet->GetColumnIndex(FC::META_TIME_EDITED, metaTimeIndex));
996 while (resultSet->GoToNextRow() == 0) {
997 string idValue;
998 int64_t mTime;
999 int64_t metaTime;
1000 if (resultSet->GetString(idIndex, idValue) == 0 && resultSet->GetLong(mTimeIndex, mTime) == 0 &&
1001 resultSet->GetLong(metaTimeIndex, metaTime) == 0) {
1002 infoMap.insert({ idValue, { metaTime, mTime } });
1003 }
1004 }
1005 return E_OK;
1006 }
1007
Reset()1008 void CloudDiskDataHandler::Reset()
1009 {
1010 modifyFailSet_.clear();
1011 createFailSet_.clear();
1012 }
1013
GetDownloadAsset(std::string uri,vector<DriveKit::DKDownloadAsset> & outAssetsToDownload)1014 int32_t CloudDiskDataHandler::GetDownloadAsset(std::string uri,
1015 vector<DriveKit::DKDownloadAsset> &outAssetsToDownload)
1016 {
1017 string path;
1018 int32_t ret = AppFileService::SandboxHelper::GetPhysicalPath(uri, to_string(userId_), path);
1019 if (ret != E_OK) {
1020 LOGE("get physical path failed");
1021 return E_INVAL_ARG;
1022 }
1023 string cloudId = CloudFileUtils::GetCloudId(path);
1024 if (cloudId.empty()) {
1025 LOGE("get cloud id failed, errno %{public}d", errno);
1026 return E_INVAL_ARG;
1027 }
1028 NativeRdb::AbsRdbPredicates predicates = NativeRdb::AbsRdbPredicates(FileColumn::FILES_TABLE);
1029 predicates.SetWhereClause(FileColumn::CLOUD_ID + " = ?");
1030 predicates.SetWhereArgs({cloudId});
1031 predicates.Limit(LIMIT_SIZE);
1032 auto resultSet = Query(predicates, {FileColumn::IS_DIRECTORY});
1033 if (resultSet == nullptr) {
1034 LOGE("get nullptr created result");
1035 return E_RDB;
1036 }
1037 int32_t rowCount = 0;
1038 ret = resultSet->GetRowCount(rowCount);
1039 if (ret != 0) {
1040 LOGE("result set get row count err %{public}d", ret);
1041 return E_RDB;
1042 }
1043 int32_t columnIndex = 0;
1044 int32_t isDirectory = 0;
1045 resultSet->GetColumnIndex(FileColumn::IS_DIRECTORY, columnIndex);
1046 resultSet->GetInt(columnIndex, isDirectory);
1047 if (isDirectory == FILE) {
1048 AppendFileToDownload(cloudId, "content", outAssetsToDownload);
1049 } else {
1050 return ERR_INVALID_VALUE;
1051 }
1052 return E_OK;
1053 }
1054
AppendFileToDownload(const string & cloudId,const std::string & fieldKey,std::vector<DKDownloadAsset> & assetsToDownload)1055 void CloudDiskDataHandler::AppendFileToDownload(const string &cloudId,
1056 const std::string &fieldKey,
1057 std::vector<DKDownloadAsset> &assetsToDownload)
1058 {
1059 DKDownloadAsset downloadAsset;
1060 downloadAsset.recordType = recordType_;
1061 downloadAsset.fieldKey = fieldKey;
1062 downloadAsset.recordId = cloudId;
1063 downloadAsset.downLoadPath = CloudFileUtils::GetLocalBucketPath(cloudId, bundleName_, userId_);
1064 downloadAsset.asset.assetName = cloudId + CloudFileUtils::TMP_SUFFIX;
1065 ForceCreateDirectory(downloadAsset.downLoadPath);
1066 assetsToDownload.push_back(downloadAsset);
1067 }
1068
OnDownloadSuccess(const DriveKit::DKDownloadAsset & asset)1069 int32_t CloudDiskDataHandler::OnDownloadSuccess(const DriveKit::DKDownloadAsset &asset)
1070 {
1071 string tmpLocalPath = asset.downLoadPath + "/" + asset.asset.assetName;
1072 string localPath = CloudFileUtils::GetPathWithoutTmp(tmpLocalPath);
1073 string cloudId = CloudFileUtils::GetPathWithoutTmp(asset.asset.assetName);
1074 if (rename(tmpLocalPath.c_str(), localPath.c_str()) != 0) {
1075 LOGE("err rename, errno: %{public}d, tmpLocalPath: %s, localPath: %s",
1076 errno, tmpLocalPath.c_str(), localPath.c_str());
1077 }
1078 // update rdb
1079 int32_t changedRows;
1080 ValuesBucket valuesBucket;
1081 valuesBucket.PutInt(FC::POSITION, POSITION_BOTH);
1082 string whereClause = FC::CLOUD_ID + " = ?";
1083 vector<string> whereArgs = {cloudId};
1084 int32_t ret = Update(changedRows, valuesBucket, whereClause, whereArgs);
1085 if (ret != E_OK) {
1086 LOGE("on download file from cloud err %{public}d", ret);
1087 }
1088 return ret;
1089 }
1090
CleanCache(const string & uri)1091 int32_t CloudDiskDataHandler::CleanCache(const string &uri)
1092 {
1093 string path;
1094 int32_t ret = AppFileService::SandboxHelper::GetPhysicalPath(uri, to_string(userId_), path);
1095 if (ret != E_OK) {
1096 LOGE("get physical path failed");
1097 return E_INVAL_ARG;
1098 }
1099 string cloudId = CloudFileUtils::GetCloudId(path);
1100 if (cloudId.empty()) {
1101 LOGE("get cloud id failed, errno %{public}d", errno);
1102 return E_INVAL_ARG;
1103 }
1104 string bucketPaht = CloudFileUtils::GetLocalBucketPath(cloudId, bundleName_, userId_) + "/" + cloudId;
1105 ret = unlink(bucketPaht.c_str());
1106 if (ret != 0 && errno != ENOENT) {
1107 LOGE("Unlink failed errno %{public}d", errno);
1108 return E_DELETE_FAILED;
1109 }
1110 if (errno == ENOENT) {
1111 LOGE("no such file");
1112 ret = E_NO_SUCH_FILE;
1113 }
1114 ValuesBucket values;
1115 values.PutInt(FC::POSITION, POSITION_CLOUD);
1116 int32_t changedRows = 0;
1117 string whereClause = FC::CLOUD_ID + " = ?";
1118 int32_t rdbRet = Update(changedRows, values, whereClause, {cloudId});
1119 if (rdbRet != E_OK) {
1120 LOGE("rdb update failed, err=%{public}d", rdbRet);
1121 return E_RDB;
1122 }
1123 return ret;
1124 }
1125 } // namespace CloudSync
1126 } // namespace FileManagement
1127 } // namespace OHOS
1128