• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2024 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 "clouddisk_rdbstore.h"
17 
18 #include <cinttypes>
19 #include <ctime>
20 #include <sys/stat.h>
21 #include <sstream>
22 #include <functional>
23 
24 #include "cloud_pref_impl.h"
25 #include "clouddisk_db_const.h"
26 #include "clouddisk_notify.h"
27 #include "clouddisk_notify_utils.h"
28 #include "clouddisk_rdb_transaction.h"
29 #include "clouddisk_rdb_utils.h"
30 #include "clouddisk_sync_helper.h"
31 #include "clouddisk_type_const.h"
32 #include "data_sync_const.h"
33 #include "dfs_error.h"
34 #include "directory_ex.h"
35 #include "file_column.h"
36 #include "ffrt_inner.h"
37 #include "nlohmann/json.hpp"
38 #include "parameter.h"
39 #include "parameters.h"
40 #include "rdb_errno.h"
41 #include "rdb_sql_utils.h"
42 #include "utils_log.h"
43 
44 namespace OHOS::FileManagement::CloudDisk {
45 using namespace std;
46 using namespace OHOS::NativeRdb;
47 using namespace CloudSync;
48 
49 enum XATTR_CODE {
50     ERROR_CODE = -1,
51     CLOUD_LOCATION = 1,
52     CLOUD_RECYCLE,
53     IS_FAVORITE,
54     FILE_SYNC_STATUS,
55     IS_EXT_ATTR,
56     HAS_THM,
57     TIME_RECYCLED,
58     RECYCLE_PATH,
59 };
60 static constexpr int32_t LOOKUP_QUERY_LIMIT = 1;
61 static constexpr int32_t CHECK_QUERY_LIMIT = 2000;
62 static const uint32_t SET_STATE = 1;
63 static const uint32_t CANCEL_STATE = 0;
64 static const uint32_t MAX_FILE_NAME_SIZE = 246;
65 static const uint32_t MAX_QUERY_TIMES = 1024;
66 static const uint32_t STAT_MODE_DIR = 0771;
67 static const uint32_t STAT_MODE_FILE = 0771;
68 static const uint32_t STAT_MODE_REG = 0660;
69 const string BUNDLENAME_FLAG = "<BundleName>";
70 const string CLOUDDISK_URI_PREFIX = "file://<BundleName>/data/storage/el2/cloud";
71 const string BACKFLASH = "/";
72 static const string RECYCLE_FILE_NAME = ".trash";
73 static const string ROOT_CLOUD_ID = "rootId";
74 static const std::string FILEMANAGER_KEY = "persist.kernel.bundle_name.filemanager";
75 // srcPath only used in restore files
76 static const string SRC_PATH_KEY = "srcPath";
77 static const string LOCAL_PATH_MNT_HMDFS = "/mnt/hmdfs/";
78 static const string LOCAL_PATH_CLOUD_DATA = "/cloud/data/";
79 static const string FILE_SCHEME = "file";
80 static const int32_t DIRECTLY_RECYCLED_COPY = 4;
81 static const int32_t VERSION_COPY = 0;
82 static const int32_t FLAG_NOT_EXIST = 2;
83 static const int32_t FLAG_TO_BE_UPLOAD = 1;
84 
CloudSyncTriggerFunc(const std::vector<std::string> & args)85 static const std::string CloudSyncTriggerFunc(const std::vector<std::string> &args)
86 {
87     size_t size = args.size();
88     if (size != ARGS_SIZE) {
89         LOGE("CloudSyncTriggerFunc args size error, %{public}zu", size);
90         return "";
91     }
92     int32_t userId = std::strtol(args[ARG_USER_ID].c_str(), nullptr, 0);
93     string bundleName = args[ARG_BUNDLE_NAME];
94     LOGD("begin cloud sync trigger, bundleName: %{public}s, userId: %{public}d", bundleName.c_str(), userId);
95     return "";
96 }
97 
CloudDiskRdbStore(const std::string & bundleName,const int32_t & userId)98 CloudDiskRdbStore::CloudDiskRdbStore(const std::string &bundleName, const int32_t &userId)
99     : bundleName_(bundleName), userId_(userId)
100 {
101     RdbInit();
102 }
103 
~CloudDiskRdbStore()104 CloudDiskRdbStore::~CloudDiskRdbStore()
105 {
106     Stop();
107 }
108 
ReBuildDatabase(const string & databasePath)109 int32_t CloudDiskRdbStore::ReBuildDatabase(const string &databasePath)
110 {
111     LOGI("database need to be rebuilded");
112     int32_t errCode = RdbHelper::DeleteRdbStore(databasePath);
113     if (errCode != NativeRdb::E_OK) {
114         LOGE("Delete CloudDisk Database is failed, err = %{public}d", errCode);
115         return errCode;
116     }
117     errCode = 0;
118     CloudDiskDataCallBack rdbDataCallBack;
119     rdbStore_ = RdbHelper::GetRdbStore(config_, CLOUD_DISK_RDB_VERSION, rdbDataCallBack, errCode);
120     if (rdbStore_ == nullptr) {
121         LOGE("ReGetRdbStore is failed, userId_ = %{public}d, bundleName_ = %{public}s, errCode = %{public}d",
122              userId_, bundleName_.c_str(), errCode);
123         return errCode;
124     }
125     DatabaseRestore();
126     return E_OK;
127 }
128 
RdbInit()129 int32_t CloudDiskRdbStore::RdbInit()
130 {
131     if (WaitParameter("persist.kernel.move.finish", "true", MOVE_FILE_TIME_DAEMON) != 0) {
132         LOGE("wait move error");
133         return EBUSY;
134     }
135     LOGI("Init rdb store, userId_ = %{public}d, bundleName_ = %{public}s", userId_, bundleName_.c_str());
136     string baseDir = "/data/service/el2/" + to_string(userId_) + "/hmdfs/cloudfile_manager/";
137     string customDir = baseDir.append(system::GetParameter(FILEMANAGER_KEY, ""));
138     string name = CLOUD_DISK_DATABASE_NAME;
139     int32_t errCode = 0;
140     string databasePath = RdbSqlUtils::GetDefaultDatabasePath(customDir, CLOUD_DISK_DATABASE_NAME, errCode);
141     if (errCode != NativeRdb::E_OK) {
142         LOGE("Create Default Database Path is failed, errCode = %{public}d", errCode);
143         return E_PATH;
144     }
145     config_.SetName(name);
146     config_.SetPath(databasePath);
147     config_.SetReadConSize(CONNECT_SIZE);
148     config_.SetScalarFunction("cloud_sync_func", ARGS_SIZE, CloudSyncTriggerFunc);
149     errCode = 0;
150     CloudDiskDataCallBack rdbDataCallBack;
151     rdbStore_ = RdbHelper::GetRdbStore(config_, CLOUD_DISK_RDB_VERSION, rdbDataCallBack, errCode);
152     if (rdbStore_ == nullptr) {
153         LOGE("GetRdbStore is failed, userId_ = %{public}d, bundleName_ = %{public}s, errCode = %{public}d",
154              userId_, bundleName_.c_str(), errCode);
155         if (errCode == NativeRdb::E_SQLITE_CORRUPT) {
156             if (ReBuildDatabase(databasePath)) {
157                 LOGE("clouddisk db image is malformed, ReBuild failed");
158             }
159         }
160         return errCode;
161     } else if (errCode == NativeRdb::E_SQLITE_CORRUPT) { DatabaseRestore(); }
162     return E_OK;
163 }
164 
Stop()165 void CloudDiskRdbStore::Stop()
166 {
167     if (rdbStore_ == nullptr) {
168         return;
169     }
170     rdbStore_ = nullptr;
171 }
172 
GetRaw()173 shared_ptr<RdbStore> CloudDiskRdbStore::GetRaw()
174 {
175     return rdbStore_;
176 }
177 
DatabaseRestore()178 void CloudDiskRdbStore::DatabaseRestore()
179 {
180     if (rdbStore_ == nullptr) {
181         LOGE("rdbStore_ is nullptr");
182         return;
183     }
184     LOGI("clouddisk db image is malformed, need to restore");
185     auto fileName = "/data/service/el2/" + to_string(userId_) + "/hmdfs/cloudfile_manager/" +
186         system::GetParameter(FILEMANAGER_KEY, "") + "/backup/clouddisk_backup.db";
187     if (access(fileName.c_str(), F_OK) == 0) {
188         int32_t ret = -1;
189         {
190             lock_guard<mutex> lock(backupMutex_);
191             ret = rdbStore_->Restore(fileName);
192         }
193         if (ret != 0) {
194             LOGE("cloudisk restore failed, ret %{public}d", ret);
195         }
196     } else {
197         LOGE("clouddisk backup db is not exist");
198     }
199 }
200 
LookUp(const std::string & parentCloudId,const std::string & fileName,CloudDiskFileInfo & info)201 int32_t CloudDiskRdbStore::LookUp(const std::string &parentCloudId,
202     const std::string &fileName, CloudDiskFileInfo &info)
203 {
204     RDBPTR_IS_NULLPTR(rdbStore_);
205     if (fileName.empty() || parentCloudId.empty()) {
206         LOGE("look up parameters is invalid");
207         return E_INVAL_ARG;
208     }
209     AbsRdbPredicates lookUpPredicates = AbsRdbPredicates(FileColumn::FILES_TABLE);
210     lookUpPredicates
211         .EqualTo(FileColumn::PARENT_CLOUD_ID, parentCloudId)->And()
212         ->EqualTo(FileColumn::FILE_NAME, fileName)->And()->EqualTo(FileColumn::FILE_TIME_RECYCLED, "0")->And()
213         ->EqualTo(FileColumn::ROOT_DIRECTORY, bundleName_)->And()
214         ->NotEqualTo(FileColumn::DIRTY_TYPE, to_string(static_cast<int32_t>(DirtyType::TYPE_DELETED)));
215     lookUpPredicates.Limit(LOOKUP_QUERY_LIMIT);
216     auto resultSet = rdbStore_->QueryByStep(lookUpPredicates, FileColumn::FILE_SYSTEM_QUERY_COLUMNS);
217     int32_t ret = CloudDiskRdbUtils::ResultSetToFileInfo(move(resultSet), info);
218     if (ret != E_OK) {
219         LOGE("lookup file info is failed, ret %{public}d", ret);
220         return E_RDB;
221     }
222     return E_OK;
223 }
224 
GetAttr(const std::string & cloudId,CloudDiskFileInfo & info)225 int32_t CloudDiskRdbStore::GetAttr(const std::string &cloudId, CloudDiskFileInfo &info)
226 {
227     RDBPTR_IS_NULLPTR(rdbStore_);
228     if (cloudId.empty() || cloudId == ROOT_CLOUD_ID) {
229         LOGE("getAttr parameter is invalid");
230         return E_INVAL_ARG;
231     }
232     AbsRdbPredicates getAttrPredicates = AbsRdbPredicates(FileColumn::FILES_TABLE);
233     getAttrPredicates.EqualTo(FileColumn::CLOUD_ID, cloudId);
234     auto resultSet = rdbStore_->QueryByStep(getAttrPredicates, FileColumn::FILE_SYSTEM_QUERY_COLUMNS);
235     int32_t ret = CloudDiskRdbUtils::ResultSetToFileInfo(move(resultSet), info);
236     if (ret != E_OK) {
237         LOGE("get file attr is failed, ret %{public}d", ret);
238         return E_RDB;
239     }
240     return E_OK;
241 }
242 
SetAttr(const std::string & fileName,const std::string & parentCloudId,const std::string & cloudId,const unsigned long long & size)243 int32_t CloudDiskRdbStore::SetAttr(const std::string &fileName, const std::string &parentCloudId,
244     const std::string &cloudId, const unsigned long long &size)
245 {
246     RDBPTR_IS_NULLPTR(rdbStore_);
247     if (cloudId.empty()) {
248         LOGE("cloudId is empty");
249         return E_INVAL_ARG;
250     }
251     if (cloudId == ROOT_CLOUD_ID) {
252         LOGE("cloudId is rootId");
253         return E_INVAL_ARG;
254     }
255 
256     ValuesBucket setAttr;
257     setAttr.PutLong(FileColumn::FILE_SIZE, static_cast<int64_t>(size));
258     TransactionOperations rdbTransaction(rdbStore_);
259     auto [ret, transaction] = rdbTransaction.Start();
260     if (ret != E_OK) {
261         LOGE("rdbstore begin transaction failed, ret = %{public}d", ret);
262         return ret;
263     }
264     int32_t changedRows = -1;
265     NativeRdb::AbsRdbPredicates predicates = NativeRdb::AbsRdbPredicates(FileColumn::FILES_TABLE);
266     predicates.EqualTo(FileColumn::CLOUD_ID, cloudId);
267     std::tie(ret, changedRows) = transaction->Update(setAttr, predicates);
268     if (ret != E_OK) {
269         LOGE("setAttr size fail, ret: %{public}d, changeRow is %{public}d", ret, changedRows);
270         return E_RDB;
271     }
272 
273     MetaBase metaBase(fileName, cloudId);
274     metaBase.size = size;
275     auto callback = [&metaBase] (MetaBase &m) {
276         m.size = metaBase.size;
277     };
278     auto metaFile = MetaFileMgr::GetInstance().GetCloudDiskMetaFile(userId_, bundleName_, parentCloudId);
279     ret = metaFile->DoLookupAndUpdate(fileName, callback);
280     if (ret != E_OK) {
281         LOGE("update new dentry failed, ret = %{public}d", ret);
282         return ret;
283     }
284     rdbTransaction.Finish();
285     return E_OK;
286 }
287 
ReadDir(const std::string & cloudId,vector<CloudDiskFileInfo> & infos)288 int32_t CloudDiskRdbStore::ReadDir(const std::string &cloudId, vector<CloudDiskFileInfo> &infos)
289 {
290     RDBPTR_IS_NULLPTR(rdbStore_);
291     CLOUDID_IS_NULL(cloudId);
292     AbsRdbPredicates readDirPredicates = AbsRdbPredicates(FileColumn::FILES_TABLE);
293     readDirPredicates.EqualTo(FileColumn::PARENT_CLOUD_ID, cloudId)
294         ->And()->EqualTo(FileColumn::FILE_TIME_RECYCLED, "0")->And()
295         ->EqualTo(FileColumn::ROOT_DIRECTORY, bundleName_)->And()
296         ->NotEqualTo(FileColumn::DIRTY_TYPE, to_string(static_cast<int32_t>(DirtyType::TYPE_DELETED)));
297     auto resultSet = rdbStore_->QueryByStep(readDirPredicates, { FileColumn::FILE_NAME, FileColumn::IS_DIRECTORY });
298     int32_t ret = CloudDiskRdbUtils::ResultSetToFileInfos(move(resultSet), infos);
299     if (ret != E_OK) {
300         LOGE("read directory is failed, ret %{public}d", ret);
301         return E_RDB;
302     }
303     return E_OK;
304 }
305 
GetFileExtension(const std::string & fileName,std::string & extension)306 static int32_t GetFileExtension(const std::string &fileName, std::string &extension)
307 {
308     size_t dotIndex = fileName.rfind(".");
309     if (dotIndex != string::npos) {
310         extension = fileName.substr(dotIndex + 1);
311         return E_OK;
312     }
313     LOGE("Failed to obtain file extension");
314     return E_INVAL_ARG;
315 }
316 
FillFileType(const std::string & fileName,ValuesBucket & fileInfo)317 static void FillFileType(const std::string &fileName, ValuesBucket &fileInfo)
318 {
319     string extension;
320     if (!GetFileExtension(fileName, extension)) {
321         fileInfo.PutString(FileColumn::FILE_CATEGORY, extension);
322     }
323 }
324 
UTCTimeMilliSeconds()325 static int64_t UTCTimeMilliSeconds()
326 {
327     struct timespec t;
328     clock_gettime(CLOCK_REALTIME, &t);
329     return t.tv_sec * SECOND_TO_MILLISECOND + t.tv_nsec / MILLISECOND_TO_NANOSECOND;
330 }
331 
CheckNameForSpace(const std::string & fileName,const int32_t isDir)332 static int32_t CheckNameForSpace(const std::string& fileName, const int32_t isDir)
333 {
334     if (fileName.empty()) {
335         return EINVAL;
336     }
337     if (fileName[0] == ' ') {
338         LOGI("Illegal name");
339         return EINVAL;
340     }
341     if (isDir == DIRECTORY) {
342         if ((fileName.length() >= 1 && fileName[fileName.length() - 1] == ' ') || fileName == RECYCLE_FILE_NAME) {
343             LOGI("Illegal name");
344             return EINVAL;
345         }
346     }
347     return E_OK;
348 }
349 
CheckName(const std::string & fileName)350 static int32_t CheckName(const std::string &fileName)
351 {
352     if (fileName.empty() ||
353         fileName == "." ||
354         fileName == ".." ||
355         fileName.length() > MAX_FILE_NAME_SIZE) {
356         return EINVAL;
357     }
358     std::map<char, bool> illegalCharacter = {
359         {'<', true},
360         {'>', true},
361         {'|', true},
362         {':', true},
363         {'?', true},
364         {'/', true},
365         {'\\', true},
366         {'"', true},
367         {'*', true},
368     };
369     for (char c : fileName) {
370         if (illegalCharacter.find(c) != illegalCharacter.end()) {
371             LOGI("Illegal name");
372             return EINVAL;
373         }
374     }
375     return E_OK;
376 }
377 
CreateFile(const std::string & fileName,const std::string & filePath,ValuesBucket & fileInfo,struct stat * statInfo)378 static int32_t CreateFile(const std::string &fileName, const std::string &filePath, ValuesBucket &fileInfo,
379     struct stat *statInfo)
380 {
381     int32_t ret = stat(filePath.c_str(), statInfo);
382     if (ret) {
383         LOGE("filePath %{private}s is invalid", GetAnonyString(filePath).c_str());
384         return E_PATH;
385     }
386     fileInfo.PutInt(FileColumn::IS_DIRECTORY, FILE);
387     fileInfo.PutLong(FileColumn::FILE_SIZE, statInfo->st_size);
388     fileInfo.PutLong(FileColumn::FILE_TIME_EDITED, CloudFileUtils::Timespec2Milliseconds(statInfo->st_mtim));
389     fileInfo.PutLong(FileColumn::META_TIME_EDITED, CloudFileUtils::Timespec2Milliseconds(statInfo->st_mtim));
390     fileInfo.PutLong(FileColumn::LCD_FLAG, NO_THM_TO_DOWNLOAD);
391     fileInfo.PutLong(FileColumn::THM_FLAG, NO_THM_TO_DOWNLOAD);
392     FillFileType(fileName, fileInfo);
393     return E_OK;
394 }
395 
CreateDentry(MetaBase & metaBase,uint32_t userId,const std::string & bundleName,const std::string & fileName,const std::string & parentCloudId)396 static int32_t CreateDentry(MetaBase &metaBase, uint32_t userId, const std::string &bundleName,
397     const std::string &fileName, const std::string &parentCloudId)
398 {
399     auto callback = [&metaBase] (MetaBase &m) {
400         m.cloudId = metaBase.cloudId;
401         m.atime = metaBase.atime;
402         m.mtime = metaBase.mtime;
403         m.size = metaBase.size;
404         m.mode = metaBase.mode;
405         m.position = metaBase.position;
406         m.fileType = metaBase.fileType;
407         m.noUpload = metaBase.noUpload;
408     };
409     auto metaFile = MetaFileMgr::GetInstance().GetCloudDiskMetaFile(userId, bundleName, parentCloudId);
410     int32_t ret = metaFile->DoLookupAndUpdate(fileName, callback);
411     if (ret != E_OK) {
412         LOGE("update new dentry failed, ret = %{public}d", ret);
413         return ret;
414     }
415     return E_OK;
416 }
417 
UpdateMetabase(MetaBase & metaBase,int64_t fileTimeAdded,struct stat * statInfo)418 static void UpdateMetabase(MetaBase &metaBase, int64_t fileTimeAdded, struct stat *statInfo)
419 {
420     metaBase.atime = static_cast<uint64_t>(fileTimeAdded);
421     metaBase.mtime = static_cast<uint64_t>(CloudFileUtils::Timespec2Milliseconds(statInfo->st_mtim));
422     metaBase.mode = statInfo->st_mode;
423     metaBase.size = static_cast<uint64_t>(statInfo->st_size);
424     metaBase.position = LOCAL;
425     metaBase.fileType = FILE_TYPE_CONTENT;
426 }
427 
HandleCreateValue(ValuesBucket & fileInfo,const std::string & cloudId,const std::string & parentCloudId,const std::string & fileName,const std::string & bundleName)428 static void HandleCreateValue(ValuesBucket &fileInfo, const std::string &cloudId, const std::string &parentCloudId,
429                               const std::string &fileName, const std::string &bundleName)
430 {
431     fileInfo.PutString(FileColumn::CLOUD_ID, cloudId);
432     fileInfo.PutString(FileColumn::FILE_NAME, fileName);
433     fileInfo.PutString(FileColumn::PARENT_CLOUD_ID, parentCloudId);
434     fileInfo.PutInt(FileColumn::DIRTY_TYPE, static_cast<int32_t>(DirtyType::TYPE_NO_NEED_UPLOAD));
435     fileInfo.PutLong(FileColumn::OPERATE_TYPE, static_cast<int64_t>(OperationType::NEW));
436     fileInfo.PutString(FileColumn::ROOT_DIRECTORY, bundleName);
437 }
438 
Create(const std::string & cloudId,const std::string & parentCloudId,const std::string & fileName,bool noNeedUpload)439 int32_t CloudDiskRdbStore::Create(const std::string &cloudId, const std::string &parentCloudId,
440     const std::string &fileName, bool noNeedUpload)
441 {
442     int32_t ret = CheckName(fileName);
443     if (ret != E_OK) {
444         return ret;
445     }
446     ret = CheckNameForSpace(fileName, FILE);
447     if (ret != E_OK) {
448         return ret;
449     }
450     RDBPTR_IS_NULLPTR(rdbStore_);
451     ValuesBucket fileInfo;
452     if (cloudId.empty() || parentCloudId.empty() || fileName.empty()) {
453         LOGE("create parameter is invalid");
454         return E_INVAL_ARG;
455     }
456 
457     MetaBase metaBase(fileName, cloudId);
458     if (noNeedUpload) {
459         fileInfo.PutInt(FileColumn::NO_NEED_UPLOAD, NO_UPLOAD);
460         metaBase.noUpload = NO_UPLOAD;
461     }
462 
463     int64_t fileTimeAdded = UTCTimeMilliSeconds();
464     fileInfo.PutLong(FileColumn::FILE_TIME_ADDED, fileTimeAdded);
465     HandleCreateValue(fileInfo, cloudId, parentCloudId, fileName, bundleName_);
466     struct stat statInfo {};
467     string filePath = CloudFileUtils::GetLocalFilePath(cloudId, bundleName_, userId_);
468     if (CreateFile(fileName, filePath, fileInfo, &statInfo)) {
469         LOGE("file path is invalid, cannot create file record");
470         return E_PATH;
471     }
472     TransactionOperations rdbTransaction(rdbStore_);
473     auto [rdbRet, transaction] = rdbTransaction.Start();
474     if (rdbRet != E_OK) {
475         LOGE("rdbstore begin transaction failed, ret = %{public}d", ret);
476         return E_RDB;
477     }
478     int64_t outRowId = 0;
479     std::tie(rdbRet, outRowId) = transaction->Insert(FileColumn::FILES_TABLE, fileInfo);
480     if (rdbRet != E_OK) {
481         LOGE("insert new file record in DB is failed, ret = %{public}d", ret);
482         return rdbRet;
483     }
484 
485     UpdateMetabase(metaBase, fileTimeAdded, &statInfo);
486     ret = CreateDentry(metaBase, userId_, bundleName_, fileName, parentCloudId);
487     if (ret != E_OK) {
488         LOGE("create new dentry failed, ret = %{public}d", ret);
489         return ret;
490     }
491     rdbTransaction.Finish();
492     return E_OK;
493 }
494 
MkDir(const std::string & cloudId,const std::string & parentCloudId,const std::string & directoryName,bool noNeedUpload)495 int32_t CloudDiskRdbStore::MkDir(const std::string &cloudId, const std::string &parentCloudId,
496     const std::string &directoryName, bool noNeedUpload)
497 {
498     int32_t ret = CheckName(directoryName);
499     if (ret != E_OK) {
500         return ret;
501     }
502     ret = CheckNameForSpace(directoryName, DIRECTORY);
503     if (ret != E_OK) {
504         return ret;
505     }
506     RDBPTR_IS_NULLPTR(rdbStore_);
507     ValuesBucket dirInfo;
508     if (cloudId.empty() || parentCloudId.empty() || directoryName.empty()) {
509         LOGE("make directory parameter is invalid");
510         return E_INVAL_ARG;
511     }
512 
513     MetaBase metaBase(directoryName, cloudId);
514     if (noNeedUpload) {
515         dirInfo.PutInt(FileColumn::NO_NEED_UPLOAD, NO_UPLOAD);
516         metaBase.noUpload = NO_UPLOAD;
517     }
518 
519     dirInfo.PutString(FileColumn::CLOUD_ID, cloudId);
520     dirInfo.PutString(FileColumn::FILE_NAME, directoryName);
521     int64_t fileTimeAdded = UTCTimeMilliSeconds();
522     dirInfo.PutLong(FileColumn::FILE_TIME_ADDED, fileTimeAdded);
523     int64_t fileTimeEdited = UTCTimeMilliSeconds();
524     dirInfo.PutLong(FileColumn::FILE_TIME_EDITED, fileTimeEdited);
525     int64_t metaTimeEdited = UTCTimeMilliSeconds();
526     dirInfo.PutLong(FileColumn::META_TIME_EDITED, metaTimeEdited);
527     dirInfo.PutInt(FileColumn::IS_DIRECTORY, DIRECTORY);
528     dirInfo.PutString(FileColumn::PARENT_CLOUD_ID, parentCloudId);
529     dirInfo.PutLong(FileColumn::OPERATE_TYPE, static_cast<int64_t>(OperationType::NEW));
530     dirInfo.PutInt(FileColumn::FILE_STATUS, FileStatus::TO_BE_UPLOADED);
531     dirInfo.PutString(FileColumn::ROOT_DIRECTORY, bundleName_);
532     TransactionOperations rdbTransaction(rdbStore_);
533     std::shared_ptr<Transaction> transaction;
534     std::tie(ret, transaction) = rdbTransaction.Start();
535     if (ret != E_OK) {
536         LOGE("rdbstore begin transaction failed, ret = %{public}d", ret);
537         return ret;
538     }
539     int64_t outRowId = 0;
540     std::tie(ret, outRowId) = transaction->Insert(FileColumn::FILES_TABLE, dirInfo);
541     if (ret != E_OK) {
542         LOGE("insert new directory record in DB is failed, ret = %{public}d", ret);
543         return ret;
544     }
545 
546     metaBase.atime = static_cast<uint64_t>(fileTimeAdded);
547     metaBase.mtime = static_cast<uint64_t>(fileTimeEdited);
548     metaBase.mode = S_IFDIR | STAT_MODE_DIR;
549     metaBase.position = LOCAL;
550     metaBase.fileType = FILE_TYPE_CONTENT;
551     ret = CreateDentry(metaBase, userId_, bundleName_, directoryName, parentCloudId);
552     if (ret != E_OK) {
553         LOGE("create new dentry failed, ret = %{public}d", ret);
554         return ret;
555     }
556     rdbTransaction.Finish();
557     if (!noNeedUpload) {
558         CloudDiskSyncHelper::GetInstance().RegisterTriggerSync(bundleName_, userId_);
559     }
560     return E_OK;
561 }
562 
HandleWriteValue(ValuesBucket & write,int32_t position,struct stat & statInfo)563 static void HandleWriteValue(ValuesBucket &write, int32_t position, struct stat &statInfo)
564 {
565     write.PutLong(FileColumn::FILE_SIZE, statInfo.st_size);
566     write.PutLong(FileColumn::FILE_TIME_EDITED, CloudFileUtils::Timespec2Milliseconds(statInfo.st_mtim));
567     write.PutLong(FileColumn::META_TIME_EDITED, CloudFileUtils::Timespec2Milliseconds(statInfo.st_mtim));
568     write.PutLong(FileColumn::FILE_TIME_VISIT, CloudFileUtils::Timespec2Milliseconds(statInfo.st_atim));
569     write.PutInt(FileColumn::FILE_STATUS, FileStatus::TO_BE_UPLOADED);
570     if (position != LOCAL) {
571         write.PutInt(FileColumn::DIRTY_TYPE, static_cast<int32_t>(DirtyType::TYPE_FDIRTY));
572         write.PutLong(FileColumn::OPERATE_TYPE, static_cast<int64_t>(OperationType::UPDATE));
573     } else {
574         write.PutInt(FileColumn::DIRTY_TYPE, static_cast<int32_t>(DirtyType::TYPE_NEW));
575     }
576 }
577 
WriteUpdateDentry(MetaBase & metaBase,uint32_t userId,const std::string & bundleName,const std::string & fileName,const std::string & parentCloudId)578 static int32_t WriteUpdateDentry(MetaBase &metaBase, uint32_t userId, const std::string &bundleName,
579     const std::string &fileName, const std::string &parentCloudId)
580 {
581     auto callback = [&metaBase] (MetaBase &m) {
582         m.mtime = metaBase.mtime;
583         m.size = metaBase.size;
584     };
585     auto metaFile = MetaFileMgr::GetInstance().GetCloudDiskMetaFile(userId, bundleName, parentCloudId);
586     LOGD("write update dentry start");
587     int32_t ret = metaFile->DoChildUpdate(fileName, callback);
588     if (ret != E_OK) {
589         LOGE("update new dentry failed, ret = %{public}d", ret);
590         return ret;
591     }
592     return ret;
593 }
594 
TriggerSyncForWrite(const std::string & fileName,const std::string & parentCloudId)595 void CloudDiskRdbStore::TriggerSyncForWrite(const std::string &fileName, const std::string &parentCloudId)
596 {
597     MetaBase metaBase(fileName);
598     auto metaFile = MetaFileMgr::GetInstance().GetCloudDiskMetaFile(userId_, bundleName_, parentCloudId);
599     int32_t ret = metaFile->DoLookup(metaBase);
600     if (ret != E_OK) {
601         LOGE("lookup dentry failed, ret = %{public}d", ret);
602         return;
603     }
604     if (metaBase.noUpload == NEED_UPLOAD) {
605         CloudDiskSyncHelper::GetInstance().RegisterTriggerSync(bundleName_, userId_);
606     }
607 }
608 
Write(const std::string & fileName,const std::string & parentCloudId,const std::string & cloudId)609 int32_t CloudDiskRdbStore::Write(const std::string &fileName, const std::string &parentCloudId,
610     const std::string &cloudId)
611 {
612     RDBPTR_IS_NULLPTR(rdbStore_);
613     if (cloudId.empty() || cloudId == ROOT_CLOUD_ID) {
614         LOGE("write parameter is invalid");
615         return E_INVAL_ARG;
616     }
617     TransactionOperations rdbTransaction(rdbStore_);
618     auto [ret, transaction] = rdbTransaction.Start();
619     if (ret != E_OK) {
620         LOGE("rdbstore begin transaction failed, ret = %{public}d", ret);
621         return ret;
622     }
623     string filePath = CloudFileUtils::GetLocalFilePath(cloudId, bundleName_, userId_);
624     struct stat statInfo {};
625     ret = stat(filePath.c_str(), &statInfo);
626     if (ret) {
627         LOGE("filePath %{private}s is invalid", GetAnonyString(filePath).c_str());
628         return E_PATH;
629     }
630     CloudDiskFileInfo info;
631     if (GetAttr(cloudId, info)) {
632         LOGE("get write cloudId info in DB fail");
633         return E_RDB;
634     }
635     int32_t position = static_cast<int32_t>(info.location);
636     ValuesBucket write;
637     HandleWriteValue(write, position, statInfo);
638     int32_t changedRows = -1;
639     NativeRdb::AbsRdbPredicates predicates = NativeRdb::AbsRdbPredicates(FileColumn::FILES_TABLE);
640     predicates.EqualTo(FileColumn::CLOUD_ID, cloudId);
641     std::tie(ret, changedRows) = transaction->Update(write, predicates);
642     if (ret != E_OK) {
643         LOGE("write file record in DB fail, ret %{public}d", ret);
644         return E_RDB;
645     }
646     MetaBase metaBase(fileName, cloudId);
647     metaBase.mtime = static_cast<uint64_t>(CloudFileUtils::Timespec2Milliseconds(statInfo.st_mtim));
648     metaBase.size = static_cast<uint64_t>(statInfo.st_size);
649     ret = WriteUpdateDentry(metaBase, userId_, bundleName_, fileName, parentCloudId);
650     if (ret != E_OK) {
651         LOGE("write update dentry failed, ret %{public}d", ret);
652         return E_RDB;
653     }
654     rdbTransaction.Finish();
655     TriggerSyncForWrite(fileName, parentCloudId);
656     return E_OK;
657 }
658 
LocationSetXattr(const std::string & name,const std::string & parentCloudId,const std::string & cloudId,const std::string & value)659 int32_t CloudDiskRdbStore::LocationSetXattr(const std::string &name, const std::string &parentCloudId,
660     const std::string &cloudId, const std::string &value)
661 {
662     RDBPTR_IS_NULLPTR(rdbStore_);
663     int32_t val = -1;
664     istringstream transfer(value);
665     transfer >> val;
666     if (val != LOCAL && val != CLOUD && val != LOCAL_AND_CLOUD) {
667         LOGE("setxattr unknown value");
668         return E_INVAL_ARG;
669     }
670     ValuesBucket setXAttr;
671     setXAttr.PutInt(FileColumn::POSITION, val);
672     int32_t changedRows = -1;
673     TransactionOperations rdbTransaction(rdbStore_);
674     auto [ret, transaction] = rdbTransaction.Start();
675     if (ret != E_OK) {
676         LOGE("rdbstore begin transaction failed, ret = %{public}d", ret);
677         return ret;
678     }
679     NativeRdb::AbsRdbPredicates predicates = NativeRdb::AbsRdbPredicates(FileColumn::FILES_TABLE);
680     predicates.EqualTo(FileColumn::CLOUD_ID, cloudId);
681     std::tie(ret, changedRows) = transaction->Update(setXAttr, predicates);
682     if (ret != E_OK) {
683         LOGE("set xAttr location fail, ret %{public}d", ret);
684         return E_RDB;
685     }
686     MetaBase metaBase(name, cloudId);
687     auto callback = [&val] (MetaBase &m) {
688         m.position = val;
689     };
690     auto metaFile = MetaFileMgr::GetInstance().GetCloudDiskMetaFile(userId_, bundleName_, parentCloudId);
691     ret = metaFile->DoLookupAndUpdate(name, callback);
692     if (ret != E_OK) {
693         LOGE("update new dentry failed, ret = %{public}d", ret);
694         return ret;
695     }
696     rdbTransaction.Finish();
697     return E_OK;
698 }
699 
UpdateTHMStatus(shared_ptr<CloudDiskMetaFile> metaFile,MetaBase & metaBase,int32_t status)700 int32_t CloudDiskRdbStore::UpdateTHMStatus(shared_ptr<CloudDiskMetaFile> metaFile,
701     MetaBase &metaBase, int32_t status)
702 {
703     ValuesBucket fileInfo;
704     if (metaBase.fileType == FILE_TYPE_THUMBNAIL) {
705         fileInfo.PutInt(FileColumn::THM_FLAG, status);
706     } else {
707         fileInfo.PutInt(FileColumn::LCD_FLAG, status);
708     }
709     string srcCloudId;
710     auto res = GetSrcCloudId(metaBase.cloudId, srcCloudId);
711     if (res != E_OK) {
712         return res;
713     }
714     TransactionOperations rdbTransaction(rdbStore_);
715     auto [ret, transaction] = rdbTransaction.Start();
716     if (ret != E_OK) {
717         LOGE("rdbstore begin transaction failed, ret = %{public}d", ret);
718         return ret;
719     }
720     int32_t changedRows = -1;
721     NativeRdb::AbsRdbPredicates predicates = NativeRdb::AbsRdbPredicates(FileColumn::FILES_TABLE);
722     predicates.EqualTo(FileColumn::CLOUD_ID, srcCloudId);
723     std::tie(ret, changedRows) = transaction->Update(fileInfo, predicates);
724     if (ret != E_OK) {
725         LOGE("set thm_flag failed, ret = %{public}d", ret);
726         return E_RDB;
727     }
728     ValuesBucket thmFileInfo;
729     thmFileInfo.PutInt(FileColumn::POSITION, static_cast<int32_t>(ThumbPosition::THM_IN_LOCAL));
730     NativeRdb::AbsRdbPredicates thmPredicates = NativeRdb::AbsRdbPredicates(FileColumn::FILES_TABLE);
731     thmPredicates.EqualTo(FileColumn::CLOUD_ID, metaBase.cloudId);
732     std::tie(ret, changedRows) = transaction->Update(thmFileInfo, thmPredicates);
733     if (ret != E_OK) {
734         LOGE("database update thumbnail file info failed, ret = %{public}d", ret);
735     }
736     auto callback = [&metaBase] (MetaBase &m) {
737         m.position = static_cast<uint8_t>(ThumbPosition::THM_IN_LOCAL);
738     };
739     ret = metaFile->DoChildUpdate(metaBase.name, callback);
740     if (ret != E_OK) {
741         LOGE("update dentry failed");
742     }
743     rdbTransaction.Finish();
744     return E_OK;
745 }
746 
HasTHMSetXattr(const std::string & name,const std::string & key,const std::string & cloudId,const std::string & value)747 int32_t CloudDiskRdbStore::HasTHMSetXattr(const std::string &name, const std::string &key,
748     const std::string &cloudId, const std::string &value)
749 {
750     RDBPTR_IS_NULLPTR(rdbStore_);
751     if (!all_of(value.begin(), value.end(), ::isdigit)) {
752         return E_INVAL_ARG;
753     }
754     int32_t val = std::stoi(value);
755     if (val != 0 && val != 1) {
756         LOGE("setxattr unknown value");
757         return E_INVAL_ARG;
758     }
759 
760     ValuesBucket setXAttr;
761     if (val == 0) {
762         if (key == CLOUD_HAS_LCD) {
763             setXAttr.PutInt(FileColumn::LCD_FLAG, NO_THM_TO_DOWNLOAD);
764         } else {
765             setXAttr.PutInt(FileColumn::THM_FLAG, NO_THM_TO_DOWNLOAD);
766         }
767     } else {
768         if (key == CLOUD_HAS_LCD) {
769             setXAttr.PutInt(FileColumn::LCD_FLAG, DOWNLOADED_THM);
770         } else {
771             setXAttr.PutInt(FileColumn::THM_FLAG, DOWNLOADED_THM);
772         }
773     }
774     int32_t dirtyType;
775     TransactionOperations rdbTransaction(rdbStore_);
776     auto [ret, transaction] = rdbTransaction.Start();
777     RETURN_ON_ERR(GetDirtyType(cloudId, dirtyType));
778     if (dirtyType == static_cast<int32_t>(DirtyType::TYPE_SYNCED)) {
779         setXAttr.PutInt(FileColumn::DIRTY_TYPE, static_cast<int32_t>(DirtyType::TYPE_MDIRTY));
780     }
781     int32_t changedRows = -1;
782     NativeRdb::AbsRdbPredicates predicates = NativeRdb::AbsRdbPredicates(FileColumn::FILES_TABLE);
783     predicates.EqualTo(FileColumn::CLOUD_ID, cloudId);
784     std::tie(ret, changedRows) = transaction->Update(setXAttr, predicates);
785     if (ret != E_OK) {
786         LOGE("set xAttr thm_flag fail, ret %{public}d", ret);
787         return E_RDB;
788     }
789     rdbTransaction.Finish();
790     CloudDiskSyncHelper::GetInstance().RegisterTriggerSync(bundleName_, userId_);
791     return E_OK;
792 }
793 
GetRowId(const std::string & cloudId,int64_t & rowId)794 int32_t CloudDiskRdbStore::GetRowId(const std::string &cloudId, int64_t &rowId)
795 {
796     RDBPTR_IS_NULLPTR(rdbStore_);
797     CLOUDID_IS_NULL(cloudId);
798     AbsRdbPredicates getRowIdPredicates = AbsRdbPredicates(FileColumn::FILES_TABLE);
799     getRowIdPredicates.EqualTo(FileColumn::CLOUD_ID, cloudId);
800     auto resultSet = rdbStore_->QueryByStep(getRowIdPredicates, {FileColumn::ROW_ID});
801     if (resultSet == nullptr) {
802         LOGE("get nullptr result set");
803         return E_RDB;
804     }
805     if (resultSet->GoToNextRow() != E_OK) {
806         LOGE("getRowId result set go to next row failed");
807         return E_RDB;
808     }
809     CloudDiskRdbUtils::GetLong(FileColumn::ROW_ID, rowId, resultSet);
810     return E_OK;
811 }
812 
RecycleSetValue(TrashOptType val,ValuesBucket & setXAttr,int32_t position,int32_t dirtyType)813 static int32_t RecycleSetValue(TrashOptType val, ValuesBucket &setXAttr, int32_t position, int32_t dirtyType)
814 {
815     if (position != LOCAL) {
816         if (dirtyType != static_cast<int32_t>(DirtyType::TYPE_FDIRTY)) {
817             setXAttr.PutInt(FileColumn::DIRTY_TYPE, static_cast<int32_t>(DirtyType::TYPE_MDIRTY));
818         }
819     } else {
820         setXAttr.PutInt(FileColumn::OPERATE_TYPE, static_cast<int32_t>(OperationType::NEW));
821     }
822     if (val == TrashOptType::RESTORE) {
823         setXAttr.PutInt(FileColumn::OPERATE_TYPE, static_cast<int32_t>(OperationType::RESTORE));
824         setXAttr.PutLong(FileColumn::FILE_TIME_RECYCLED, CANCEL_STATE);
825         setXAttr.PutInt(FileColumn::DIRECTLY_RECYCLED, CANCEL_STATE);
826         setXAttr.PutLong(FileColumn::META_TIME_EDITED, UTCTimeMilliSeconds());
827     } else if (val == TrashOptType::RECYCLE) {
828         int64_t recycledTime = UTCTimeMilliSeconds();
829         setXAttr.PutInt(FileColumn::OPERATE_TYPE, static_cast<int32_t>(OperationType::DELETE));
830         setXAttr.PutLong(FileColumn::FILE_TIME_RECYCLED, recycledTime);
831         setXAttr.PutInt(FileColumn::DIRECTLY_RECYCLED, SET_STATE);
832         setXAttr.PutLong(FileColumn::META_TIME_EDITED, recycledTime);
833     } else {
834         LOGE("invalid value");
835         return E_RDB;
836     }
837     return E_OK;
838 }
839 
GetParentCloudId(const std::string & cloudId,std::string & parentCloudId)840 int32_t CloudDiskRdbStore::GetParentCloudId(const std::string &cloudId, std::string &parentCloudId)
841 {
842     RDBPTR_IS_NULLPTR(rdbStore_);
843     AbsRdbPredicates getParentCloudIdPredicates = AbsRdbPredicates(FileColumn::FILES_TABLE);
844     getParentCloudIdPredicates.EqualTo(FileColumn::CLOUD_ID, cloudId);
845     auto resultSet = rdbStore_->QueryByStep(getParentCloudIdPredicates, { FileColumn::PARENT_CLOUD_ID });
846     if (resultSet == nullptr) {
847         LOGE("get nullptr parentCloudId resultSet");
848         return E_RDB;
849     }
850     if (resultSet->GoToNextRow() != E_OK) {
851         LOGE("get parentCloudId go to next row failed");
852         return E_RDB;
853     }
854     int32_t ret = CloudDiskRdbUtils::GetString(FileColumn::PARENT_CLOUD_ID, parentCloudId, resultSet);
855     if (ret != E_OK) {
856         LOGE("get parent cloudId failed");
857         return ret;
858     }
859     return E_OK;
860 }
861 
ConvertUriToSrcPath(const string & uriStr)862 static string ConvertUriToSrcPath(const string &uriStr)
863 {
864     Uri uri(uriStr);
865     string scheme = uri.GetScheme();
866     if (scheme != FILE_SCHEME) {
867         return "/";
868     }
869     const string sandboxPrefix = "/data/storage/el2/cloud";
870     string filePath = uri.GetPath().substr(sandboxPrefix.length());
871     size_t pos = filePath.rfind("/");
872     filePath = pos == 0 ? "/" : filePath.substr(0, pos);
873     return filePath;
874 }
875 
GetSourcePath(const string & attr,const string & parentCloudId,string & sourcePath)876 int32_t CloudDiskRdbStore::GetSourcePath(const string &attr, const string &parentCloudId, string &sourcePath)
877 {
878     nlohmann::json jsonObject = nlohmann::json::parse(attr, nullptr, false);
879     if (jsonObject.is_discarded() || (!jsonObject.is_object())) {
880         LOGD("jsonObject is discarded");
881         jsonObject = nlohmann::json::object();
882     }
883     if (jsonObject.contains(SRC_PATH_KEY) && jsonObject[SRC_PATH_KEY].is_string()) {
884         sourcePath = jsonObject[SRC_PATH_KEY].get<std::string>();
885         return E_OK;
886     }
887 
888     string uri;
889     int32_t ret = GetUriFromDB(parentCloudId, uri);
890     if (ret == E_OK) {
891         sourcePath == ConvertUriToSrcPath(uri);
892     } else {
893         LOGI("file src path fail, restore to root dir");
894     }
895     return E_OK;
896 }
897 
SourcePathSetValue(const string & cloudId,const string & attr,ValuesBucket & setXattr)898 int32_t CloudDiskRdbStore::SourcePathSetValue(const string &cloudId, const string &attr, ValuesBucket &setXattr)
899 {
900     RDBPTR_IS_NULLPTR(rdbStore_);
901     string uri;
902     CacheNode cacheNode = {cloudId};
903     RETURN_ON_ERR(GetCurNode(cloudId, cacheNode));
904     int32_t ret = GetNotifyUri(cacheNode, uri);
905     if (ret != E_OK) {
906         LOGE("failed to get source path, ret=%{public}d", ret);
907         return ret;
908     }
909     string filePath = ConvertUriToSrcPath(uri);
910     nlohmann::json jsonObject = nlohmann::json::parse(attr, nullptr, false);
911     if (jsonObject.is_discarded() || (!jsonObject.is_object())) {
912         LOGD("jsonObject is discarded");
913         jsonObject = nlohmann::json::object();
914     }
915     jsonObject[SRC_PATH_KEY] = filePath;
916     string attrStr;
917     try {
918         attrStr = jsonObject.dump();
919     } catch (nlohmann::json::type_error& err) {
920         LOGE("failed to dump json object, reason: %{public}s", err.what());
921         return E_INVAL_ARG;
922     }
923     setXattr.PutString(FileColumn::ATTRIBUTE, attrStr);
924     return E_OK;
925 }
926 
UpdateParent(const int32_t userId,const string & bundleName,const string & srcPath,string & parentCloudId)927 static int32_t UpdateParent(const int32_t userId, const string &bundleName, const string &srcPath,
928     string &parentCloudId)
929 {
930     // root dir no need create
931     if (srcPath.empty() || srcPath == "/") {
932         parentCloudId = ROOT_CLOUD_ID;
933         return E_OK;
934     }
935 
936     string parentDir = LOCAL_PATH_MNT_HMDFS + to_string(userId) + LOCAL_PATH_CLOUD_DATA + bundleName + srcPath;
937     if (!ForceCreateDirectory(parentDir)) {
938         LOGE("create parent dir fail, %{public}s", GetAnonyString(parentDir).c_str());
939         return errno;
940     }
941     parentCloudId = CloudFileUtils::GetCloudId(parentDir);
942     return E_OK;
943 }
944 
RecycleSetXattr(const std::string & name,const std::string & parentCloudId,const std::string & cloudId,const std::string & value)945 int32_t CloudDiskRdbStore::RecycleSetXattr(const std::string &name, const std::string &parentCloudId,
946     const std::string &cloudId, const std::string &value)
947 {
948     bool isNum = std::all_of(value.begin(), value.end(), ::isdigit);
949     if (!isNum) {
950         return EINVAL;
951     }
952     int32_t val = std::stoi(value);
953     if (val == static_cast<int32_t>(TrashOptType::RESTORE)) {
954         return HandleRestoreXattr(name, parentCloudId, cloudId);
955     }
956     if (val == static_cast<int32_t>(TrashOptType::RECYCLE)) {
957         return HandleRecycleXattr(name, parentCloudId, cloudId);
958     }
959     return EINVAL;
960 }
961 
CheckIsConflict(const string & name,const string & parentCloudId,string & newName)962 int32_t CloudDiskRdbStore::CheckIsConflict(const string &name, const string &parentCloudId, string &newName)
963 {
964     MetaBase metaBase(name);
965     auto metaFile = MetaFileMgr::GetInstance().GetCloudDiskMetaFile(userId_, bundleName_, parentCloudId);
966     int32_t ret = metaFile->DoLookup(metaBase);
967     if (ret != E_OK) {
968         if (ret == ENOENT) {
969             LOGI("no conflict file at target dir.");
970             return E_OK;
971         }
972         LOGE("lookup conflict name fail, ret = %{public}d", ret);
973         return ret;
974     }
975 
976     RETURN_ON_ERR(MetaFileMgr::GetInstance().GetNewName(metaFile, name, newName));
977 
978     return E_OK;
979 }
980 
RestoreUpdateRdb(const string & cloudId,const struct RestoreInfo & restoreInfo,const ValuesBucket & setXattr)981 int32_t CloudDiskRdbStore::RestoreUpdateRdb(const string &cloudId, const struct RestoreInfo &restoreInfo,
982     const ValuesBucket &setXattr)
983 {
984     TransactionOperations rdbTransactionUpdate(rdbStore_);
985     auto [ret, transaction] = rdbTransactionUpdate.Start();
986     if (ret != E_OK) {
987         LOGE("rdbstore begin transaction failed, ret = %{public}d", ret);
988         return ret;
989     }
990 
991     NativeRdb::AbsRdbPredicates predicates = NativeRdb::AbsRdbPredicates(FileColumn::FILES_TABLE);
992     predicates.EqualTo(FileColumn::CLOUD_ID, cloudId);
993 
994     int32_t changedRows = -1;
995     tie(ret, changedRows) = transaction->Update(setXattr, predicates);
996     if (ret != E_OK) {
997         LOGE("resotre update rdb failed, ret = %{public}d", ret);
998         return E_RDB;
999     }
1000 
1001     ret = MetaFileMgr::GetInstance().RemoveFromRecycleDentryfile(userId_, bundleName_, restoreInfo);
1002     if (ret != E_OK) {
1003         LOGE("recycled restore set dentry failed, ret = %{public}d", ret);
1004         return ret;
1005     }
1006     rdbTransactionUpdate.Finish();
1007 
1008     return E_OK;
1009 }
1010 
HandleRestoreXattr(const string & name,const string & parentCloudId,const string & cloudId)1011 int32_t CloudDiskRdbStore::HandleRestoreXattr(const string &name, const string &parentCloudId, const string &cloudId)
1012 {
1013     RDBPTR_IS_NULLPTR(rdbStore_);
1014     int64_t rowId = 0;
1015     int32_t position = -1;
1016     string attr;
1017     int32_t dirtyType = static_cast<int32_t>(DirtyType::TYPE_SYNCED);
1018     TransactionOperations rdbTransaction(rdbStore_);
1019     auto [ret, transaction] = rdbTransaction.Start();
1020     if (ret != E_OK) {
1021         LOGE("rdbstore begin transaction failed, ret = %{public}d", ret);
1022         return ret;
1023     }
1024     ret = GetRecycleInfo(transaction, cloudId, rowId, position, attr, dirtyType);
1025     if (ret != E_OK) {
1026         LOGE("get recycle fields fail, ret %{public}d", ret);
1027         return E_RDB;
1028     }
1029     rdbTransaction.Finish();
1030 
1031     string realParentCloudId = parentCloudId;
1032     string srcPath = "/";
1033     RETURN_ON_ERR(GetSourcePath(attr, parentCloudId, srcPath));
1034     RETURN_ON_ERR(UpdateParent(userId_, bundleName_, srcPath, realParentCloudId));
1035 
1036     string newName = name;
1037     RETURN_ON_ERR(CheckIsConflict(name, realParentCloudId, newName));
1038 
1039     ValuesBucket setXAttr;
1040     setXAttr.PutString(FileColumn::PARENT_CLOUD_ID, realParentCloudId);
1041     setXAttr.PutString(FileColumn::FILE_NAME, newName);
1042     RETURN_ON_ERR(RecycleSetValue(TrashOptType::RESTORE, setXAttr, position, dirtyType));
1043     struct RestoreInfo restoreInfo = {name, realParentCloudId, newName, rowId};
1044     ret = RestoreUpdateRdb(cloudId, restoreInfo, setXAttr);
1045     if (ret != E_OK) {
1046         LOGE("handle restore rdb update fail, ret = %{public}d", ret);
1047         return ret;
1048     }
1049     CloudDiskSyncHelper::GetInstance().RegisterTriggerSync(bundleName_, userId_);
1050     return E_OK;
1051 }
1052 
HandleRecycleXattr(const string & name,const string & parentCloudId,const string & cloudId)1053 int32_t CloudDiskRdbStore::HandleRecycleXattr(const string &name, const string &parentCloudId, const string &cloudId)
1054 {
1055     RDBPTR_IS_NULLPTR(rdbStore_);
1056     int64_t rowId = 0;
1057     int32_t position = -1;
1058     string attr;
1059     int32_t dirtyType = static_cast<int32_t>(DirtyType::TYPE_SYNCED);
1060     TransactionOperations rdbTransaction(rdbStore_);
1061     auto [ret, transaction] = rdbTransaction.Start();
1062     if (ret != E_OK) {
1063         LOGE("rdbstore begin transaction failed, ret = %{public}d", ret);
1064         return ret;
1065     }
1066     ret = GetRecycleInfo(transaction, cloudId, rowId, position, attr, dirtyType);
1067     if (ret != E_OK) {
1068         LOGE("get rowId and position fail, ret %{public}d", ret);
1069         return E_RDB;
1070     }
1071     ValuesBucket setXAttr;
1072     SourcePathSetValue(cloudId, attr, setXAttr);
1073     ret = RecycleSetValue(TrashOptType::RECYCLE, setXAttr, position, dirtyType);
1074     if (ret != E_OK) {
1075         return ret;
1076     }
1077     NativeRdb::AbsRdbPredicates predicates = NativeRdb::AbsRdbPredicates(FileColumn::FILES_TABLE);
1078     predicates.EqualTo(FileColumn::CLOUD_ID, cloudId);
1079     int32_t changedRows = -1;
1080     std::tie(ret, changedRows) = transaction->Update(setXAttr, predicates);
1081     if (ret != E_OK) {
1082         LOGE("set xAttr location fail, ret %{public}d", ret);
1083         return E_RDB;
1084     }
1085     struct RestoreInfo restoreInfo = {name, parentCloudId, name, rowId};
1086     ret = MetaFileMgr::GetInstance().MoveIntoRecycleDentryfile(userId_, bundleName_, restoreInfo);
1087     if (ret != E_OK) {
1088         LOGE("recycle set dentryfile failed, ret = %{public}d", ret);
1089         return ret;
1090     }
1091     rdbTransaction.Finish();
1092     CloudDiskSyncHelper::GetInstance().RegisterTriggerSync(bundleName_, userId_);
1093     return E_OK;
1094 }
1095 
GetRecycleInfo(shared_ptr<Transaction> transaction,const std::string & cloudId,int64_t & rowId,int32_t & position,string & attr,int32_t & dirtyType)1096 int32_t CloudDiskRdbStore::GetRecycleInfo(shared_ptr<Transaction> transaction, const std::string &cloudId,
1097     int64_t &rowId, int32_t &position, string &attr, int32_t &dirtyType)
1098 {
1099     RDBPTR_IS_NULLPTR(rdbStore_);
1100     CLOUDID_IS_NULL(cloudId);
1101     AbsRdbPredicates getRowIdAndPositionPredicates = AbsRdbPredicates(FileColumn::FILES_TABLE);
1102     getRowIdAndPositionPredicates.EqualTo(FileColumn::CLOUD_ID, cloudId);
1103     auto resultSet = transaction->QueryByStep(getRowIdAndPositionPredicates,
1104                                               {FileColumn::ROW_ID, FileColumn::POSITION, FileColumn::ATTRIBUTE,
1105                                                FileColumn::DIRTY_TYPE});
1106     if (resultSet == nullptr) {
1107         LOGE("get nullptr result set");
1108         return E_RDB;
1109     }
1110     if (resultSet->GoToNextRow() != E_OK) {
1111         LOGE("getRowIdAndPositionPredicates result set go to next row failed");
1112         return E_RDB;
1113     }
1114     int32_t ret = CloudDiskRdbUtils::GetLong(FileColumn::ROW_ID, rowId, resultSet);
1115     if (ret != E_OK) {
1116         LOGE("get rowId failed");
1117         return ret;
1118     }
1119     ret = CloudDiskRdbUtils::GetInt(FileColumn::POSITION, position, resultSet);
1120     if (ret != E_OK) {
1121         LOGE("get position failed");
1122         return ret;
1123     }
1124     ret = CloudDiskRdbUtils::GetString(FileColumn::ATTRIBUTE, attr, resultSet);
1125     if (ret != E_OK) {
1126         LOGE("get file attribute failed");
1127         return ret;
1128     }
1129     ret = CloudDiskRdbUtils::GetInt(FileColumn::DIRTY_TYPE, dirtyType, resultSet);
1130     if (ret != E_OK) {
1131         LOGE("get dirtyType failed");
1132         return ret;
1133     }
1134     return E_OK;
1135 }
1136 
FavoriteSetXattr(const std::string & cloudId,const std::string & value)1137 int32_t CloudDiskRdbStore::FavoriteSetXattr(const std::string &cloudId, const std::string &value)
1138 {
1139     LOGD("favoriteSetXattr, value %{public}s", value.c_str());
1140     RDBPTR_IS_NULLPTR(rdbStore_);
1141     bool isNum = std::all_of(value.begin(), value.end(), ::isdigit);
1142     if (!isNum) {
1143         return EINVAL;
1144     }
1145     int32_t val = std::stoi(value);
1146     ValuesBucket setXAttr;
1147     if (val == 0) {
1148         setXAttr.PutInt(FileColumn::IS_FAVORITE, CANCEL_STATE);
1149         setXAttr.PutLong(FileColumn::META_TIME_EDITED, UTCTimeMilliSeconds());
1150     } else if (val == 1) {
1151         setXAttr.PutInt(FileColumn::IS_FAVORITE, SET_STATE);
1152         setXAttr.PutLong(FileColumn::META_TIME_EDITED, UTCTimeMilliSeconds());
1153     } else {
1154         return E_RDB;
1155     }
1156     int32_t changedRows = -1;
1157     vector<ValueObject> bindArgs;
1158     bindArgs.emplace_back(cloudId);
1159     int32_t ret = rdbStore_->Update(changedRows, FileColumn::FILES_TABLE, setXAttr,
1160         FileColumn::CLOUD_ID + " = ?", bindArgs);
1161     if (ret != E_OK) {
1162         LOGE("set xAttr location fail, ret %{public}d", ret);
1163         return E_RDB;
1164     }
1165     return E_OK;
1166 }
1167 
CheckXattr(const std::string & key)1168 int32_t CheckXattr(const std::string &key)
1169 {
1170     if (key == CLOUD_FILE_LOCATION) {
1171         return CLOUD_LOCATION;
1172     } else if (key == CLOUD_CLOUD_RECYCLE_XATTR) {
1173         return CLOUD_RECYCLE;
1174     } else if (key == IS_FAVORITE_XATTR) {
1175         return IS_FAVORITE;
1176     } else if (key == IS_FILE_STATUS_XATTR) {
1177         return FILE_SYNC_STATUS;
1178     } else if (key == CLOUD_EXT_ATTR) {
1179         return IS_EXT_ATTR;
1180     } else if (key == CLOUD_HAS_LCD || key == CLOUD_HAS_THM) {
1181         return HAS_THM;
1182     } else if (key == CLOUD_TIME_RECYCLED) {
1183         return TIME_RECYCLED;
1184     } else if (key == CLOUD_RECYCLE_PATH) {
1185         return RECYCLE_PATH;
1186     } else {
1187         return ERROR_CODE;
1188     }
1189 }
1190 
LocationGetXattr(const std::string & name,const std::string & key,std::string & value,const std::string & parentCloudId)1191 int32_t CloudDiskRdbStore::LocationGetXattr(const std::string &name, const std::string &key, std::string &value,
1192     const std::string &parentCloudId)
1193 {
1194     if (key != CLOUD_FILE_LOCATION) {
1195         LOGE("getxattr parameter is invalid");
1196         return E_INVAL_ARG;
1197     }
1198     MetaBase metaBase(name);
1199     auto metaFile = MetaFileMgr::GetInstance().GetCloudDiskMetaFile(userId_, bundleName_, parentCloudId);
1200     int32_t ret = metaFile->DoLookup(metaBase);
1201     if (ret != E_OK) {
1202         LOGE("lookup dentry failed, ret = %{public}d", ret);
1203         return ENOENT;
1204     }
1205     value = std::to_string(metaBase.position);
1206     return E_OK;
1207 }
1208 
FavoriteGetXattr(const std::string & cloudId,const std::string & key,std::string & value)1209 int32_t CloudDiskRdbStore::FavoriteGetXattr(const std::string &cloudId, const std::string &key, std::string &value)
1210 {
1211     RDBPTR_IS_NULLPTR(rdbStore_);
1212     if (cloudId.empty() || cloudId == ROOT_CLOUD_ID || key != IS_FAVORITE_XATTR) {
1213         LOGE("getxattr parameter is invalid");
1214         return E_INVAL_ARG;
1215     }
1216     AbsRdbPredicates getXAttrPredicates = AbsRdbPredicates(FileColumn::FILES_TABLE);
1217     getXAttrPredicates.EqualTo(FileColumn::CLOUD_ID, cloudId);
1218     auto resultSet = rdbStore_->QueryByStep(getXAttrPredicates, { FileColumn::IS_FAVORITE });
1219     if (resultSet == nullptr) {
1220         LOGE("get nullptr getxattr result");
1221         return E_RDB;
1222     }
1223     if (resultSet->GoToNextRow() != E_OK) {
1224         LOGE("getxattr result set go to next row failed");
1225         return E_RDB;
1226     }
1227     int32_t isFavorite;
1228     CloudDiskRdbUtils::GetInt(FileColumn::IS_FAVORITE, isFavorite, resultSet);
1229     value = to_string(isFavorite);
1230     return E_OK;
1231 }
1232 
FileStatusGetXattr(const std::string & cloudId,const std::string & key,std::string & value)1233 int32_t CloudDiskRdbStore::FileStatusGetXattr(const std::string &cloudId, const std::string &key, std::string &value)
1234 {
1235     RDBPTR_IS_NULLPTR(rdbStore_);
1236     if (cloudId.empty() || cloudId == ROOT_CLOUD_ID || key != IS_FILE_STATUS_XATTR) {
1237         LOGE("getxattr parameter is invalid");
1238         return E_INVAL_ARG;
1239     }
1240     AbsRdbPredicates getXAttrPredicates = AbsRdbPredicates(FileColumn::FILES_TABLE);
1241     getXAttrPredicates.EqualTo(FileColumn::CLOUD_ID, cloudId);
1242     auto resultSet = rdbStore_->QueryByStep(getXAttrPredicates, { FileColumn::FILE_STATUS });
1243     if (resultSet == nullptr) {
1244         LOGE("get nullptr getxattr result");
1245         return E_RDB;
1246     }
1247     if (resultSet->GoToNextRow() != E_OK) {
1248         LOGE("getxattr result set go to next row failed");
1249         return E_RDB;
1250     }
1251     int32_t fileStatus;
1252     int32_t ret = CloudDiskRdbUtils::GetInt(FileColumn::FILE_STATUS, fileStatus, resultSet);
1253     if (ret != E_OK) {
1254         LOGE("get file status failed");
1255         return ret;
1256     }
1257     value = to_string(fileStatus);
1258     return E_OK;
1259 }
1260 
TimeRecycledGetXattr(const string & cloudId,const string & key,string & value)1261 int32_t CloudDiskRdbStore::TimeRecycledGetXattr(const string &cloudId, const string &key, string &value)
1262 {
1263     RDBPTR_IS_NULLPTR(rdbStore_);
1264     if (cloudId.empty() || cloudId == ROOT_CLOUD_ID || key != CLOUD_TIME_RECYCLED) {
1265         LOGE("getxattr parameter is invalid");
1266         return E_INVAL_ARG;
1267     }
1268     AbsRdbPredicates getXAttrPredicates = AbsRdbPredicates(FileColumn::FILES_TABLE);
1269     getXAttrPredicates.EqualTo(FileColumn::CLOUD_ID, cloudId);
1270     auto resultSet = rdbStore_->QueryByStep(getXAttrPredicates, { FileColumn::FILE_TIME_RECYCLED });
1271     if (resultSet == nullptr) {
1272         LOGE("get nullptr getxattr result");
1273         return E_RDB;
1274     }
1275     if (resultSet->GoToNextRow() != E_OK) {
1276         LOGE("getxattr result set go to next row failed");
1277         return E_RDB;
1278     }
1279     int64_t timeRecycled = 0;
1280     CloudDiskRdbUtils::GetLong(FileColumn::FILE_TIME_RECYCLED, timeRecycled, resultSet);
1281     value = to_string(timeRecycled);
1282     return E_OK;
1283 }
1284 
GetExtAttrValue(const std::string & cloudId,const std::string & key,std::string & value)1285 int32_t CloudDiskRdbStore::GetExtAttrValue(const std::string &cloudId, const std::string &key, std::string &value)
1286 {
1287     if (cloudId.empty() || cloudId == ROOT_CLOUD_ID || key.empty()) {
1288         LOGE("get ext attr value parameter is invalid");
1289         return E_INVAL_ARG;
1290     }
1291 
1292     std::string res;
1293     int32_t pos = 0;
1294     int32_t dirtyType = static_cast<int32_t>(DirtyType::TYPE_SYNCED);
1295     int32_t ret = GetExtAttr(cloudId, res, pos, dirtyType);
1296     if (ret != E_OK || res.empty()) {
1297         LOGE("get ext attr value res is empty");
1298         return E_RDB;
1299     }
1300 
1301     nlohmann::json jsonObj = nlohmann::json::parse(res, nullptr, false);
1302     if (jsonObj.is_discarded()) {
1303         LOGE("get ext jsonObj parse failed");
1304         return E_RDB;
1305     }
1306 
1307     LOGD("GetExtAttrValue, name %{public}s", key.c_str());
1308     if (!jsonObj.contains(key) || !jsonObj[key].is_string()) {
1309         LOGE("get ext not a string");
1310         return E_RDB;
1311     }
1312 
1313     value = jsonObj[key].get<std::string>();
1314     return E_OK;
1315 }
1316 
GetExtAttr(const std::string & cloudId,std::string & value,int32_t & position,int32_t & dirtyType)1317 int32_t CloudDiskRdbStore::GetExtAttr(const std::string &cloudId, std::string &value, int32_t &position,
1318     int32_t &dirtyType)
1319 {
1320     RDBPTR_IS_NULLPTR(rdbStore_);
1321     if (cloudId.empty() || cloudId == ROOT_CLOUD_ID) {
1322         LOGE("get ext attr parameter is invalid");
1323         return E_INVAL_ARG;
1324     }
1325     AbsRdbPredicates getAttrPredicates = AbsRdbPredicates(FileColumn::FILES_TABLE);
1326     getAttrPredicates.EqualTo(FileColumn::CLOUD_ID, cloudId);
1327     auto resultSet = rdbStore_->QueryByStep(getAttrPredicates, FileColumn::EXT_ATTR_QUERY_COLUMNS);
1328     if (resultSet == nullptr) {
1329         LOGE("get nullptr get ext attr result");
1330         return E_RDB;
1331     }
1332     if (resultSet->GoToNextRow() != E_OK) {
1333         LOGE("get ext attr result set go to next row failed");
1334         return E_RDB;
1335     }
1336 
1337     int32_t ret = CloudDiskRdbUtils::GetString(FileColumn::ATTRIBUTE, value, resultSet);
1338     if (ret != E_OK) {
1339         LOGE("get ext attr value failed");
1340         return ret;
1341     }
1342 
1343     ret = CloudDiskRdbUtils::GetInt(FileColumn::POSITION, position, resultSet);
1344     if (ret != E_OK) {
1345         LOGE("get location value failed");
1346         return ret;
1347     }
1348 
1349     ret = CloudDiskRdbUtils::GetInt(FileColumn::DIRTY_TYPE, dirtyType, resultSet);
1350     if (ret != E_OK) {
1351         LOGE("get dirtyType value failed");
1352         return ret;
1353     }
1354 
1355     return E_OK;
1356 }
1357 
GetXAttr(const std::string & cloudId,const std::string & key,std::string & value,const CacheNode & node,const std::string & extAttrKey)1358 int32_t CloudDiskRdbStore::GetXAttr(const std::string &cloudId, const std::string &key, std::string &value,
1359     const CacheNode &node, const std::string &extAttrKey)
1360 {
1361     int32_t num = CheckXattr(key);
1362     int32_t ret;
1363     switch (num) {
1364         case CLOUD_LOCATION:
1365             ret = LocationGetXattr(node.fileName, key, value, node.parentCloudId);
1366             break;
1367         case IS_FAVORITE:
1368             ret = FavoriteGetXattr(cloudId, key, value);
1369             break;
1370         case FILE_SYNC_STATUS:
1371             ret = FileStatusGetXattr(cloudId, key, value);
1372             break;
1373         case IS_EXT_ATTR:
1374             ret = GetExtAttrValue(cloudId, extAttrKey, value);
1375             break;
1376         case TIME_RECYCLED:
1377             ret = TimeRecycledGetXattr(cloudId, key, value);
1378             break;
1379         default:
1380             ret = ENOSYS;
1381             break;
1382     }
1383     return ret;
1384 }
1385 
ExtAttrJsonValue(std::string & jsonValue,ValuesBucket & setXAttr,int32_t pos,int32_t dirtyType)1386 static int32_t ExtAttrJsonValue(std::string &jsonValue, ValuesBucket &setXAttr, int32_t pos, int32_t dirtyType)
1387 {
1388     setXAttr.PutString(FileColumn::ATTRIBUTE, jsonValue);
1389     if (pos != LOCAL) {
1390         if (dirtyType != static_cast<int32_t>(DirtyType::TYPE_FDIRTY)) {
1391             setXAttr.PutInt(FileColumn::DIRTY_TYPE, static_cast<int32_t>(DirtyType::TYPE_MDIRTY));
1392         }
1393         setXAttr.PutLong(FileColumn::OPERATE_TYPE, static_cast<int32_t>(OperationType::UNKNOWN_TYPE));
1394     }
1395     setXAttr.PutLong(FileColumn::META_TIME_EDITED, UTCTimeMilliSeconds());
1396     return E_OK;
1397 }
1398 
ExtAttributeSetValue(std::string & jsonValue,const std::string & key,const std::string & value,std::string & xattrList)1399 static int32_t ExtAttributeSetValue(std::string &jsonValue, const std::string &key,
1400     const std::string &value, std::string &xattrList)
1401 {
1402     auto jsonObj = nlohmann::json::parse(xattrList, nullptr, false);
1403     if (jsonObj.is_discarded() || (!jsonObj.is_object())) {
1404         LOGD("jsonObj is discarded");
1405         jsonObj = nlohmann::json::object();
1406     }
1407 
1408     auto it = jsonObj.find(key);
1409     if (it == jsonObj.end()) {
1410         jsonObj.emplace(key, value);
1411     } else {
1412         jsonObj[key] = value;
1413     }
1414 
1415     try {
1416         jsonValue = jsonObj.dump();
1417     } catch (nlohmann::json::type_error& err) {
1418         LOGE("failed to dump json object, reason: %{public}s", err.what());
1419         return E_INVAL_ARG;
1420     }
1421     return E_OK;
1422 }
1423 
ExtAttributeSetXattr(const std::string & cloudId,const std::string & value,const std::string & key)1424 int32_t CloudDiskRdbStore::ExtAttributeSetXattr(const std::string &cloudId, const std::string &value,
1425     const std::string &key)
1426 {
1427     RDBPTR_IS_NULLPTR(rdbStore_);
1428     ValuesBucket setAttr;
1429     int32_t changedRows = -1;
1430     TransactionOperations rdbTransaction(rdbStore_);
1431     auto [ret, transaction] = rdbTransaction.Start();
1432     if (ret != E_OK) {
1433         LOGE("Ext rdbstore begin transaction failed, ret = %{public}d", ret);
1434         return ret;
1435     }
1436     std::string xattrList;
1437     int32_t pos = 0;
1438     int32_t dirtyType = static_cast<int32_t>(DirtyType::TYPE_SYNCED);
1439     RETURN_ON_ERR(GetExtAttr(cloudId, xattrList, pos, dirtyType));
1440     std::string jsonValue = "";
1441     RETURN_ON_ERR(ExtAttributeSetValue(jsonValue, key, value, xattrList));
1442     RETURN_ON_ERR(ExtAttrJsonValue(jsonValue, setAttr, pos, dirtyType));
1443     NativeRdb::AbsRdbPredicates predicates = NativeRdb::AbsRdbPredicates(FileColumn::FILES_TABLE);
1444     predicates.EqualTo(FileColumn::CLOUD_ID, cloudId);
1445     std::tie(ret, changedRows) = transaction->Update(setAttr, predicates);
1446     if (ret != E_OK) {
1447         LOGE("ext attr location fail, ret %{public}d", ret);
1448         return E_RDB;
1449     }
1450     rdbTransaction.Finish();
1451     CloudDiskSyncHelper::GetInstance().RegisterTriggerSync(bundleName_, userId_);
1452     return E_OK;
1453 }
1454 
SetXAttr(const std::string & cloudId,const std::string & key,const std::string & value,const std::string & name,const std::string & parentCloudId)1455 int32_t CloudDiskRdbStore::SetXAttr(const std::string &cloudId, const std::string &key, const std::string &value,
1456     const std::string &name, const std::string &parentCloudId)
1457 {
1458     int32_t num = CheckXattr(key);
1459     int32_t ret;
1460     switch (num) {
1461         case CLOUD_LOCATION:
1462             ret = LocationSetXattr(name, parentCloudId, cloudId, value);
1463             break;
1464         case CLOUD_RECYCLE:
1465             ret = RecycleSetXattr(name, parentCloudId, cloudId, value);
1466             break;
1467         case IS_FAVORITE:
1468             ret = FavoriteSetXattr(cloudId, value);
1469             break;
1470         case IS_EXT_ATTR:
1471             ret = ExtAttributeSetXattr(cloudId, value, name);
1472             break;
1473         case HAS_THM:
1474             ret = HasTHMSetXattr(name, key, cloudId, value);
1475             break;
1476         default:
1477             ret = ENOSYS;
1478             break;
1479     }
1480     return ret;
1481 }
1482 
FileRename(ValuesBucket & values,const int32_t & position,const std::string & newFileName,const int32_t dirtyType)1483 static void FileRename(ValuesBucket &values, const int32_t &position, const std::string &newFileName,
1484     const int32_t dirtyType)
1485 {
1486     values.PutString(FileColumn::FILE_NAME, newFileName);
1487     values.PutInt(FileColumn::FILE_STATUS, FileStatus::TO_BE_UPLOADED);
1488     FillFileType(newFileName, values);
1489     if (position != LOCAL) {
1490         if (dirtyType != static_cast<int32_t>(DirtyType::TYPE_FDIRTY)) {
1491             values.PutInt(FileColumn::DIRTY_TYPE, static_cast<int32_t>(DirtyType::TYPE_MDIRTY));
1492         }
1493         values.PutLong(FileColumn::OPERATE_TYPE, static_cast<int64_t>(OperationType::RENAME));
1494     }
1495 }
1496 
FileMove(ValuesBucket & values,const int32_t & position,const std::string & newParentCloudId,const int32_t dirtyType)1497 static void FileMove(ValuesBucket &values, const int32_t &position, const std::string &newParentCloudId,
1498     const int32_t dirtyType)
1499 {
1500     values.PutString(FileColumn::PARENT_CLOUD_ID, newParentCloudId);
1501     values.PutInt(FileColumn::FILE_STATUS, FileStatus::TO_BE_UPLOADED);
1502     if (position != LOCAL) {
1503         if (dirtyType != static_cast<int32_t>(DirtyType::TYPE_FDIRTY)) {
1504             values.PutInt(FileColumn::DIRTY_TYPE, static_cast<int32_t>(DirtyType::TYPE_MDIRTY));
1505         }
1506         values.PutLong(FileColumn::OPERATE_TYPE, static_cast<int64_t>(OperationType::MOVE));
1507     }
1508 }
1509 
FileMoveAndRename(ValuesBucket & values,const int32_t & position,const std::string & newParentCloudId,const std::string & newFileName,const int32_t dirtyType)1510 static void FileMoveAndRename(ValuesBucket &values, const int32_t &position, const std::string &newParentCloudId,
1511     const std::string &newFileName, const int32_t dirtyType)
1512 {
1513     values.PutString(FileColumn::PARENT_CLOUD_ID, newParentCloudId);
1514     values.PutString(FileColumn::FILE_NAME, newFileName);
1515     values.PutInt(FileColumn::FILE_STATUS, FileStatus::TO_BE_UPLOADED);
1516     FillFileType(newFileName, values);
1517     if (position != LOCAL) {
1518         if (dirtyType != static_cast<int32_t>(DirtyType::TYPE_FDIRTY)) {
1519             values.PutInt(FileColumn::DIRTY_TYPE, static_cast<int32_t>(DirtyType::TYPE_MDIRTY));
1520         }
1521         values.PutLong(FileColumn::OPERATE_TYPE, static_cast<int64_t>(OperationType::MOVE));
1522     }
1523 }
1524 
HandleRenameValue(ValuesBucket & rename,int32_t position,uint8_t noNeedUpload,const CacheNode & oldNode,const CacheNode & newNode)1525 int32_t CloudDiskRdbStore::HandleRenameValue(ValuesBucket &rename, int32_t position, uint8_t noNeedUpload,
1526     const CacheNode &oldNode, const CacheNode &newNode)
1527 {
1528     string oldParentCloudId = oldNode.parentCloudId;
1529     string oldFileName = oldNode.fileName;
1530     string newParentCloudId = newNode.parentCloudId;
1531     string newFileName = newNode.fileName;
1532     rename.PutLong(FileColumn::META_TIME_EDITED, UTCTimeMilliSeconds());
1533     rename.PutInt(FileColumn::NO_NEED_UPLOAD, noNeedUpload);
1534     int32_t dirtyType = static_cast<int32_t>(DirtyType::TYPE_SYNCED);
1535     RETURN_ON_ERR(GetDirtyType(oldNode.cloudId, dirtyType));
1536     if (oldFileName != newFileName && oldParentCloudId == newParentCloudId) {
1537         FileRename(rename, position, newFileName, dirtyType);
1538     }
1539     if (oldFileName == newFileName && oldParentCloudId != newParentCloudId) {
1540         FileMove(rename, position, newParentCloudId, dirtyType);
1541     }
1542     if (oldFileName != newFileName && oldParentCloudId != newParentCloudId) {
1543         FileMoveAndRename(rename, position, newParentCloudId, newFileName, dirtyType);
1544     }
1545     return E_OK;
1546 }
1547 
Rename(const std::string & oldParentCloudId,const std::string & oldFileName,const std::string & newParentCloudId,const std::string & newFileName,bool newFileNoNeedUpload)1548 int32_t CloudDiskRdbStore::Rename(const std::string &oldParentCloudId, const std::string &oldFileName,
1549     const std::string &newParentCloudId, const std::string &newFileName, bool newFileNoNeedUpload)
1550 {
1551     int32_t ret = CheckName(newFileName);
1552     if (ret != E_OK) {
1553         return ret;
1554     }
1555     RDBPTR_IS_NULLPTR(rdbStore_);
1556     if (oldParentCloudId.empty() || oldFileName.empty() || newParentCloudId.empty() || newFileName.empty()) {
1557         LOGE("rename parameters is invalid");
1558         return E_INVAL_ARG;
1559     }
1560     MetaBase metaBase(oldFileName);
1561     auto oldMetaFile = MetaFileMgr::GetInstance().GetCloudDiskMetaFile(userId_, bundleName_, oldParentCloudId);
1562     ret = oldMetaFile->DoLookup(metaBase);
1563     if (ret != E_OK) {
1564         LOGE("lookup dentry failed, ret = %{public}d", ret);
1565         return EINVAL;
1566     }
1567     uint8_t oldFileNoNeedUpload = metaBase.noUpload;
1568     metaBase.noUpload = (newFileNoNeedUpload == NEED_UPLOAD)? NEED_UPLOAD : NO_UPLOAD;
1569     ret = CheckNameForSpace(newFileName, S_ISDIR(metaBase.mode));
1570     if (ret != E_OK) {
1571         return ret;
1572     }
1573     ValuesBucket rename;
1574     CacheNode newNode = {.cloudId = metaBase.cloudId, .parentCloudId = newParentCloudId, .fileName = newFileName};
1575     CacheNode oldNode = {.cloudId = metaBase.cloudId, .parentCloudId = oldParentCloudId, .fileName = oldFileName};
1576     RETURN_ON_ERR(HandleRenameValue(rename, metaBase.position, metaBase.noUpload, oldNode, newNode));
1577     vector<ValueObject> bindArgs;
1578     bindArgs.emplace_back(metaBase.cloudId);
1579     auto newMetaFile = MetaFileMgr::GetInstance().GetCloudDiskMetaFile(userId_, bundleName_, newParentCloudId);
1580     ret = oldMetaFile->DoRename(metaBase, newFileName, newMetaFile);
1581     if (ret != E_OK) {
1582         LOGE("rename dentry failed, ret = %{public}d", ret);
1583         return EINVAL;
1584     }
1585     function<void()> rdbUpdate = [this, rename, bindArgs,
1586         oldFileNoNeedUpload, newFileNoNeedUpload, oldFileName, newFileName] {
1587         int32_t changedRows = -1;
1588         int32_t ret = rdbStore_ ->Update(changedRows, FileColumn::FILES_TABLE, rename,
1589                                          FileColumn::CLOUD_ID + " = ?", bindArgs);
1590         if (ret != E_OK) {
1591             LOGE("rename file fail, ret %{public}d", ret);
1592         }
1593         if ((oldFileNoNeedUpload == NEED_UPLOAD) || (newFileNoNeedUpload == NEED_UPLOAD)) {
1594             CloudDiskSyncHelper::GetInstance().RegisterTriggerSync(bundleName_, userId_);
1595         }
1596     };
1597     ffrt::thread(rdbUpdate).detach();
1598     return E_OK;
1599 }
1600 
GetHasChild(const std::string & cloudId,bool & hasChild)1601 int32_t CloudDiskRdbStore::GetHasChild(const std::string &cloudId, bool &hasChild)
1602 {
1603     RDBPTR_IS_NULLPTR(rdbStore_);
1604     CLOUDID_IS_NULL(cloudId);
1605     AbsRdbPredicates readDirPredicates = AbsRdbPredicates(FileColumn::FILES_TABLE);
1606     readDirPredicates.EqualTo(FileColumn::PARENT_CLOUD_ID, cloudId)
1607         ->And()->EqualTo(FileColumn::FILE_TIME_RECYCLED, "0")->And()
1608         ->NotEqualTo(FileColumn::DIRTY_TYPE, to_string(static_cast<int32_t>(DirtyType::TYPE_DELETED)));
1609     auto resultSet = rdbStore_->QueryByStep(readDirPredicates, {FileColumn::FILE_NAME});
1610     if (resultSet == nullptr) {
1611         LOGE("get nullptr result set");
1612         return E_RDB;
1613     }
1614     if (resultSet->GoToNextRow() == E_OK) {
1615         hasChild = true;
1616     } else {
1617         hasChild = false;
1618     }
1619     return E_OK;
1620 }
1621 
UnlinkSynced(const std::string & cloudId)1622 int32_t CloudDiskRdbStore::UnlinkSynced(const std::string &cloudId)
1623 {
1624     RDBPTR_IS_NULLPTR(rdbStore_);
1625     CLOUDID_IS_NULL(cloudId);
1626     int32_t changedRows = -1;
1627     ValuesBucket updateValue;
1628     vector<string> whereArgs = {cloudId};
1629     updateValue.PutInt(FileColumn::DIRTY_TYPE, static_cast<int32_t>(DirtyType::TYPE_DELETED));
1630     int32_t ret = rdbStore_->Update(changedRows, FileColumn::FILES_TABLE, updateValue, FileColumn::CLOUD_ID + " = ?",
1631         whereArgs);
1632     if (ret != E_OK) {
1633         LOGE("unlink synced directory fail, ret %{public}d", ret);
1634         return E_RDB;
1635     }
1636     return E_OK;
1637 }
1638 
UnlinkLocal(const std::string & cloudId)1639 int32_t CloudDiskRdbStore::UnlinkLocal(const std::string &cloudId)
1640 {
1641     RDBPTR_IS_NULLPTR(rdbStore_);
1642     CLOUDID_IS_NULL(cloudId);
1643     int32_t changedRows = -1;
1644     vector<string> whereArgs = {cloudId};
1645     int32_t ret = rdbStore_->Delete(changedRows, FileColumn::FILES_TABLE, FileColumn::CLOUD_ID + " = ?", whereArgs);
1646     if (ret != E_OK) {
1647         LOGE("unlink local directory fail, ret %{public}d", ret);
1648         return E_RDB;
1649     }
1650     return E_OK;
1651 }
1652 
Unlink(const std::string & cloudId,const int32_t & noUpload)1653 int32_t CloudDiskRdbStore::Unlink(const std::string &cloudId, const int32_t &noUpload)
1654 {
1655     RDBPTR_IS_NULLPTR(rdbStore_);
1656     if (cloudId.empty() || cloudId == ROOT_CLOUD_ID) {
1657         LOGE("Unlink parameters is invalid");
1658         return E_INVAL_ARG;
1659     }
1660     if (noUpload == NO_UPLOAD) {
1661         RETURN_ON_ERR(UnlinkLocal(cloudId));
1662     } else {
1663         RETURN_ON_ERR(UnlinkSynced(cloudId));
1664         CloudDiskSyncHelper::GetInstance().RegisterTriggerSync(bundleName_, userId_);
1665     }
1666     return E_OK;
1667 }
1668 
GetDirtyType(const std::string & cloudId,int32_t & dirtyType)1669 int32_t CloudDiskRdbStore::GetDirtyType(const std::string &cloudId, int32_t &dirtyType)
1670 {
1671     RDBPTR_IS_NULLPTR(rdbStore_);
1672     AbsRdbPredicates predicates = AbsRdbPredicates(FileColumn::FILES_TABLE);
1673     predicates.EqualTo(FileColumn::CLOUD_ID, cloudId);
1674     auto resultSet = rdbStore_->QueryByStep(predicates, {FileColumn::DIRTY_TYPE});
1675     if (resultSet == nullptr) {
1676         LOGE("get null result");
1677         return E_RDB;
1678     }
1679     if (resultSet->GoToNextRow() != E_OK) {
1680         LOGE("get current node resultSet fail");
1681         return E_RDB;
1682     }
1683 
1684     int32_t ret = CloudDiskRdbUtils::GetInt(FileColumn::DIRTY_TYPE, dirtyType, resultSet);
1685     if (ret != E_OK) {
1686         LOGE("get file status fail");
1687         return ret;
1688     }
1689     return E_OK;
1690 }
1691 
GetSrcCloudId(const std::string & cloudId,std::string & srcCloudId)1692 int32_t CloudDiskRdbStore::GetSrcCloudId(const std::string &cloudId, std::string &srcCloudId)
1693 {
1694     RDBPTR_IS_NULLPTR(rdbStore_);
1695     AbsRdbPredicates predicates = AbsRdbPredicates(FileColumn::FILES_TABLE);
1696     predicates.EqualTo(FileColumn::CLOUD_ID, cloudId);
1697     auto resultSet = rdbStore_->QueryByStep(predicates, {FileColumn::SOURCE_CLOUD_ID});
1698     if (resultSet == nullptr) {
1699         LOGE("get null result");
1700         return E_RDB;
1701     }
1702     if (resultSet->GoToNextRow() != E_OK) {
1703         LOGE("get current node resultSet fail");
1704         return E_RDB;
1705     }
1706 
1707     int32_t ret = CloudDiskRdbUtils::GetString(FileColumn::SOURCE_CLOUD_ID, srcCloudId, resultSet);
1708     if (ret != E_OK) {
1709         LOGE("get file src_cloudid failed, ret = %{public}d", ret);
1710         return ret;
1711     }
1712     return E_OK;
1713 }
1714 
GetCurNode(const std::string & cloudId,CacheNode & curNode)1715 int32_t CloudDiskRdbStore::GetCurNode(const std::string &cloudId, CacheNode &curNode)
1716 {
1717     RDBPTR_IS_NULLPTR(rdbStore_);
1718     if (cloudId.empty() || cloudId == ROOT_CLOUD_ID) {
1719         LOGE("parameter invalid");
1720         return E_INVAL_ARG;
1721     }
1722     AbsRdbPredicates predicates = AbsRdbPredicates(FileColumn::FILES_TABLE);
1723     predicates.EqualTo(FileColumn::CLOUD_ID, cloudId);
1724     auto resultSet = rdbStore_->QueryByStep(
1725         predicates, {FileColumn::PARENT_CLOUD_ID, FileColumn::IS_DIRECTORY, FileColumn::FILE_NAME});
1726     if (resultSet == nullptr) {
1727         LOGE("get null result");
1728         return E_RDB;
1729     }
1730     if (resultSet->GoToNextRow() != E_OK) {
1731         LOGE("get current node resultSet fail");
1732         return E_RDB;
1733     }
1734     RowEntity rowEntity;
1735     if (resultSet->GetRow(rowEntity) != E_OK) {
1736         LOGE("result set to file info get row failed");
1737         return E_RDB;
1738     }
1739 
1740     int32_t isDirectory;
1741     rowEntity.Get(FileColumn::PARENT_CLOUD_ID).GetString(curNode.parentCloudId);
1742     rowEntity.Get(FileColumn::FILE_NAME).GetString(curNode.fileName);
1743     rowEntity.Get(FileColumn::IS_DIRECTORY).GetInt(isDirectory);
1744     curNode.isDir = isDirectory ? "directory" : "file";
1745 
1746     return E_OK;
1747 }
1748 
GetParentNode(const std::string & parentCloudId,std::string & nextCloudId,std::string & fileName)1749 int32_t CloudDiskRdbStore::GetParentNode(const std::string &parentCloudId, std::string &nextCloudId,
1750     std::string &fileName)
1751 {
1752     RDBPTR_IS_NULLPTR(rdbStore_);
1753     if (parentCloudId.empty()) {
1754         LOGE("parameter invalid");
1755         return E_INVAL_ARG;
1756     }
1757     AbsRdbPredicates predicates = AbsRdbPredicates(FileColumn::FILES_TABLE);
1758     predicates.EqualTo(FileColumn::CLOUD_ID, parentCloudId);
1759     auto resultSet = rdbStore_->QueryByStep(predicates, {FileColumn::PARENT_CLOUD_ID, FileColumn::FILE_NAME});
1760     if (resultSet == nullptr) {
1761         LOGE("get null result");
1762         return E_RDB;
1763     }
1764     if (resultSet->GoToNextRow() != E_OK) {
1765         LOGE("get current node resultSet fail");
1766         return E_RDB;
1767     }
1768     RowEntity rowEntity;
1769     if (resultSet->GetRow(rowEntity) != E_OK) {
1770         LOGE("result set to file info get row failed");
1771         return E_RDB;
1772     }
1773     rowEntity.Get(FileColumn::PARENT_CLOUD_ID).GetString(nextCloudId);
1774     rowEntity.Get(FileColumn::FILE_NAME).GetString(fileName);
1775     return E_OK;
1776 }
1777 
GetUriFromDB(const std::string & parentCloudId,std::string & uri)1778 int32_t CloudDiskRdbStore::GetUriFromDB(const std::string &parentCloudId, std::string &uri)
1779 {
1780     string realPrefix = CLOUDDISK_URI_PREFIX;
1781     realPrefix.replace(realPrefix.find(BUNDLENAME_FLAG), BUNDLENAME_FLAG.length(), bundleName_);
1782     if (parentCloudId.empty() || parentCloudId == rootId_ || parentCloudId == ROOT_CLOUD_ID) {
1783         uri = realPrefix + BACKFLASH + uri;
1784         return E_OK;
1785     }
1786 
1787     string nextCloudId;
1788     string fileName;
1789     int32_t ret = GetParentNode(parentCloudId, nextCloudId, fileName);
1790     if (ret != E_OK) {
1791         LOGI("get parentnode fail, parentCloudId: %{public}s", parentCloudId.c_str());
1792         return ret;
1793     }
1794     uri = fileName + BACKFLASH + uri;
1795     uint32_t queryTimes = 0;
1796     while (nextCloudId != ROOT_CLOUD_ID) {
1797         ret = GetParentNode(nextCloudId, nextCloudId, fileName);
1798         if (ret != E_OK) {
1799             return E_OK;
1800         }
1801         uri = fileName + BACKFLASH + uri;
1802         queryTimes++;
1803         if (uri.length() > PATH_MAX || queryTimes > MAX_QUERY_TIMES) {
1804             return E_INVAL_ARG;
1805         }
1806     }
1807     uri = realPrefix + BACKFLASH + uri;
1808     return E_OK;
1809 }
1810 
GetNotifyUri(const CacheNode & cacheNode,std::string & uri)1811 int32_t CloudDiskRdbStore::GetNotifyUri(const CacheNode &cacheNode, std::string &uri)
1812 {
1813     int32_t ret = CheckRootIdValid();
1814     if (ret != E_OK) {
1815         LOGE("rootId is invalid");
1816         return ret;
1817     }
1818     ret = CloudDiskNotifyUtils::GetUriFromCache(bundleName_, rootId_, cacheNode, uri);
1819     if (ret == E_OK) {
1820         return ret;
1821     }
1822     LOGD("get uri from cache fail, name: %{public}s", GetAnonyString(cacheNode.fileName).c_str());
1823     uri = cacheNode.fileName;
1824     ret = GetUriFromDB(cacheNode.parentCloudId, uri);
1825     if (ret == E_OK) {
1826         return ret;
1827     }
1828     LOGI("get uri from db fail, name: %{public}s", GetAnonyString(cacheNode.fileName).c_str());
1829     return ret;
1830 }
1831 
GetNotifyData(const CacheNode & cacheNode,NotifyData & notifyData)1832 int32_t CloudDiskRdbStore::GetNotifyData(const CacheNode &cacheNode, NotifyData &notifyData)
1833 {
1834     int32_t ret = GetNotifyUri(cacheNode, notifyData.uri);
1835     if (ret == E_OK) {
1836         notifyData.isDir = cacheNode.isDir == "directory";
1837     }
1838     return ret;
1839 }
1840 
CheckRootIdValid()1841 int32_t CloudDiskRdbStore::CheckRootIdValid()
1842 {
1843     if (!rootId_.empty()) {
1844         return E_OK;
1845     }
1846     CloudPrefImpl cloudPrefImpl(userId_, bundleName_, FileColumn::FILES_TABLE);
1847     cloudPrefImpl.GetString(ROOT_CLOUD_ID, rootId_);
1848     if (rootId_.empty()) {
1849         LOGE("get rootId fail");
1850         return E_INVAL_ARG;
1851     }
1852     LOGI("load rootis succ, rootId: %{public}s", rootId_.c_str());
1853     return E_OK;
1854 }
1855 
GenCloudSyncTriggerFuncParams(RdbStore & store,std::string & userId,std::string & bundleName)1856 static void GenCloudSyncTriggerFuncParams(RdbStore &store, std::string &userId, std::string &bundleName)
1857 {
1858     string databasePath = store.GetPath();
1859     string str = "cloudfile/";
1860     size_t startPos = databasePath.find(str);
1861     size_t endPos = databasePath.find("/rdb");
1862     if (startPos != std::string::npos && endPos != std::string::npos) {
1863         startPos += str.size();
1864         string tempStr = databasePath.substr(startPos, endPos - startPos);
1865         size_t pos = tempStr.find('/');
1866         if (pos != std::string::npos) {
1867             userId = tempStr.substr(0, pos);
1868             bundleName = tempStr.substr(pos + 1);
1869             LOGI("generate CloudSyncTriggerFunc parameters success, userId: %{public}s, bundleName: %{public}s",
1870                 userId.c_str(), bundleName.c_str());
1871             return;
1872         }
1873     }
1874     LOGE("generate CloudSyncTriggerFunc parameters fail");
1875     return;
1876 }
1877 
CreateFolderTriggerSync(RdbStore & store)1878 static const std::string &CreateFolderTriggerSync(RdbStore &store)
1879 {
1880     string userId;
1881     string bundleName;
1882     GenCloudSyncTriggerFuncParams(store, userId, bundleName);
1883     static const string CREATE_FOLDERS_NEW_CLOUD_SYNC =
1884         "CREATE TRIGGER folders_new_cloud_sync_trigger AFTER INSERT ON " + FileColumn::FILES_TABLE +
1885         " FOR EACH ROW WHEN new.isDirectory == 1 AND new.dirty_type == " +
1886         std::to_string(static_cast<int32_t>(DirtyType::TYPE_NEW)) +
1887         " BEGIN SELECT cloud_sync_func(" + "'" + userId + "', " + "'" + bundleName + "'); END;";
1888     return CREATE_FOLDERS_NEW_CLOUD_SYNC;
1889 }
1890 
UpdateFileTriggerSync(RdbStore & store)1891 static const std::string &UpdateFileTriggerSync(RdbStore &store)
1892 {
1893     string userId;
1894     string bundleName;
1895     GenCloudSyncTriggerFuncParams(store, userId, bundleName);
1896     static const string CREATE_FILES_UPDATE_CLOUD_SYNC =
1897         "CREATE TRIGGER files_update_cloud_sync_trigger AFTER UPDATE ON " + FileColumn::FILES_TABLE +
1898         " FOR EACH ROW WHEN OLD.dirty_type IN (0,1,2,3) AND new.dirty_type IN (2,3)" +
1899         " AND OLD.meta_time_edited != new.meta_time_edited" +
1900         " BEGIN SELECT cloud_sync_func(" + "'" + userId + "', " + "'" + bundleName + "'); END;";
1901     return CREATE_FILES_UPDATE_CLOUD_SYNC;
1902 }
1903 
DeleteFileTriggerSync(RdbStore & store)1904 static const std::string &DeleteFileTriggerSync(RdbStore &store)
1905 {
1906     string userId;
1907     string bundleName;
1908     GenCloudSyncTriggerFuncParams(store, userId, bundleName);
1909     static const string CREATE_FILES_DELETE_CLOUD_SYNC =
1910         "CREATE TRIGGER files_delete_cloud_sync_trigger AFTER UPDATE ON " + FileColumn::FILES_TABLE +
1911         " FOR EACH ROW WHEN OLD.dirty_type IN (0,2,3) AND new.dirty_type == " +
1912         std::to_string(static_cast<int32_t>(DirtyType::TYPE_DELETED)) +
1913         " BEGIN SELECT cloud_sync_func(" + "'" + userId + "', " + "'" + bundleName + "'); END;";
1914     return CREATE_FILES_DELETE_CLOUD_SYNC;
1915 }
1916 
LocalFileTriggerSync(RdbStore & store)1917 static const std::string &LocalFileTriggerSync(RdbStore &store)
1918 {
1919     string userId;
1920     string bundleName;
1921     GenCloudSyncTriggerFuncParams(store, userId, bundleName);
1922     static const string CREATE_FILES_LOCAL_CLOUD_SYNC =
1923         "CREATE TRIGGER files_local_cloud_sync_trigger AFTER UPDATE ON " + FileColumn::FILES_TABLE +
1924         " FOR EACH ROW WHEN OLD.dirty_type IN (1,6) AND new.dirty_type == " +
1925         std::to_string(static_cast<int32_t>(DirtyType::TYPE_NEW)) +
1926         " AND OLD.file_status NOT IN (0,1) AND new.file_status NOT IN (1,2)" +
1927         " BEGIN SELECT cloud_sync_func(" + "'" + userId + "', " + "'" + bundleName + "'); END;";
1928     return CREATE_FILES_LOCAL_CLOUD_SYNC;
1929 }
1930 
ExecuteSql(RdbStore & store)1931 static int32_t ExecuteSql(RdbStore &store)
1932 {
1933     static const vector<string> onCreateSqlStrs = {
1934         FileColumn::CREATE_FILE_TABLE,
1935         FileColumn::CREATE_PARENT_CLOUD_ID_INDEX,
1936     };
1937     for (const string& sqlStr : onCreateSqlStrs) {
1938         if (store.ExecuteSql(sqlStr) != NativeRdb::E_OK) {
1939             return NativeRdb::E_ERROR;
1940         }
1941     }
1942     return NativeRdb::E_OK;
1943 }
1944 
OnCreate(RdbStore & store)1945 int32_t CloudDiskDataCallBack::OnCreate(RdbStore &store)
1946 {
1947     if (ExecuteSql(store) != NativeRdb::E_OK) {
1948         return NativeRdb::E_ERROR;
1949     }
1950     return NativeRdb::E_OK;
1951 }
1952 
VersionAddParentCloudIdIndex(RdbStore & store)1953 static void VersionAddParentCloudIdIndex(RdbStore &store)
1954 {
1955     const string executeSqlStr = FileColumn::CREATE_PARENT_CLOUD_ID_INDEX;
1956     int32_t ret = store.ExecuteSql(executeSqlStr);
1957     if (ret != NativeRdb::E_OK) {
1958         LOGE("add parent cloud id index fail, err %{public}d", ret);
1959     }
1960 }
1961 
VersionFixFileTrigger(RdbStore & store)1962 static void VersionFixFileTrigger(RdbStore &store)
1963 {
1964     const string dropFilesUpdateTrigger = "DROP TRIGGER IF EXISTS files_update_cloud_sync_trigger";
1965     if (store.ExecuteSql(dropFilesUpdateTrigger) != NativeRdb::E_OK) {
1966         LOGE("drop files_update_cloud_sync_trigger fail");
1967     }
1968     const string addUpdateFileTrigger = UpdateFileTriggerSync(store);
1969     int32_t ret = store.ExecuteSql(addUpdateFileTrigger);
1970     if (ret != NativeRdb::E_OK) {
1971         LOGE("add update file trigger fail, err %{public}d", ret);
1972     }
1973     const string addDeleteFileTrigger = DeleteFileTriggerSync(store);
1974     ret = store.ExecuteSql(addDeleteFileTrigger);
1975     if (ret != NativeRdb::E_OK) {
1976         LOGE("add delete file trigger fail, err %{public}d", ret);
1977     }
1978     const string addLocalFileTrigger = LocalFileTriggerSync(store);
1979     ret = store.ExecuteSql(addLocalFileTrigger);
1980     if (ret != NativeRdb::E_OK) {
1981         LOGE("add local file trigger fail, err %{public}d", ret);
1982     }
1983 }
1984 
VersionFixCreateAndLocalTrigger(RdbStore & store)1985 static void VersionFixCreateAndLocalTrigger(RdbStore &store)
1986 {
1987     const string dropFilesCreateTrigger = "DROP TRIGGER IF EXISTS files_new_cloud_sync_trigger";
1988     if (store.ExecuteSql(dropFilesCreateTrigger) != NativeRdb::E_OK) {
1989         LOGE("drop files_new_cloud_sync_trigger fail");
1990     }
1991     const string dropFilesLocalTrigger = "DROP TRIGGER IF EXISTS files_local_cloud_sync_trigger";
1992     if (store.ExecuteSql(dropFilesLocalTrigger) != NativeRdb::E_OK) {
1993         LOGE("drop files_local_cloud_sync_trigger fail");
1994     }
1995     const string addLocalFileTrigger = LocalFileTriggerSync(store);
1996     int32_t ret = store.ExecuteSql(addLocalFileTrigger);
1997     if (ret != NativeRdb::E_OK) {
1998         LOGE("add local file trigger fail, err %{public}d", ret);
1999     }
2000     const string addCreateFolderTrigger = CreateFolderTriggerSync(store);
2001     ret = store.ExecuteSql(addCreateFolderTrigger);
2002     if (ret != NativeRdb::E_OK) {
2003         LOGE("add create folder trigger fail, err %{public}d", ret);
2004     }
2005 }
2006 
VersionAddFileStatusAndErrorCode(RdbStore & store)2007 static void VersionAddFileStatusAndErrorCode(RdbStore &store)
2008 {
2009     const string addIsFavorite = FileColumn::ADD_IS_FAVORITE;
2010     int32_t ret = store.ExecuteSql(addIsFavorite);
2011     if (ret != NativeRdb::E_OK) {
2012         LOGE("add is_favorite fail, err %{public}d", ret);
2013     }
2014 }
2015 
VersionAddFileStatus(RdbStore & store)2016 static void VersionAddFileStatus(RdbStore &store)
2017 {
2018     const string addFileStatus = FileColumn::ADD_FILE_STATUS;
2019     int32_t ret = store.ExecuteSql(addFileStatus);
2020     if (ret != NativeRdb::E_OK) {
2021         LOGE("add file_status fail, err %{public}d", ret);
2022     }
2023 }
2024 
VersionSetFileStatusDefault(RdbStore & store)2025 static void VersionSetFileStatusDefault(RdbStore &store)
2026 {
2027     const string setFileStatus = FileColumn::SET_FILE_STATUS_DEFAULT;
2028     int32_t ret = store.ExecuteSql(setFileStatus);
2029     if (ret != NativeRdb::E_OK) {
2030         LOGE("set file_status fail, err %{public}d", ret);
2031     }
2032 }
2033 
VersionFixSyncMetatimeTrigger(RdbStore & store)2034 static void VersionFixSyncMetatimeTrigger(RdbStore &store)
2035 {
2036     const string dropFilesUpdateTrigger = "DROP TRIGGER IF EXISTS files_update_cloud_sync_trigger";
2037     if (store.ExecuteSql(dropFilesUpdateTrigger) != NativeRdb::E_OK) {
2038         LOGE("drop files_update_cloud_sync_trigger fail");
2039     }
2040     const string addUpdateFileTrigger = UpdateFileTriggerSync(store);
2041     int32_t ret = store.ExecuteSql(addUpdateFileTrigger);
2042     if (ret != NativeRdb::E_OK) {
2043         LOGE("add update file trigger fail, err %{public}d", ret);
2044     }
2045 }
2046 
VersionFixRetryTrigger(RdbStore & store)2047 static void VersionFixRetryTrigger(RdbStore &store)
2048 {
2049     const string dropFilesLocalTrigger = "DROP TRIGGER IF EXISTS files_local_cloud_sync_trigger";
2050     if (store.ExecuteSql(dropFilesLocalTrigger) != NativeRdb::E_OK) {
2051         LOGE("drop local file trigger fail");
2052     }
2053     const string addFilesLocalTrigger = LocalFileTriggerSync(store);
2054     int32_t ret = store.ExecuteSql(addFilesLocalTrigger);
2055     if (ret != NativeRdb::E_OK) {
2056         LOGE("add local file trigger fail, err %{public}d", ret);
2057     }
2058 }
2059 
VersionRemoveCloudSyncFuncTrigger(RdbStore & store)2060 static void VersionRemoveCloudSyncFuncTrigger(RdbStore &store)
2061 {
2062     const string dropNewFolderTrigger = "DROP TRIGGER IF EXISTS folders_new_cloud_sync_trigger";
2063     if (store.ExecuteSql(dropNewFolderTrigger) != NativeRdb::E_OK) {
2064         LOGE("drop folders_new_cloud_sync_trigger fail");
2065     }
2066     const string dropUpdateFileTrigger = "DROP TRIGGER IF EXISTS files_update_cloud_sync_trigger";
2067     if (store.ExecuteSql(dropUpdateFileTrigger) != NativeRdb::E_OK) {
2068         LOGE("drop files_update_cloud_sync_trigger fail");
2069     }
2070     const string dropFileDeleteTrigger = "DROP TRIGGER IF EXISTS files_delete_cloud_sync_trigger";
2071     if (store.ExecuteSql(dropFileDeleteTrigger) != NativeRdb::E_OK) {
2072         LOGE("drop files_delete_cloud_sync_trigger fail");
2073     }
2074     const string dropFileLocalTrigger = "DROP TRIGGER IF EXISTS files_local_cloud_sync_trigger";
2075     if (store.ExecuteSql(dropFileLocalTrigger) != NativeRdb::E_OK) {
2076         LOGE("drop files_local_cloud_sync_trigger fail");
2077     }
2078 }
2079 
VersionAddThmFlag(RdbStore & store)2080 static void VersionAddThmFlag(RdbStore &store)
2081 {
2082     const string addThmFlag = FileColumn::ADD_THM_FLAG;
2083     int32_t ret = store.ExecuteSql(addThmFlag);
2084     if (ret != NativeRdb::E_OK) {
2085         LOGE("add thm_flag fail, err %{public}d", ret);
2086     }
2087     const string addLcdFlag = FileColumn::ADD_LCD_FLAG;
2088     ret = store.ExecuteSql(addLcdFlag);
2089     if (ret != NativeRdb::E_OK) {
2090         LOGE("add lcd_flag fail, err %{public}d", ret);
2091     }
2092     const string addUploadFlag = FileColumn::ADD_UPLOAD_FLAG;
2093     ret = store.ExecuteSql(addUploadFlag);
2094     if (ret != NativeRdb::E_OK) {
2095         LOGE("add no_need_upload fail, err %{public}d", ret);
2096     }
2097 }
2098 
VersionAddSrcCloudId(RdbStore & store)2099 static void VersionAddSrcCloudId(RdbStore &store)
2100 {
2101     const string addSrcCloudId = FileColumn::ADD_SRC_CLOUD_ID;
2102     int32_t ret = store.ExecuteSql(addSrcCloudId);
2103     if (ret != NativeRdb::E_OK) {
2104         LOGE("add src_cloud_id fail, err %{public}d", ret);
2105     }
2106 }
2107 
VersionAddThmSize(RdbStore & store)2108 static void VersionAddThmSize(RdbStore &store)
2109 {
2110     const string addThmSize = FileColumn::ADD_THM_SIZE;
2111     int32_t ret = store.ExecuteSql(addThmSize);
2112     if (ret != NativeRdb::E_OK) {
2113         LOGE("add thm_size fail, err %{public}d", ret);
2114     }
2115     const string addLcdSize = FileColumn::ADD_LCD_SIZE;
2116     ret = store.ExecuteSql(addLcdSize);
2117     if (ret != NativeRdb::E_OK) {
2118         LOGE("add lcd_size fail, err %{public}d", ret);
2119     }
2120     const string addSourceCloudId = FileColumn::ADD_SOURCE_CLOUD_ID;
2121     ret = store.ExecuteSql(addSourceCloudId);
2122     if (ret != NativeRdb::E_OK) {
2123         LOGE("add source_cloud_id fail, err %{public}d", ret);
2124     }
2125 }
2126 
VersionAddLocalFlag(RdbStore & store)2127 static void VersionAddLocalFlag(RdbStore &store)
2128 {
2129     const string addLocalFlag = FileColumn::ADD_LOCAL_FLAG;
2130     int32_t ret = store.ExecuteSql(addLocalFlag);
2131     if (ret != NativeRdb::E_OK) {
2132         LOGE("add local_flag fail, err %{public}d", ret);
2133     }
2134 }
2135 
GetMetaBaseData(CloudDiskFileInfo & info,const shared_ptr<ResultSet> resultSet)2136 static int32_t GetMetaBaseData(CloudDiskFileInfo &info, const shared_ptr<ResultSet> resultSet)
2137 {
2138     RETURN_ON_ERR(CloudDiskRdbUtils::GetString(FileColumn::CLOUD_ID, info.cloudId, resultSet));
2139     RETURN_ON_ERR(CloudDiskRdbUtils::GetString(FileColumn::FILE_NAME, info.name, resultSet));
2140     int32_t isDir = 0;
2141     RETURN_ON_ERR(CloudDiskRdbUtils::GetInt(FileColumn::IS_DIRECTORY, isDir, resultSet));
2142     info.IsDirectory = static_cast<bool>(isDir);
2143     int32_t position = 0;
2144     RETURN_ON_ERR(CloudDiskRdbUtils::GetInt(FileColumn::POSITION, position, resultSet));
2145     info.location = static_cast<uint32_t>(position);
2146     int64_t atime = 0;
2147     RETURN_ON_ERR(CloudDiskRdbUtils::GetLong(FileColumn::FILE_TIME_ADDED, atime, resultSet));
2148     info.atime = static_cast<uint64_t>(atime);
2149     int64_t mtime = 0;
2150     RETURN_ON_ERR(CloudDiskRdbUtils::GetLong(FileColumn::FILE_TIME_EDITED, mtime, resultSet));
2151     info.mtime = static_cast<uint64_t>(mtime);
2152     int64_t size = 0;
2153     RETURN_ON_ERR(CloudDiskRdbUtils::GetLong(FileColumn::FILE_SIZE, size, resultSet));
2154     info.size = static_cast<uint64_t>(size);
2155     int64_t rowId = 0;
2156     RETURN_ON_ERR(CloudDiskRdbUtils::GetLong(FileColumn::ROW_ID, rowId, resultSet));
2157     info.rowId = static_cast<uint64_t>(rowId);
2158     return E_OK;
2159 }
2160 
GetUserIdAndBundleName(RdbStore & store,uint32_t & userId,string & bundleName)2161 static int32_t GetUserIdAndBundleName(RdbStore &store, uint32_t &userId, string &bundleName)
2162 {
2163     string userIdStr;
2164     GenCloudSyncTriggerFuncParams(store, userIdStr, bundleName);
2165     bool isValid = std::all_of(userIdStr.begin(), userIdStr.end(), ::isdigit);
2166     if (!isValid) {
2167         LOGE("invalid user Id");
2168         return E_INVAL_ARG;
2169     }
2170     userId = static_cast<uint32_t>(std::stoi(userIdStr));
2171     return E_OK;
2172 }
2173 
GenerateDentryRecursively(RdbStore & store,const string & parentCloudId)2174 static int32_t GenerateDentryRecursively(RdbStore &store, const string &parentCloudId)
2175 {
2176     LOGD("Generate dentry recursively parentCloudId:%{public}s", parentCloudId.c_str());
2177     uint32_t userId;
2178     string bundleName;
2179     RETURN_ON_ERR(GetUserIdAndBundleName(store, userId, bundleName));
2180     AbsRdbPredicates lookUpPredicates = AbsRdbPredicates(FileColumn::FILES_TABLE);
2181     lookUpPredicates.EqualTo(FileColumn::PARENT_CLOUD_ID, parentCloudId)
2182         ->And()->EqualTo(FileColumn::FILE_TIME_RECYCLED, "0");
2183     int32_t rowCount = 0;
2184     uint64_t offset = 0;
2185     do {
2186         lookUpPredicates.Limit(offset, CHECK_QUERY_LIMIT);
2187         auto resultSet = store.Query(lookUpPredicates, FileColumn::FILE_SYSTEM_QUERY_COLUMNS);
2188         if (resultSet == nullptr) {
2189             LOGE("failed to get result set at offset:%{public}" PRIu64 "", offset);
2190             continue;
2191         }
2192         int32_t ret = resultSet->GetRowCount(rowCount);
2193         if (ret != E_OK || rowCount < 0) {
2194             LOGE("failed to get row count at offset:%{public}" PRIu64 ", ret: %{public}d", offset, ret);
2195             continue;
2196         }
2197         if (rowCount == 0) {
2198             return E_OK;
2199         }
2200         CloudDiskFileInfo info;
2201         while (resultSet->GoToNextRow() == 0) {
2202             RETURN_ON_ERR(GetMetaBaseData(info, resultSet));
2203             MetaBase metaBase(info.name);
2204             auto callback = [info] (MetaBase &m) {
2205                 m.cloudId = info.cloudId;
2206                 m.atime = info.atime;
2207                 m.mtime = info.mtime;
2208                 m.size = info.size;
2209                 m.mode = (info.IsDirectory) ? (S_IFDIR | STAT_MODE_DIR) : (S_IFREG | STAT_MODE_REG);
2210                 m.position = info.location;
2211                 m.fileType = FILE_TYPE_CONTENT;
2212             };
2213             auto metaFile = MetaFileMgr::GetInstance().GetCloudDiskMetaFile(userId, bundleName, parentCloudId);
2214             ret = metaFile->DoLookupAndUpdate(info.name, callback);
2215             if (ret != E_OK) {
2216                 LOGE("insert new dentry failed, ret = %{public}d", ret);
2217                 return ret;
2218             }
2219             if (info.IsDirectory) {RETURN_ON_ERR(GenerateDentryRecursively(store, info.cloudId));}
2220         }
2221         offset += CHECK_QUERY_LIMIT;
2222     } while (rowCount != 0);
2223     return E_OK;
2224 }
2225 
GenerateRecycleDentryRecursively(RdbStore & store)2226 static int32_t GenerateRecycleDentryRecursively(RdbStore &store)
2227 {
2228     uint32_t userId;
2229     string bundleName;
2230     RETURN_ON_ERR(GetUserIdAndBundleName(store, userId, bundleName));
2231     AbsRdbPredicates lookUpPredicates = AbsRdbPredicates(FileColumn::FILES_TABLE);
2232     lookUpPredicates.NotEqualTo(FileColumn::FILE_TIME_RECYCLED, "0");
2233     int32_t rowCount = 0;
2234     uint64_t offset = 0;
2235     do {
2236         lookUpPredicates.Limit(offset, CHECK_QUERY_LIMIT);
2237         auto resultSet = store.Query(lookUpPredicates, FileColumn::FILE_SYSTEM_QUERY_COLUMNS);
2238         if (resultSet == nullptr) {
2239             LOGE("failed to get result set at offset:%{public}" PRIu64 "", offset);
2240             continue;
2241         }
2242         int32_t ret = resultSet->GetRowCount(rowCount);
2243         if (ret != E_OK || rowCount < 0) {
2244             LOGE("failed to get row count at offset:%{public}" PRIu64 ", ret: %{public}d", offset, ret);
2245             continue;
2246         }
2247         if (rowCount == 0) {
2248             return E_OK;
2249         }
2250         CloudDiskFileInfo info;
2251         while (resultSet->GoToNextRow() == 0) {
2252             RETURN_ON_ERR(GetMetaBaseData(info, resultSet));
2253             string uniqueName = info.name + "_" + std::to_string(info.rowId);
2254             MetaBase metaBase(uniqueName);
2255             auto callback = [info] (MetaBase &m) {
2256                 m.cloudId = info.cloudId;
2257                 m.atime = info.atime;
2258                 m.mtime = info.mtime;
2259                 m.size = info.size;
2260                 m.mode = (info.IsDirectory) ? (S_IFDIR | STAT_MODE_DIR) : (S_IFREG | STAT_MODE_REG);
2261                 m.position = info.location;
2262                 m.fileType = FILE_TYPE_CONTENT;
2263             };
2264             RETURN_ON_ERR(MetaFileMgr::GetInstance().CreateRecycleDentry(userId, bundleName));
2265             auto metaFile = MetaFileMgr::GetInstance().GetCloudDiskMetaFile(userId, bundleName, RECYCLE_CLOUD_ID);
2266             ret = metaFile->DoLookupAndUpdate(uniqueName, callback);
2267             if (ret != E_OK) {
2268                 LOGE("insert new dentry failed, ret = %{public}d", ret);
2269                 return ret;
2270             }
2271         }
2272         offset += CHECK_QUERY_LIMIT;
2273     } while (rowCount != 0);
2274     return E_OK;
2275 }
2276 
VersionAddCheckFlag(RdbStore & store)2277 static void VersionAddCheckFlag(RdbStore &store)
2278 {
2279     const string addCheckFlag = FileColumn::ADD_CHECK_FLAG;
2280     int32_t ret = store.ExecuteSql(addCheckFlag);
2281     if (ret != NativeRdb::E_OK) {
2282         LOGE("add check_flag fail, ret = %{public}d", ret);
2283     }
2284     ret = GenerateDentryRecursively(store, ROOT_CLOUD_ID);
2285     if (ret != E_OK) {
2286         LOGE("failed to generate dentry recursively, ret = %{public}d", ret);
2287     }
2288     ret = GenerateRecycleDentryRecursively(store);
2289     if (ret != E_OK) {
2290         LOGE("failed to generate recycle ndentry recursively, ret = %{public}d", ret);
2291     }
2292 }
2293 
VersionAddRootDirectory(RdbStore & store)2294 static void VersionAddRootDirectory(RdbStore &store)
2295 {
2296     const string addRootDirectory = "ALTER Table " + FileColumn::FILES_TABLE +
2297         " ADD COLUMN " + FileColumn::ROOT_DIRECTORY + " TEXT";
2298     int32_t ret = store.ExecuteSql(addRootDirectory);
2299     if (ret != NativeRdb::E_OK) {
2300         LOGE("add root_directory fail, ret = %{public}d", ret);
2301     }
2302     ValuesBucket rootDirectory;
2303     rootDirectory.PutString(FileColumn::ROOT_DIRECTORY, system::GetParameter(FILEMANAGER_KEY, ""));
2304     int32_t changedRows = -1;
2305     vector<ValueObject> bindArgs;
2306     ret = store.Update(changedRows, FileColumn::FILES_TABLE, rootDirectory, "", bindArgs);
2307     if (ret != NativeRdb::E_OK) {
2308         LOGE("set root_directory fail, err %{public}d", ret);
2309     }
2310 }
2311 
VersionAddAttribute(RdbStore & store)2312 static void VersionAddAttribute(RdbStore &store)
2313 {
2314     const string attrbute = FileColumn::ADD_ATTRIBUTE;
2315     int32_t ret = store.ExecuteSql(attrbute);
2316     if (ret != NativeRdb::E_OK) {
2317         LOGE("add attrbute fail, ret = %{public}d", ret);
2318     }
2319 }
2320 
OnUpgradeExtend(RdbStore & store,int32_t oldVersion,int32_t newVersion)2321 int32_t CloudDiskDataCallBack::OnUpgradeExtend(RdbStore &store, int32_t oldVersion, int32_t newVersion)
2322 {
2323     if (oldVersion < VERSION_ADD_THM_SIZE) {
2324         VersionAddThmSize(store);
2325     }
2326     if (oldVersion < VERSION_ADD_LOCAL_FLAG) {
2327         VersionAddLocalFlag(store);
2328     }
2329 
2330     return NativeRdb::E_OK;
2331 }
2332 
OnUpgrade(RdbStore & store,int32_t oldVersion,int32_t newVersion)2333 int32_t CloudDiskDataCallBack::OnUpgrade(RdbStore &store, int32_t oldVersion, int32_t newVersion)
2334 {
2335     LOGD("OnUpgrade old:%d, new:%d", oldVersion, newVersion);
2336     if (oldVersion < VERSION_ADD_PARENT_CLOUD_ID_INDEX) {
2337         VersionAddParentCloudIdIndex(store);
2338     }
2339     if (oldVersion < VERSION_FIX_FILE_TRIGGER) {
2340         VersionFixFileTrigger(store);
2341     }
2342     if (oldVersion < VERSION_FIX_CREATE_AND_LOCAL_TRIGGER) {
2343         VersionFixCreateAndLocalTrigger(store);
2344     }
2345     if (oldVersion < VERSION_ADD_STATUS_ERROR_FAVORITE) {
2346         VersionAddFileStatusAndErrorCode(store);
2347     }
2348     if (oldVersion < VERSION_ADD_FILE_STATUS) {
2349         VersionAddFileStatus(store);
2350     }
2351     if (oldVersion < VERSION_SET_FILE_STATUS_DEFAULT) {
2352         VersionSetFileStatusDefault(store);
2353     }
2354     if (oldVersion < VERSION_ADD_CHECK_FLAG) {
2355         VersionAddCheckFlag(store);
2356     }
2357     if (oldVersion < VERSION_ADD_ROOT_DIRECTORY) {
2358         VersionAddRootDirectory(store);
2359     }
2360     if (oldVersion < VERSION_FIX_SYNC_METATIME_TRIGGER) {
2361         VersionFixSyncMetatimeTrigger(store);
2362     }
2363     if (oldVersion < VERSION_FIX_RETRY_TRIGGER) {
2364         VersionFixRetryTrigger(store);
2365     }
2366 
2367     if (oldVersion < VERSION_REMOVE_CLOUD_SYNC_FUNC_TRIGGER) {
2368         VersionRemoveCloudSyncFuncTrigger(store);
2369     }
2370 
2371     if (oldVersion < VERSION_ADD_ATTRIBUTE) {
2372         VersionAddAttribute(store);
2373     }
2374     if (oldVersion < VERSION_ADD_THM_FLAG) {
2375         VersionAddThmFlag(store);
2376     }
2377     if (oldVersion < VERSION_ADD_SRC_CLOUD_ID) {
2378         VersionAddSrcCloudId(store);
2379     }
2380     OnUpgradeExtend(store, oldVersion, newVersion);
2381 
2382     return NativeRdb::E_OK;
2383 }
2384 
CreateDentryFile(MetaBase metaBase,std::string destParentCloudId)2385 int32_t CloudDiskRdbStore::CreateDentryFile(MetaBase metaBase, std::string destParentCloudId)
2386 {
2387     auto metaFileCallBack = [&metaBase] (MetaBase &m) {
2388         m.size = metaBase.size;
2389         m.name = metaBase.name;
2390         m.cloudId = metaBase.cloudId;
2391         m.atime = metaBase.atime;
2392         m.mtime = metaBase.mtime;
2393         m.fileType = metaBase.fileType;
2394         m.mode = metaBase.mode;
2395     };
2396     auto metaFile = MetaFileMgr::GetInstance().GetCloudDiskMetaFile(userId_, bundleName_, destParentCloudId);
2397     int32_t ret = metaFile->DoLookupAndCreate(metaBase.name, metaFileCallBack);
2398     if (ret != E_OK) {
2399         LOGE("create new dentry failed, ret : %{public}d", ret);
2400     }
2401     return ret;
2402 }
2403 
getCopyValues(std::string srcCloudId,std::string destCloudId,std::string destParentCloudId,std::shared_ptr<NativeRdb::ResultSet> resultSet,ValuesBucket & fileInfo)2404 static void getCopyValues(std::string srcCloudId, std::string destCloudId, std::string destParentCloudId,
2405                           std::shared_ptr<NativeRdb::ResultSet> resultSet, ValuesBucket &fileInfo)
2406 {
2407     int32_t isDirectory;
2408     CloudDiskRdbUtils::GetInt(FileColumn::IS_DIRECTORY, isDirectory, resultSet);
2409     std::string sha256;
2410     CloudDiskRdbUtils::GetString(FileColumn::FILE_SHA256, sha256, resultSet);
2411     int64_t fileTimeRecycled;
2412     CloudDiskRdbUtils::GetLong(FileColumn::FILE_TIME_RECYCLED, fileTimeRecycled, resultSet);
2413     int64_t metaTimeEdited;
2414     CloudDiskRdbUtils::GetLong(FileColumn::META_TIME_EDITED, metaTimeEdited, resultSet);
2415     int64_t fileTimeVisit;
2416     CloudDiskRdbUtils::GetLong(FileColumn::FILE_TIME_VISIT, fileTimeVisit, resultSet);
2417     int32_t syncStatus;
2418     CloudDiskRdbUtils::GetInt(FileColumn::SYNC_STATUS, syncStatus, resultSet);
2419     std::string fileCalegory;
2420     CloudDiskRdbUtils::GetString(FileColumn::FILE_CATEGORY, fileCalegory, resultSet);
2421     int32_t isFavorite;
2422     CloudDiskRdbUtils::GetInt(FileColumn::IS_FAVORITE, isFavorite, resultSet);
2423     int32_t checkFlag;
2424     CloudDiskRdbUtils::GetInt(FileColumn::CHECK_FLAG, checkFlag, resultSet);
2425     std::string rootDirectory;
2426     CloudDiskRdbUtils::GetString(FileColumn::ROOT_DIRECTORY, rootDirectory, resultSet);
2427     std::string attribute;
2428     CloudDiskRdbUtils::GetString(FileColumn::ATTRIBUTE, attribute, resultSet);
2429     int32_t thmFlag;
2430     CloudDiskRdbUtils::GetInt(FileColumn::THM_FLAG, thmFlag, resultSet);
2431     thmFlag = thmFlag == FLAG_NOT_EXIST ? thmFlag : FLAG_TO_BE_UPLOAD;
2432     int32_t lcdFlag;
2433     CloudDiskRdbUtils::GetInt(FileColumn::LCD_FLAG, lcdFlag, resultSet);
2434     lcdFlag = lcdFlag == FLAG_NOT_EXIST ? lcdFlag : FLAG_TO_BE_UPLOAD;
2435     int32_t noNeedUpload;
2436     CloudDiskRdbUtils::GetInt(FileColumn::NO_NEED_UPLOAD, noNeedUpload, resultSet);
2437 
2438     fileInfo.PutString(FileColumn::CLOUD_ID, destCloudId);
2439     fileInfo.PutInt(FileColumn::IS_DIRECTORY, isDirectory);
2440     fileInfo.PutString(FileColumn::PARENT_CLOUD_ID, destParentCloudId);
2441     fileInfo.PutString(FileColumn::FILE_SHA256, sha256);
2442     fileInfo.PutLong(FileColumn::FILE_TIME_RECYCLED, fileTimeRecycled);
2443     fileInfo.PutLong(FileColumn::META_TIME_EDITED, metaTimeEdited);
2444     fileInfo.PutLong(FileColumn::FILE_TIME_VISIT, fileTimeVisit);
2445     fileInfo.PutInt(FileColumn::DIRECTLY_RECYCLED, DIRECTLY_RECYCLED_COPY);
2446     fileInfo.PutLong(FileColumn::VERSION, VERSION_COPY);
2447     fileInfo.PutLong(FileColumn::OPERATE_TYPE, static_cast<int>(OperationType::COPY));
2448     fileInfo.PutInt(FileColumn::SYNC_STATUS, syncStatus);
2449     fileInfo.PutInt(FileColumn::POSITION, CLOUD);
2450     fileInfo.PutInt(FileColumn::DIRTY_TYPE, static_cast<int>(DirtyType::TYPE_COPY));
2451     fileInfo.PutString(FileColumn::FILE_CATEGORY, fileCalegory);
2452     fileInfo.PutInt(FileColumn::IS_FAVORITE, isFavorite);
2453     fileInfo.PutInt(FileColumn::FILE_STATUS, static_cast<int>(FileStatus::UNKNOW));
2454     fileInfo.PutInt(FileColumn::CHECK_FLAG, checkFlag);
2455     fileInfo.PutString(FileColumn::ROOT_DIRECTORY, rootDirectory);
2456     fileInfo.PutString(FileColumn::ATTRIBUTE, attribute);
2457     fileInfo.PutInt(FileColumn::THM_FLAG, thmFlag);
2458     fileInfo.PutInt(FileColumn::LCD_FLAG, lcdFlag);
2459     fileInfo.PutInt(FileColumn::NO_NEED_UPLOAD, noNeedUpload);
2460     fileInfo.PutString(FileColumn::SRC_CLOUD_ID, srcCloudId);
2461 }
2462 
InsertCopyData(std::string srcCloudId,std::string destCloudId,std::string destParentCloudId,std::shared_ptr<NativeRdb::ResultSet> resultSet)2463 int32_t CloudDiskRdbStore::InsertCopyData(std::string srcCloudId, std::string destCloudId,
2464                                           std::string destParentCloudId,
2465                                           std::shared_ptr<NativeRdb::ResultSet> resultSet)
2466 {
2467     RDBPTR_IS_NULLPTR(rdbStore_);
2468     ValuesBucket fileInfo;
2469     int32_t ret;
2470     getCopyValues(srcCloudId, destCloudId, destParentCloudId, resultSet, fileInfo);
2471     std::string fileName;
2472     CloudDiskRdbUtils::GetString(FileColumn::FILE_NAME, fileName, resultSet);
2473     std::string oldName = fileName;
2474     RETURN_ON_ERR(CheckIsConflict(oldName, destParentCloudId, fileName));
2475     fileInfo.PutString(FileColumn::FILE_NAME, fileName);
2476     int64_t fileSize;
2477     CloudDiskRdbUtils::GetLong(FileColumn::FILE_SIZE, fileSize, resultSet);
2478     fileInfo.PutLong(FileColumn::FILE_SIZE, fileSize);
2479     int64_t fileTimeAdded = UTCTimeMilliSeconds();
2480     fileInfo.PutLong(FileColumn::FILE_TIME_ADDED, fileTimeAdded);
2481     int32_t fileType;
2482     CloudDiskRdbUtils::GetInt(FileColumn::FILE_TYPE, fileType, resultSet);
2483     fileInfo.PutInt(FileColumn::FILE_TYPE, fileType);
2484     int64_t fileTimeEdited = UTCTimeMilliSeconds();
2485     fileInfo.PutLong(FileColumn::FILE_TIME_EDITED, fileTimeEdited);
2486 
2487     TransactionOperations rdbTransaction(rdbStore_);
2488     auto [rdbRet, transaction] = rdbTransaction.Start();
2489     if (rdbRet != E_OK) {
2490         LOGE("rdbstore begin transaction failed ,ret = %{public}d", rdbRet);
2491         return E_RDB;
2492     }
2493     int64_t outRowId = 0;
2494     std::tie(rdbRet, outRowId) = transaction->Insert(FileColumn::FILES_TABLE, fileInfo);
2495     if (rdbRet != E_OK) {
2496         LOGE("insert new file record in DB failed ,ret = %{public}d", rdbRet);
2497         return rdbRet;
2498     }
2499 
2500     MetaBase metaBase(fileName, destCloudId);
2501     metaBase.size = static_cast<uint64_t>(fileSize);
2502     metaBase.fileType = fileType;
2503     metaBase.atime = static_cast<uint64_t>(fileTimeAdded);
2504     metaBase.mtime = static_cast<uint64_t>(fileTimeEdited);
2505     metaBase.mode = metaBase.mode = S_IFREG | STAT_MODE_FILE;
2506     ret = CreateDentryFile(metaBase, destParentCloudId);
2507     if (ret != E_OK) {
2508         LOGE("create new dentry failed, ret = %{public}d", ret);
2509         return ret;
2510     }
2511     rdbTransaction.Finish();
2512     CloudDiskSyncHelper::GetInstance().RegisterTriggerSync(bundleName_, userId_);
2513     return ret;
2514 }
2515 
CopyFile(std::string srcCloudId,std::string destCloudId,std::string bundleName,const int userId,std::string destPath)2516 int32_t CloudDiskRdbStore::CopyFile(std::string srcCloudId, std::string destCloudId, std::string bundleName,
2517                                     const int userId, std::string destPath)
2518 {
2519     std::string parentCloudId = CloudFileUtils::GetCloudId(destPath);
2520     AbsRdbPredicates getCopyMsg = AbsRdbPredicates(FileColumn::FILES_TABLE);
2521     getCopyMsg.EqualTo(FileColumn::CLOUD_ID, srcCloudId);
2522     auto resultSet = rdbStore_->QueryByStep(getCopyMsg, FileColumn::DISK_CLOUD_FOR_COPY);
2523     if (resultSet == nullptr) {
2524         LOGE("Query failed, no such file in rdb");
2525         return E_RDB;
2526     }
2527 
2528     if (resultSet->GoToNextRow() != E_OK) {
2529         LOGE("result set to file info go to next row failed");
2530         return E_RDB;
2531     }
2532 
2533     int32_t ret = InsertCopyData(srcCloudId, destCloudId, parentCloudId, resultSet);
2534     if (ret!= E_OK) {
2535         LOGE("Failed to insert copy data to the rdb, ret = %{public}d", ret);
2536     }
2537     return ret;
2538 }
2539 }