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