diff --git a/services/cloudsyncservice/include/data_sync/gallery_data_sync/gallery_file_const.h b/services/cloudsyncservice/include/data_sync/gallery_data_sync/gallery_file_const.h index 5eccba508564d623a5653b1e9f26f6b1b582afbf..6b204edcd232c6e5c12e2da81b5f1a9c2d843a53 100644 --- a/services/cloudsyncservice/include/data_sync/gallery_data_sync/gallery_file_const.h +++ b/services/cloudsyncservice/include/data_sync/gallery_data_sync/gallery_file_const.h @@ -19,6 +19,8 @@ #include #include "data_convertor.h" +#include "medialibrary_db_const.h" +#include "medialibrary_type_const.h" namespace OHOS { namespace FileManagement { diff --git a/services/cloudsyncservice/src/data_sync/gallery_data_sync/data_convertor.cpp b/services/cloudsyncservice/src/data_sync/gallery_data_sync/data_convertor.cpp index 2868fbbaf526ab82135d476f328f129f76b0f5f3..bc5c5940de5c150f83094398d1f5571ee46cfdf7 100644 --- a/services/cloudsyncservice/src/data_sync/gallery_data_sync/data_convertor.cpp +++ b/services/cloudsyncservice/src/data_sync/gallery_data_sync/data_convertor.cpp @@ -18,6 +18,7 @@ #include "rdb_errno.h" #include "dfs_error.h" +#include "gallery_file_const.h" #include "utils_log.h" #include "sdk_helper.h" @@ -148,6 +149,50 @@ int32_t DataConvertor::GetBool(const string &key, bool &val, NativeRdb::ResultSe int32_t DataConvertor::RecordToValueBucket(const DriveKit::DKRecord &record, NativeRdb::ValuesBucket &valueBucket) { + DriveKit::DKRecordData data; + record.GetRecordData(data); + DriveKit::DKRecordFieldMap properties = data[FILE_PROPERTIES]; + + auto size = GALLERY_FILE_COLUMNS.size(); + for (int i = 0 ; i < size; i++) { + auto field = GALLERY_FILE_COLUMNS[i]; + auto type = GALLERY_FILE_COLUMN_TYPES[i]; + if (properties.find(field) == properties.end()) { + LOGE("filed %{public}s not found in record.properties", field.c_str()); + continue; + } + switch (type) { + case DataType::INT: { + int value = properties[field]; + valueBucket.PutInt(field, value); + break; + } + case DataType::LONG: { + int64_t value = properties[field]; + valueBucket.PutInt(field, value); + break; + } + case DataType::STRING: { + string value = properties[field]; + valueBucket.PutString(field, value); + break; + } + case DataType::BOOL: { + bool value = properties[field]; + valueBucket.PutInt(field, value); + break; + } + case DataType::DOUBLE: { + double value = properties[field]; + valueBucket.PutDouble(field, value); + break; + } + default: { + LOGE("invalid data type %{public}d", static_cast(type)); + break; + } + } + } return E_OK; } } // namespace CloudSync diff --git a/services/cloudsyncservice/src/data_sync/gallery_data_sync/file_data_handler.cpp b/services/cloudsyncservice/src/data_sync/gallery_data_sync/file_data_handler.cpp index e67d774610f95fc320efabbce6dc6b507c0d2599..810f661e98762c2ba4e98ec175789616289906d3 100644 --- a/services/cloudsyncservice/src/data_sync/gallery_data_sync/file_data_handler.cpp +++ b/services/cloudsyncservice/src/data_sync/gallery_data_sync/file_data_handler.cpp @@ -18,6 +18,7 @@ #include "dfs_error.h" #include "utils_log.h" #include "gallery_file_const.h" +#include "meta_file.h" namespace OHOS { namespace FileManagement { @@ -41,6 +42,7 @@ void FileDataHandler::GetFetchCondition(FetchCondition &cond) int32_t FileDataHandler::OnFetchRecords(const shared_ptr> &records) { + LOGI("on fetch %{public}zu records", records->size()); int32_t ret = E_OK; for (const auto &it : *records) { const auto &record = it; @@ -87,18 +89,72 @@ int32_t FileDataHandler::OnFetchRecords(const shared_ptr> &reco break; } } + MetaFileMgr::GetInstance().ClearAll(); return ret; } +static int32_t DentryInsert(int userId, const DKRecord &record) +{ + DKRecordData data; + record.GetRecordData(data); + if (data.find(FILE_PROPERTIES) == data.end()) { + LOGE("record data cannot find properties"); + return E_INVAL_ARG; + } + DriveKit::DKRecordFieldMap prop = data[FILE_PROPERTIES]; + if (prop.find(MEDIA_DATA_DB_FILE_PATH) == prop.end() || prop.find(MEDIA_DATA_DB_SIZE) == prop.end() || + prop.find(MEDIA_DATA_DB_DATE_MODIFIED) == prop.end()) { + LOGE("record data cannot find some properties"); + return E_INVAL_ARG; + } + + const string sandboxPrefix = "/storage/media/local"; + string fullPath = prop[MEDIA_DATA_DB_FILE_PATH]; + size_t pos = fullPath.find_first_of(sandboxPrefix); + size_t lpos = fullPath.find_last_of("/"); + if (pos != 0 || pos == string::npos || lpos == string::npos) { + LOGE("invalid path %{private}s", fullPath.c_str()); + return E_INVAL_ARG; + } + string relativePath = fullPath.substr(sandboxPrefix.length(), lpos - sandboxPrefix.length()); + relativePath = (relativePath == "") ? "/" : relativePath; + string fileName = fullPath.substr(lpos + 1); + + string rawRecordId = record.GetRecordId(); + string cloudId = MetaFileMgr::RecordIdToCloudId(rawRecordId); + int64_t isize = prop[MEDIA_DATA_DB_SIZE]; + int64_t mtime = prop[MEDIA_DATA_DB_DATE_MODIFIED]; + + auto mFile = MetaFileMgr::GetInstance().GetMetaFile(userId, relativePath); + MetaBase mBaseLookup(fileName); + MetaBase mBase(fileName, cloudId); + mBase.size = isize; + mBase.mtime = mtime; + if (mFile->DoLookup(mBaseLookup) == E_OK) { + LOGE("dentry exist when insert, do update instead"); + return mFile->DoUpdate(mBase); + } + return mFile->DoCreate(mBase); +} + int32_t FileDataHandler::PullRecordInsert(const DKRecord &record) { - /* insert hmdfs dentry file here */ + /* check local file conflict */ + int ret = DentryInsert(userId_, record); + if (ret != E_OK) { + LOGE("MetaFile Create failed %{public}d", ret); + return ret; + } int64_t rowId; ValuesBucket values; - createConvertor_.RecordToValueBucket(record, values); + ret = createConvertor_.RecordToValueBucket(record, values); + if (ret != E_OK) { + LOGE("record to valuebucket failed"); + return E_INVAL_ARG; + } - int ret = Insert(rowId, values); + ret = Insert(rowId, values); if (ret != E_OK) { LOGE("Insert pull record failed"); return E_RDB; diff --git a/test/unittests/cloudsync_sa/data_sync/BUILD.gn b/test/unittests/cloudsync_sa/data_sync/BUILD.gn index 6fb083488bb4c2773ed77f6a1fcddd0c689e8f1e..11a4ccad658ae8ac74c1607f1611deb9ccbacc29 100644 --- a/test/unittests/cloudsync_sa/data_sync/BUILD.gn +++ b/test/unittests/cloudsync_sa/data_sync/BUILD.gn @@ -45,6 +45,7 @@ ohos_unittest("data_sync_manager_test") { ] deps = [ + "${utils_path}:libdistributedfiledentry", "${utils_path}:libdistributedfileutils", "//third_party/googletest:gmock_main", "//third_party/googletest:gtest_main", diff --git a/test/unittests/cloudsync_sa/ipc/BUILD.gn b/test/unittests/cloudsync_sa/ipc/BUILD.gn index 2ccb4a07acca91b187f12507b73ae8ff98b1481b..11f7b2217f4b13e3da9c0c27adbf093fbf8093da 100644 --- a/test/unittests/cloudsync_sa/ipc/BUILD.gn +++ b/test/unittests/cloudsync_sa/ipc/BUILD.gn @@ -81,6 +81,7 @@ ohos_unittest("cloud_sync_service_test") { ] deps = [ + "${utils_path}:libdistributedfiledentry", "${utils_path}:libdistributedfileutils", "//third_party/googletest:gmock_main", "//third_party/googletest:gtest_main", diff --git a/utils/dentry/include/meta_file.h b/utils/dentry/include/meta_file.h index 47f8dbf741a94a094825d87917f357bd4595d615..a38a75646ce4362189276c0b73ff8089d8fc237a 100644 --- a/utils/dentry/include/meta_file.h +++ b/utils/dentry/include/meta_file.h @@ -58,6 +58,9 @@ public: static MetaFileMgr instance_; return instance_; } + /* recordId is hex string of 256 bits, convert to u8 cloudId[32] to kernel */ + static std::string RecordIdToCloudId(const std::string hexStr); + static std::string CloudIdToRecordId(const std::string cloudId); std::shared_ptr GetMetaFile(uint32_t userId, const std::string &path); void ClearAll(); private: diff --git a/utils/dentry/src/meta_file.cpp b/utils/dentry/src/meta_file.cpp index 501633d26dff075846fa2fa3bca2787e03d99c55..825ecb11d01c5eac34de5a5d6b52bc4bdf301233 100644 --- a/utils/dentry/src/meta_file.cpp +++ b/utils/dentry/src/meta_file.cpp @@ -16,6 +16,7 @@ #include "meta_file.h" #include +#include #include #include @@ -740,5 +741,38 @@ void MetaFileMgr::ClearAll() metaFiles_.clear(); } +std::string MetaFileMgr::RecordIdToCloudId(const std::string hexStr) +{ + std::string result; + + for (std::size_t i = 0; i < hexStr.length(); i += 2) { + std::string hexByte = hexStr.substr(i, 2); + char *endPtr; + unsigned long hexValue = std::strtoul(hexByte.c_str(), &endPtr, 16); + + if (endPtr != hexByte.c_str() + hexByte.length()) { + LOGE("Invalid hexadecimal string: %{public}s", hexStr.c_str()); + return ""; + } + result += static_cast(hexValue); + } + if (result.size() > CLOUD_RECORD_ID_LEN) { + LOGE("Invalid result length %{public}zu", result.size()); + return ""; + } + + return result; +} + +std::string MetaFileMgr::CloudIdToRecordId(const std::string cloudId) +{ + std::stringstream result; + for (std::size_t i = 0; i < cloudId.length(); i++) { + uint8_t u8Byte = cloudId[i]; + result << std::setw(2) << std::setfill('0') << std::hex << static_cast(u8Byte); + } + return result.str(); +} + } // namespace FileManagement } // namespace OHOS