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 ¬ifyData)
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 }