• 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 #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 &params)
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 &params)
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 &params)
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