From 55dd7f7c85c235dffde70070d9ae96b908bc7623 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Carlos=20Gonz=C3=A1lez?= Date: Wed, 29 Jan 2025 18:03:30 +0100 Subject: [PATCH] chore: clean up --- binding.gyp | 5 - .../placeholders_interface/PlaceHolderInfo.h | 5 +- include/placeholders_interface/Placeholders.h | 1 + include/sync_root_interface/Utilities.h | 1 + .../sync_root_interface/callbacks/Callbacks.h | 9 - include/sync_root_watcher/DirectoryWatcher.h | 64 --- .../sync_root_watcher/DownloadMutexManager.h | 46 -- include/sync_root_watcher/SyncRootWatcher.h | 44 -- include/virtual_drive/Wrappers.h | 2 - native-src/main.cpp | 35 -- .../placeholders_interface/Planceholders.cpp | 65 ++- native-src/sync_root_interface/SyncRoot.cpp | 1 - native-src/sync_root_interface/Utilities.cpp | 31 ++ .../callbacks/FetchData/FetchData.cpp | 1 - .../NotifyFileAddedCallback.cpp | 252 ----------- .../NotifyMessage/NofifyMessageCallback.cpp | 150 ------- .../sync_root_watcher/DirectoryWatcher.cpp | 405 ------------------ .../sync_root_watcher/SyncRootWatcher.cpp | 215 ---------- native-src/virtual_drive/Wrappers.cpp | 134 +----- src/addon.ts | 1 - src/virtual-drive.ts | 25 -- 21 files changed, 102 insertions(+), 1390 deletions(-) delete mode 100644 include/sync_root_watcher/DirectoryWatcher.h delete mode 100644 include/sync_root_watcher/DownloadMutexManager.h delete mode 100644 include/sync_root_watcher/SyncRootWatcher.h delete mode 100644 native-src/sync_root_interface/callbacks/NotifyFileAdded/NotifyFileAddedCallback.cpp delete mode 100644 native-src/sync_root_interface/callbacks/NotifyMessage/NofifyMessageCallback.cpp delete mode 100644 native-src/sync_root_watcher/DirectoryWatcher.cpp delete mode 100644 native-src/sync_root_watcher/SyncRootWatcher.cpp diff --git a/binding.gyp b/binding.gyp index 458d69eb..ad8ec2ef 100644 --- a/binding.gyp +++ b/binding.gyp @@ -28,11 +28,7 @@ "native-src/sync_root_interface/callbacks/FetchData/TransferContext.cpp", "native-src/sync_root_interface/callbacks/FetchPlaceholder/FetchPlaceholder.cpp", "native-src/sync_root_interface/callbacks/NotifyDelete/NotifyDeleteCallback.cpp", - "native-src/sync_root_interface/callbacks/NotifyFileAdded/NotifyFileAddedCallback.cpp", - "native-src/sync_root_interface/callbacks/NotifyMessage/NofifyMessageCallback.cpp", "native-src/sync_root_interface/callbacks/NotifyRename/NotifyRenameCallback.cpp", - "native-src/sync_root_watcher/DirectoryWatcher.cpp", - "native-src/sync_root_watcher/SyncRootWatcher.cpp", "native-src/virtual_drive/Wrappers.cpp" ], "include_dirs": [ @@ -41,7 +37,6 @@ "include/placeholders_interface", "include/sync_root_interface", "include/sync_root_interface/callbacks", - "include/sync_root_watcher", "include/types", "include/virtual_drive" ], diff --git a/include/placeholders_interface/PlaceHolderInfo.h b/include/placeholders_interface/PlaceHolderInfo.h index 9987d8f3..1042cadb 100644 --- a/include/placeholders_interface/PlaceHolderInfo.h +++ b/include/placeholders_interface/PlaceHolderInfo.h @@ -25,7 +25,10 @@ enum class PinState Excluded = 4, }; - +struct FileState { + PinState pinstate; + SyncState syncstate; +}; class PlaceHolderInfo { diff --git a/include/placeholders_interface/Placeholders.h b/include/placeholders_interface/Placeholders.h index e98b4d82..b720bb10 100644 --- a/include/placeholders_interface/Placeholders.h +++ b/include/placeholders_interface/Placeholders.h @@ -48,4 +48,5 @@ class Placeholders static std::string GetFileIdentity(const std::wstring &filePath); static void UpdateFileIdentity(const std::wstring &filePath, const std::wstring &fileIdentity, bool isDirectory); static PlaceholderAttribute GetAttribute(const std::wstring &filePath); + static FileState GetPlaceholderInfo(const std::wstring &directoryPath); }; \ No newline at end of file diff --git a/include/sync_root_interface/Utilities.h b/include/sync_root_interface/Utilities.h index 980ec585..f36df097 100644 --- a/include/sync_root_interface/Utilities.h +++ b/include/sync_root_interface/Utilities.h @@ -10,6 +10,7 @@ class Utilities static void ApplyCustomOverwriteStateToPlaceholderFile(_In_ LPCWSTR path, _In_ LPCWSTR filename, _In_ winrt::StorageProviderItemProperty &prop); static std::wstring ProcessErrorNameToWString(_In_ ProcessErrorName error); static std::wstring FileOperationErrorToWString(_In_ FileOperationError error); + static bool IsTemporaryFile(const std::wstring &fullPath); static winrt::com_array ConvertSidToStringSid(_In_ PSID sid) diff --git a/include/sync_root_interface/callbacks/Callbacks.h b/include/sync_root_interface/callbacks/Callbacks.h index 34d20d7a..c52e89a5 100644 --- a/include/sync_root_interface/callbacks/Callbacks.h +++ b/include/sync_root_interface/callbacks/Callbacks.h @@ -1,7 +1,6 @@ #pragma once #include -#include "DirectoryWatcher.h" void register_threadsafe_callbacks(napi_env env, InputSyncCallbacks input); @@ -24,11 +23,3 @@ void CALLBACK fetch_data_callback_wrapper(_In_ CONST CF_CALLBACK_INFO *callbackI // Fetch Data Cancel Callback void register_threadsafe_cancel_fetch_data_callback(const std::string &resource_name, napi_env env, InputSyncCallbacks input); void CALLBACK cancel_fetch_data_callback_wrapper(_In_ CONST CF_CALLBACK_INFO *callbackInfo, _In_ CONST CF_CALLBACK_PARAMETERS *callbackParameters); - -// Notify File Added Callback. This is a fake callback -void notify_file_added_call(napi_env env, napi_value js_callback, void *context, void *data); -void register_threadsafe_notify_file_added_callback(FileChange &change, const std::string &resource_name, napi_env env, InputSyncCallbacksThreadsafe input); - -// Notify message from node-win -void notify_message_call(napi_env env, napi_value js_callback, void *context, void *data); -void register_threadsafe_message_callback(FileChange &change, const std::string &resource_name, napi_env env, InputSyncCallbacksThreadsafe input); \ No newline at end of file diff --git a/include/sync_root_watcher/DirectoryWatcher.h b/include/sync_root_watcher/DirectoryWatcher.h deleted file mode 100644 index f8844e1e..00000000 --- a/include/sync_root_watcher/DirectoryWatcher.h +++ /dev/null @@ -1,64 +0,0 @@ -#pragma once - -#include -#include "PlaceHolderInfo.h" - -// 20GB limit -#define FILE_SIZE_LIMIT 21474836480 - -enum ChangeType -{ - NEW_FILE, - NEW_FOLDER, - MODIFIED_FILE, - ERROR_FILE_SIZE_EXCEEDED, - ERROR_FOLDER_SIZE_EXCEEDED, - ERROR_FILE_ZERO_SIZE, - ERROR_FILE_NON_EXTENSION, - OTHER -}; -struct FileChange -{ - std::wstring path; - bool item_added; - ChangeType type; - std::wstring message; -}; - -struct InputCallbacks -{ - napi_ref notify_file_added_callback_ref; - napi_ref notify_message_callback_ref; -}; - -struct FileState { - PinState pinstate; - SyncState syncstate; -}; - -struct InputSyncCallbacksThreadsafe -{ - napi_threadsafe_function notify_file_added_threadsafe_callback; - napi_threadsafe_function notify_message_threadsafe_callback; -}; -class DirectoryWatcher -{ -public: - std::atomic _shouldRun; - void Initialize(_In_ PCWSTR path, _In_ std::function &, napi_env env, InputSyncCallbacksThreadsafe input)> callback, napi_env env, InputSyncCallbacksThreadsafe input); - winrt::Windows::Foundation::IAsyncAction ReadChangesAsync(); - static FileState getPlaceholderInfo(const std::wstring &directoryPath); - void Cancel(); - -private: - winrt::Windows::Foundation::IAsyncAction ReadChangesInternalAsync(); - std::map _file_sizes; - winrt::handle _dir; - std::wstring _path; - napi_env _env; - InputSyncCallbacksThreadsafe _input; - std::unique_ptr _notify; - OVERLAPPED _overlapped{}; - winrt::Windows::Foundation::IAsyncAction _readTask; - std::function &, napi_env env, InputSyncCallbacksThreadsafe input)> _callback; -}; diff --git a/include/sync_root_watcher/DownloadMutexManager.h b/include/sync_root_watcher/DownloadMutexManager.h deleted file mode 100644 index c08d9e4d..00000000 --- a/include/sync_root_watcher/DownloadMutexManager.h +++ /dev/null @@ -1,46 +0,0 @@ -#include -#include - -class DownloadMutexManager -{ -public: - // Elimina las maneras de copiar y asignar - DownloadMutexManager(const DownloadMutexManager &) = delete; - DownloadMutexManager &operator=(const DownloadMutexManager &) = delete; - - static DownloadMutexManager &getInstance() - { - static DownloadMutexManager instance; // Instancia única - return instance; - } - - void waitReady() - { - std::unique_lock lock(mtx); - cv.wait(lock, [this]() - { return ready; }); - } - - void setReady(bool loadFinished) - { - if (loadFinished) - { - std::lock_guard lock(mtx); - ready = true; - cv.notify_one(); - } - } - void resetReady() - { - std::lock_guard lock(mtx); - ready = false; - } - -private: - std::mutex mtx; - std::condition_variable cv; - bool ready = false; - - // Constructor privado - DownloadMutexManager() = default; -}; diff --git a/include/sync_root_watcher/SyncRootWatcher.h b/include/sync_root_watcher/SyncRootWatcher.h deleted file mode 100644 index 5583b750..00000000 --- a/include/sync_root_watcher/SyncRootWatcher.h +++ /dev/null @@ -1,44 +0,0 @@ -#pragma once - -#include "DirectoryWatcher.h" -#include -#include -#include - -class SyncRootWatcher -{ - std::shared_ptr watcherThread; - - public: - void WatchAndWait(const wchar_t *syncRootPath, napi_env env, InputSyncCallbacksThreadsafe input); - static BOOL WINAPI Stop(DWORD reason); - - static auto StatusChanged(winrt::Windows::Foundation::EventHandler const& handler) - { - return s_statusChanged.add(handler); - } - - static auto StatusChanged(winrt::event_token const& token) noexcept - { - return s_statusChanged.remove(token); - } - - static auto State() { return s_state; } - - ~SyncRootWatcher() { - if (watcherThread && watcherThread->joinable()) { - watcherThread->join(); - } - } - - private: - static void WatcherTask(const wchar_t *syncRootPath, napi_env env, InputSyncCallbacksThreadsafe input); - static void InitDirectoryWatcher(const wchar_t *syncRootPath, napi_env env, InputSyncCallbacksThreadsafe input); - static void OnSyncRootFileChanges(_In_ std::list& changes, napi_env env, InputSyncCallbacksThreadsafe input); - - static DirectoryWatcher s_directoryWatcher; - static bool s_shutdownWatcher; - static winrt::Windows::Storage::Provider::StorageProviderState s_state; - static winrt::event> s_statusChanged; -}; - diff --git a/include/virtual_drive/Wrappers.h b/include/virtual_drive/Wrappers.h index 749c50e4..49248a1b 100644 --- a/include/virtual_drive/Wrappers.h +++ b/include/virtual_drive/Wrappers.h @@ -6,7 +6,6 @@ napi_value CreatePlaceholderFile(napi_env env, napi_callback_info args); napi_value UnregisterSyncRootWrapper(napi_env env, napi_callback_info args); napi_value RegisterSyncRootWrapper(napi_env env, napi_callback_info args); napi_value ConnectSyncRootWrapper(napi_env env, napi_callback_info args); -napi_value WatchAndWaitWrapper(napi_env env, napi_callback_info args); napi_value CreateEntryWrapper(napi_env env, napi_callback_info args); napi_value DisconnectSyncRootWrapper(napi_env env, napi_callback_info args); napi_value GetFileIdentityWrapper(napi_env env, napi_callback_info args); @@ -15,7 +14,6 @@ napi_value UpdateSyncStatusWrapper(napi_env env, napi_callback_info args); napi_value GetPlaceholderStateWrapper(napi_env env, napi_callback_info args); napi_value GetPlaceholderWithStatePendingWrapper(napi_env env, napi_callback_info args); napi_value ConvertToPlaceholderWrapper(napi_env env, napi_callback_info args); -napi_value CloseMutexWrapper(napi_env env, napi_callback_info args); napi_value DeleteFileSyncRootWrapper(napi_env env, napi_callback_info args); napi_value UpdateFileIdentityWrapper(napi_env env, napi_callback_info args); napi_value DehydrateFileWrapper(napi_env env, napi_callback_info args); diff --git a/native-src/main.cpp b/native-src/main.cpp index 965470d4..ac64dfbb 100644 --- a/native-src/main.cpp +++ b/native-src/main.cpp @@ -3,24 +3,6 @@ napi_value init(napi_env env, napi_value exports) { - // Watcher - napi_property_descriptor watchAndWaitDesc = { - "watchAndWait", // nombre de la función en JS - nullptr, - WatchAndWaitWrapper, // nombre de tu función en C++ - nullptr, - nullptr, - nullptr, - napi_default, - nullptr}; - - napi_status defineWatchAndWaitStatus = napi_define_properties(env, exports, 1, &watchAndWaitDesc); - if (defineWatchAndWaitStatus != napi_ok) - { - napi_throw_error(env, nullptr, "Failed to define WatchAndWait function"); - return nullptr; - } - // CreatePlaceholderFileWrapper napi_property_descriptor desc = { "createPlaceholderFile", @@ -247,23 +229,6 @@ napi_value init(napi_env env, napi_value exports) return nullptr; } - napi_property_descriptor closeMutexDesc = { - "closeMutex", - nullptr, - CloseMutexWrapper, - nullptr, - nullptr, - nullptr, - napi_default, - nullptr}; - - napi_status closeMutexStatus = napi_define_properties(env, exports, 1, &closeMutexDesc); - if (closeMutexStatus != napi_ok) - { - napi_throw_error(env, nullptr, "Failed to define closeMutex function"); - return nullptr; - } - napi_property_descriptor updateFileIdentityDesc = { "updateFileIdentity", nullptr, diff --git a/native-src/placeholders_interface/Planceholders.cpp b/native-src/placeholders_interface/Planceholders.cpp index f957c4c7..360df8ee 100644 --- a/native-src/placeholders_interface/Planceholders.cpp +++ b/native-src/placeholders_interface/Planceholders.cpp @@ -4,7 +4,6 @@ #include "PlaceholderInfo.h" #include #include -#include "SyncRootWatcher.h" #include #include #include @@ -451,6 +450,68 @@ CF_PLACEHOLDER_STATE GetPlaceholderStateMock(const std::wstring &filePath) } } + +FileState Placeholders::GetPlaceholderInfo(const std::wstring &directoryPath) +{ + + constexpr auto fileIdMaxLength = 400; + const auto infoSize = sizeof(CF_PLACEHOLDER_BASIC_INFO) + fileIdMaxLength; + auto info = PlaceHolderInfo(reinterpret_cast(new char[infoSize]), FileHandle::deletePlaceholderInfo); + + FileState fileState; + auto fileHandle = handleForPath(directoryPath); + + if (!fileHandle) + { + printf("Error: Invalid file handle.\n"); + fileState.pinstate = PinState::Unspecified; + fileState.syncstate = SyncState::Undefined; + return fileState; + } + + HRESULT result = CfGetPlaceholderInfo(fileHandle.get(), CF_PLACEHOLDER_INFO_BASIC, info.get(), Utilities::sizeToDWORD(infoSize), nullptr); + + if (result != S_OK) + { + printf("CfGetPlaceholderInfo failed with HRESULT %lx\n", result); + fileState.pinstate = PinState::Unspecified; + fileState.syncstate = SyncState::Undefined; + return fileState; + } + + auto pinStateOpt = info.pinState(); + auto syncStateOpt = info.syncState(); + + if (syncStateOpt.has_value()) + { + + SyncState syncState = syncStateOpt.value(); + + printf("placeholderInfo.SyncState: %s\n", syncStateToString(syncState).c_str()); + } + else + { + printf("placeholderInfo.SyncState: No value\n"); + } + + if (pinStateOpt.has_value()) + { + + PinState pinState = pinStateOpt.value(); + + printf("placeholderInfo.PinState: %s\n", pinStateToString(pinState).c_str()); + } + else + { + printf("placeholderInfo.PinState: No value\n"); + } + + fileState.pinstate = pinStateOpt.value_or(PinState::Unspecified); + fileState.syncstate = syncStateOpt.value_or(SyncState::Undefined); + + return fileState; +} + std::vector Placeholders::GetPlaceholderWithStatePending(const std::wstring &directoryPath) { std::vector resultPaths; @@ -466,7 +527,7 @@ std::vector Placeholders::GetPlaceholderWithStatePending(const std } else if (entry.is_regular_file()) { - FileState placeholderState = DirectoryWatcher::getPlaceholderInfo(path); + FileState placeholderState = Placeholders::GetPlaceholderInfo(path); bool isFileValidForSync = (placeholderState.syncstate == SyncState::Undefined || placeholderState.syncstate == SyncState::NotInSync); if (isFileValidForSync && IsFileValidForSync(path)) { diff --git a/native-src/sync_root_interface/SyncRoot.cpp b/native-src/sync_root_interface/SyncRoot.cpp index 5e5ce0c0..04125741 100644 --- a/native-src/sync_root_interface/SyncRoot.cpp +++ b/native-src/sync_root_interface/SyncRoot.cpp @@ -5,7 +5,6 @@ #include #include #include "Logger.h" -#include "DownloadMutexManager.h" namespace fs = std::filesystem; // variable to disconect diff --git a/native-src/sync_root_interface/Utilities.cpp b/native-src/sync_root_interface/Utilities.cpp index 3152dd1a..fa664e3b 100644 --- a/native-src/sync_root_interface/Utilities.cpp +++ b/native-src/sync_root_interface/Utilities.cpp @@ -160,6 +160,37 @@ void Utilities::ApplyTransferStateToFile(_In_ PCWSTR fullPath, _In_ CF_CALLBACK_ } } + +bool Utilities::IsTemporaryFile(const std::wstring &fullPath) +{ + size_t fileNameStart = fullPath.find_last_of(L'\\') + 1; + if (fullPath.size() >= fileNameStart + 2 && fullPath.compare(fileNameStart, 2, L"~$") == 0) + { + return true; + } + + std::array tempExtensions = { + L".tmp", + L".laccdb", + L".ldb", + L".bak", + L".sv$", + L".psdtmp", + L".~tmp" + }; + + for (const auto &ext : tempExtensions) + { + if (fullPath.size() >= ext.size() && + fullPath.compare(fullPath.size() - ext.size(), ext.size(), ext) == 0) + { + return true; + } + } + + return false; +} + std::wstring Utilities::ProcessErrorNameToWString(ProcessErrorName error) { switch (error) diff --git a/native-src/sync_root_interface/callbacks/FetchData/FetchData.cpp b/native-src/sync_root_interface/callbacks/FetchData/FetchData.cpp index 0a5c987b..97fe2f72 100644 --- a/native-src/sync_root_interface/callbacks/FetchData/FetchData.cpp +++ b/native-src/sync_root_interface/callbacks/FetchData/FetchData.cpp @@ -4,7 +4,6 @@ #include #include #include -#include #include #include #include diff --git a/native-src/sync_root_interface/callbacks/NotifyFileAdded/NotifyFileAddedCallback.cpp b/native-src/sync_root_interface/callbacks/NotifyFileAdded/NotifyFileAddedCallback.cpp deleted file mode 100644 index afeddfae..00000000 --- a/native-src/sync_root_interface/callbacks/NotifyFileAdded/NotifyFileAddedCallback.cpp +++ /dev/null @@ -1,252 +0,0 @@ -#include "Callbacks.h" -#include "DirectoryWatcher.h" -#include "Logger.h" -#include -inline std::mutex mtx; -inline std::condition_variable cv; -inline bool ready = false; -inline bool callbackResult = false; -inline std::wstring server_identity; -inline std::wstring global_path; -inline ChangeType global_type; -#include -#include -#include "Logger.h" - -struct FetchDataArgs -{ - std::wstring fileIdentityArg; -}; - -napi_value response_callback_fn_added(napi_env env, napi_callback_info info) -{ - size_t argc = 2; - napi_value argv[2]; - napi_get_cb_info(env, info, &argc, argv, nullptr, nullptr); - - if (argc < 2) - { - wprintf(L"This function must receive at least two arguments"); - return nullptr; - } - - napi_valuetype valueType; - - // Verificar el primer argumento: debería ser un booleano - napi_typeof(env, argv[0], &valueType); - if (valueType != napi_boolean) - { - wprintf(L"First argument should be boolean\n"); - return nullptr; - } - - bool confirmation_response; - napi_get_value_bool(env, argv[0], &confirmation_response); - - // Verificar el segundo argumento: debería ser un string - napi_typeof(env, argv[1], &valueType); - if (valueType != napi_string) - { - wprintf(L"Second argument should be string\n"); - return nullptr; - } - - size_t response_len; - napi_get_value_string_utf16(env, argv[1], nullptr, 0, &response_len); - - std::wstring response_wstr(response_len, L'\0'); - - napi_get_value_string_utf16(env, argv[1], (char16_t *)response_wstr.data(), response_len + 1, &response_len); - - // wprintf(L"input path: %s .\n", response_wstr.c_str()); - - std::lock_guard lock(mtx); - ready = true; - callbackResult = confirmation_response; - server_identity = response_wstr.c_str(); - - bool result = false; - - if (confirmation_response) - { - Sleep(100); - result = Placeholders::ConvertToPlaceholder(global_path, server_identity); - if (global_type == NEW_FILE) - { - Logger::getInstance().log("NEW FILE", LogLevel::INFO); - Placeholders::UpdatePinState(global_path, PinState::AlwaysLocal); - }; - } - - cv.notify_one(); - - napi_value result_value; - napi_get_boolean(env, result, &result_value); - - // Crear la promesa y obtener el deferred - napi_value promise; - napi_deferred deferred; - napi_create_promise(env, &deferred, &promise); - // print result - Logger::getInstance().log("Result: " + std::to_string(result), LogLevel::INFO); - // Resolver la promesa con el resultado booleano - napi_resolve_deferred(env, deferred, result_value); - - return promise; -} - -void notify_file_added_call(napi_env env, napi_value js_callback, void *context, void *data) -{ - napi_status status; - FetchDataArgs *args = static_cast(data); - napi_value js_string_path, js_response_callback_fn, undefined, result; - - std::u16string u16_fileIdentity(args->fileIdentityArg.begin(), args->fileIdentityArg.end()); - - napi_create_string_utf16(env, u16_fileIdentity.c_str(), u16_fileIdentity.size(), &js_string_path); - - napi_create_function(env, "responseCallback", NAPI_AUTO_LENGTH, response_callback_fn_added, nullptr, &js_response_callback_fn); - - napi_value args_to_js_callback[2] = {js_string_path, js_response_callback_fn}; - - status = napi_get_undefined(env, &undefined); - if (status != napi_ok) - { - fprintf(stderr, "Failed to get undefined value.\n"); - return; - } - - { - std::lock_guard lock(mtx); - ready = false; - } - - status = napi_call_function(env, undefined, js_callback, 2, args_to_js_callback, &result); - if (status != napi_ok) - { - Logger::getInstance().log("Failed to call JS function.", LogLevel::ERROR); - Logger::getInstance().log("Failed to call JS function in notifyAddedCallback.", LogLevel::ERROR); - return; - } - delete args; -} - -// TODO: move to utils -std::string wstringToString(const std::wstring &wstr) -{ - // Configurar la conversión a UTF-8 - std::wstring_convert> converter; - - // Utilizar la conversión - return converter.to_bytes(wstr); -} - -void register_threadsafe_notify_file_added_callback(FileChange &change, const std::string &resource_name, napi_env env, InputSyncCallbacksThreadsafe input) -{ - std::wstring *dataToSend = new std::wstring(change.type == NEW_FILE ? change.path : (change.path + L"\\")); - napi_status status = napi_call_threadsafe_function(input.notify_file_added_threadsafe_callback, dataToSend, napi_tsfn_blocking); - - global_path = change.path; - global_type = change.type; - { - std::unique_lock lock(mtx); - while (!ready) - { - cv.wait(lock); - } - } - // HANDLE placeholder; - - if (!std::filesystem::exists(change.path)) - { - Logger::getInstance().log("File does not exist", LogLevel::ERROR); - return; - }; - - try - { - - // if (change.type == NEW_FOLDER) - // { - // placeholder = CreateFileW( - // change.path.c_str(), - // FILE_LIST_DIRECTORY | WRITE_DAC, - // FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, - // nullptr, - // OPEN_EXISTING, - // FILE_FLAG_BACKUP_SEMANTICS, - // nullptr); - // } - // else if (change.type == NEW_FILE) - // { //|| change.type == MODIFIED_FILE) { - // placeholder = CreateFileW( - // change.path.c_str(), - // FILE_READ_ATTRIBUTES | FILE_WRITE_ATTRIBUTES, - // FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, - // nullptr, - // OPEN_EXISTING, - // 0, - // nullptr); - // } - - // winrt::handle placeholder(CreateFileW(change.path.c_str(), 0, FILE_READ_DATA, nullptr, OPEN_EXISTING, 0, nullptr)); - - // const std::wstring idStr = server_identity; - // LPCVOID idStrLPCVOID = static_cast(idStr.c_str()); - // DWORD idStrByteLength = static_cast(idStr.size() * sizeof(wchar_t)); - - if (callbackResult) - { - try - { - // Logger::getInstance().log("Convert to placeholder in sync" + Logger::fromWStringToString(change.path), LogLevel::INFO); - // Sleep(100); - // HRESULT hr = CfConvertToPlaceholder(placeholder, idStrLPCVOID, idStrByteLength, CF_CONVERT_FLAG_MARK_IN_SYNC, nullptr, nullptr); - // show error - // if (FAILED(hr) || hr != S_OK) - // { - // Logger::getInstance().log("Error converting to placeholder, ConvertToPlaceholder failed,", LogLevel::ERROR); - // } - - // if (change.type == NEW_FILE) { - // Placeholders::UpdatePinState(change.path.c_str(), PinState::AlwaysLocal); - // }; - // CloseHandle(placeholder); - } - catch (...) - { - Logger::getInstance().log("Error converting to placeholder, CloseHandle failed.", LogLevel::ERROR); - } - } - } - catch (...) - { - Logger::getInstance().log("Error converting to placeholder", LogLevel::ERROR); - } - - // if (!callbackResult) { - // wprintf(L"not in sync\n"); - // winrt::StorageProviderItemProperty prop; - // prop.Id(1); - // prop.Value(L"Value1"); - // prop.IconResource(L"imageres.dll,-1402"); - - // std::filesystem::path fullPath(change.path.c_str()); - // std::wstring directory = fullPath.parent_path().wstring(); - // std::wstring filename = fullPath.filename().wstring(); - - // // this is adding the custom state over the existing one - // Utilities::ApplyCustomOverwriteStateToPlaceholderFile(directory.c_str(), filename.c_str(), prop); - // } - - if (status != napi_ok) - { - Logger::getInstance().log("Unable to call notify_file_added_threadsafe_callback", LogLevel::ERROR); - napi_throw_error(env, NULL, "Unable to call notify_file_added_threadsafe_callback"); - } - - { - std::lock_guard lock(mtx); - ready = false; // Reset ready - } -}; diff --git a/native-src/sync_root_interface/callbacks/NotifyMessage/NofifyMessageCallback.cpp b/native-src/sync_root_interface/callbacks/NotifyMessage/NofifyMessageCallback.cpp deleted file mode 100644 index 9db33c62..00000000 --- a/native-src/sync_root_interface/callbacks/NotifyMessage/NofifyMessageCallback.cpp +++ /dev/null @@ -1,150 +0,0 @@ -#include "Callbacks.h" -#include "DirectoryWatcher.h" -#include "Logger.h" -#include "Utilities.h" -#include "ProcessTypes.h" -#include -#include -#include -#include - -inline std::mutex mtx; -inline std::condition_variable cv; -inline bool ready = false; -inline bool callbackResult = false; -inline std::wstring server_identity; -#include - -struct ProcessNotifications -{ - std::wstring message; - std::wstring action; - std::wstring errorName; -}; - -napi_value response_callback_fn_nofify(napi_env env, napi_callback_info info) -{ - // just 1 argument - size_t argc = 1; - napi_value argv[1]; - napi_get_cb_info(env, info, &argc, argv, nullptr, nullptr); - - if (argc < 1) - { - wprintf(L"[Error] This function must receive at least two arguments"); - return nullptr; - } - napi_valuetype valueType; - - // Verificar el primer argumento: debería ser un booleano - napi_typeof(env, argv[0], &valueType); - if (valueType != napi_boolean) - { - wprintf(L"[Error] First argument should be boolean\n"); - return nullptr; - } - bool confirmation_response; - napi_get_value_bool(env, argv[0], &confirmation_response); - - std::lock_guard lock(mtx); - ready = true; - callbackResult = confirmation_response; - - cv.notify_one(); - - return nullptr; -} - -void notify_message_call(napi_env env, napi_value js_callback, void *context, void *data) -{ - napi_status status; - // std::wstring *receivedData = static_cast(data); - ProcessNotifications *args = static_cast(data); - napi_value js_message, js_action, js_errorName, js_response_callback_fn, undefined, result; - // asign data to the js_string - std::u16string u16_action(args->action.begin(), args->action.end()); - std::u16string u16_errorName(args->errorName.begin(), args->errorName.end()); - std::u16string u16_message(args->message.begin(), args->message.end()); - // napi_create_string_utf16(env, reinterpret_cast(receivedData->c_str()), receivedData->size(), &js_string1); - - status = napi_create_string_utf16(env, u16_action.c_str(), u16_action.size(), &js_action); - if (status != napi_ok) - { - fprintf(stderr, "[Error] Failed to create u16_action string.\n"); - return; - } - - status = napi_create_string_utf16(env, u16_errorName.c_str(), u16_errorName.size(), &js_errorName); - if (status != napi_ok) - { - fprintf(stderr, "[Error] Failed to create u16_errorName string.\n"); - return; - } - - status = napi_create_string_utf16(env, u16_message.c_str(), u16_message.size(), &js_message); - if (status != napi_ok) - { - fprintf(stderr, "[Error] Failed to create u16_message string.\n"); - return; - } - - // asign the nofify callback function to the js_response_callback_fn - napi_create_function(env, "responseCallback", NAPI_AUTO_LENGTH, response_callback_fn_nofify, nullptr, &js_response_callback_fn); - - napi_value args_to_js_callback[4] = {js_message, js_action, js_errorName, js_response_callback_fn}; - status = napi_get_undefined(env, &undefined); - if (status != napi_ok) - { - fprintf(stderr, "[Error] Failed to get undefined value.\n"); - return; - } - - { - std::lock_guard lock(mtx); - ready = false; - } - - status = napi_call_function(env, undefined, js_callback, 4, args_to_js_callback, &result); - if (status != napi_ok) - { - fprintf(stderr, "[Error] Failed to call JS function.\n"); - Logger::getInstance().log("Failed to call JS function in notifyMessageCallback.", LogLevel::ERROR); - return; - } - delete args; -} - -void register_threadsafe_message_callback(FileChange &change, const std::string &resource_name, napi_env env, InputSyncCallbacksThreadsafe input) -{ - ProcessNotifications *args = new ProcessNotifications(); - switch (change.type) - { - case ERROR_FILE_SIZE_EXCEEDED: - args->action = Utilities::FileOperationErrorToWString(FileOperationError::UPLOAD_ERROR); - args->errorName = Utilities::ProcessErrorNameToWString(ProcessErrorName::FILE_TOO_BIG); - args->message = change.message; - break; - case ERROR_FILE_ZERO_SIZE: - args->action = Utilities::FileOperationErrorToWString(FileOperationError::UPLOAD_ERROR); - args->errorName = Utilities::ProcessErrorNameToWString(ProcessErrorName::EMPTY_FILE); - args->message = change.message; - break; - case ERROR_FILE_NON_EXTENSION: - args->action = Utilities::FileOperationErrorToWString(FileOperationError::UPLOAD_ERROR); - args->errorName = Utilities::ProcessErrorNameToWString(ProcessErrorName::FILE_NON_EXTENSION); - args->message = change.message; - break; - default: - break; - } - - napi_status status = napi_call_threadsafe_function(input.notify_message_threadsafe_callback, args, napi_tsfn_blocking); - - { - std::unique_lock lock(mtx); - while (!ready) - { - cv.wait(lock); - } - } -}; \ No newline at end of file diff --git a/native-src/sync_root_watcher/DirectoryWatcher.cpp b/native-src/sync_root_watcher/DirectoryWatcher.cpp deleted file mode 100644 index 3b44ee49..00000000 --- a/native-src/sync_root_watcher/DirectoryWatcher.cpp +++ /dev/null @@ -1,405 +0,0 @@ -#include "stdafx.h" -#include "DirectoryWatcher.h" -#include -#include -#include -#include "Logger.h" -#include "Utilities.h" - -const size_t c_bufferSize = 32768; // sizeof(FILE_NOTIFY_INFORMATION) * 100; - -namespace fs = std::filesystem; - -bool IsTemporaryFile(const std::wstring &fullPath) -{ - // Comprueba el prefijo ~$ usado por Word, Excel y PowerPoint - size_t fileNameStart = fullPath.find_last_of(L'\\') + 1; - if (fullPath.size() >= fileNameStart + 2 && fullPath.compare(fileNameStart, 2, L"~$") == 0) - { - return true; - } - - // Comprueba las extensiones de archivo temporales y las extensiones específicas mencionadas - std::array tempExtensions = { - L".tmp", // Extension genérica de archivo temporal - L".laccdb", // Access - L".ldb", // Access versión más antigua - L".bak", // AutoCAD backup - L".sv$", // AutoCAD autosave - L".psdtmp", // Photoshop (en algunos casos) - L".~tmp" // Algunos programas generan este tipo de archivos temporales - }; - - for (const auto &ext : tempExtensions) - { - if (fullPath.size() >= ext.size() && - fullPath.compare(fullPath.size() - ext.size(), ext.size(), ext) == 0) - { - return true; - } - } - - return false; -} - -void DirectoryWatcher::Initialize( - _In_ PCWSTR path, - _In_ std::function &, napi_env env, InputSyncCallbacksThreadsafe input)> callback, - napi_env env, - InputSyncCallbacksThreadsafe input) -{ - _path = path; - _notify.reset(reinterpret_cast(new char[c_bufferSize])); - - _callback = callback; - - _env = env; - - _input = input; - - _dir.attach( - CreateFileW(path, - FILE_LIST_DIRECTORY, - FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, - nullptr, - OPEN_EXISTING, - FILE_FLAG_BACKUP_SEMANTICS | FILE_FLAG_OVERLAPPED, - nullptr)); - if (_dir.get() == INVALID_HANDLE_VALUE) - { - throw winrt::hresult_error(HRESULT_FROM_WIN32(GetLastError())); - } -} - -winrt::Windows::Foundation::IAsyncAction DirectoryWatcher::ReadChangesAsync() -{ - _readTask = ReadChangesInternalAsync(); - return _readTask; -} - -std::uintmax_t getDirectorySize(const fs::path &directoryPath) -{ - std::uintmax_t size = 0; - - for (const auto &entry : fs::recursive_directory_iterator(directoryPath)) - { - if (fs::is_regular_file(entry)) - { - size += fs::file_size(entry.path()); - } - } - - return size; -} - -// void deletePlaceholderInfo(char *infoBuffer) -// { -// delete[] infoBuffer; -// } - - - -FileState DirectoryWatcher::getPlaceholderInfo(const std::wstring &directoryPath) -{ - - constexpr auto fileIdMaxLength = 400; - const auto infoSize = sizeof(CF_PLACEHOLDER_BASIC_INFO) + fileIdMaxLength; - auto info = PlaceHolderInfo(reinterpret_cast(new char[infoSize]), FileHandle::deletePlaceholderInfo); - - FileState fileState; - auto fileHandle = handleForPath(directoryPath); - - if (!fileHandle) - { - printf("Error: Invalid file handle.\n"); - fileState.pinstate = PinState::Unspecified; - fileState.syncstate = SyncState::Undefined; - return fileState; - } - - HRESULT result = CfGetPlaceholderInfo(fileHandle.get(), CF_PLACEHOLDER_INFO_BASIC, info.get(), Utilities::sizeToDWORD(infoSize), nullptr); - - if (result != S_OK) - { - printf("CfGetPlaceholderInfo failed with HRESULT %lx\n", result); - fileState.pinstate = PinState::Unspecified; - fileState.syncstate = SyncState::Undefined; - return fileState; - } - - auto pinStateOpt = info.pinState(); - auto syncStateOpt = info.syncState(); - - if (syncStateOpt.has_value()) - { - - SyncState syncState = syncStateOpt.value(); - - printf("placeholderInfo.SyncState: %s\n", syncStateToString(syncState).c_str()); - } - else - { - printf("placeholderInfo.SyncState: No value\n"); - } - - if (pinStateOpt.has_value()) - { - - PinState pinState = pinStateOpt.value(); - - printf("placeholderInfo.PinState: %s\n", pinStateToString(pinState).c_str()); - } - else - { - printf("placeholderInfo.PinState: No value\n"); - } - - fileState.pinstate = pinStateOpt.value_or(PinState::Unspecified); - fileState.syncstate = syncStateOpt.value_or(SyncState::Undefined); - - return fileState; -} - -bool isFileValid(const std::wstring &fullPath, std::list &result, FileChange fc) -{ - std::filesystem::path p(fullPath); - - Logger::getInstance().log("File Validation: " + Logger::fromWStringToString(fullPath), LogLevel::INFO); - if (std::filesystem::file_size(p) > FILE_SIZE_LIMIT) - { - Logger::getInstance().log("ERROR_FILE_SIZE_EXCEEDED", LogLevel::ERROR); - fc.type = ERROR_FILE_SIZE_EXCEEDED; - fc.item_added = false; - result.push_back(fc); - return false; - } - else if (std::filesystem::file_size(p) == 0) - { - Logger::getInstance().log("ERROR_FILE_ZERO_SIZE", LogLevel::ERROR); - fc.type = ERROR_FILE_ZERO_SIZE; - fc.item_added = false; - result.push_back(fc); - return false; - } - else if (p.extension().string().empty()) - { - Logger::getInstance().log("ERROR_FILE_NON_EXTENSION", LogLevel::ERROR); - fc.type = ERROR_FILE_NON_EXTENSION; - fc.item_added = false; - result.push_back(fc); - return false; - } - else - { - // Logger::getInstance().log("Pass File Validation", LogLevel::INFO); - return true; - } -} - -void ExploreDirectory(const std::wstring &directoryPath, std::list &result, FileChange fc) -{ - Logger::getInstance().log("New Folder: " + Logger::fromWStringToString(directoryPath), LogLevel::INFO); - fc.path = directoryPath; - fc.type = NEW_FOLDER; - fc.item_added = true; - result.push_back(fc); - - std::wstring searchPath = directoryPath + L"\\*"; - WIN32_FIND_DATAW data; - HANDLE hFind = FindFirstFileW(searchPath.c_str(), &data); - - if (hFind != INVALID_HANDLE_VALUE) - { - do - { - if (data.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) - { - if (wcscmp(data.cFileName, L".") != 0 && wcscmp(data.cFileName, L"..") != 0) - { - // Es un directorio, llama a la función recursivamente - std::wstring fullPath2 = directoryPath + L"\\" + data.cFileName; - ExploreDirectory(fullPath2, result, fc); - } - } - else - { - Logger::getInstance().log("New file processed recursively: " + Logger::fromWStringToString(data.cFileName), LogLevel::INFO); - std::wstring fullPath2 = directoryPath + L"\\" + data.cFileName; - FileChange fc; - if (isFileValid(fullPath2, result, fc)) - { - - fc.path = fullPath2; - fc.type = NEW_FILE; - fc.item_added = true; - result.push_back(fc); - } - } - } while (FindNextFileW(hFind, &data)); - FindClose(hFind); - } -} - -winrt::Windows::Foundation::IAsyncAction DirectoryWatcher::ReadChangesInternalAsync() -{ - co_await winrt::resume_background(); - - while (true) - { - Logger::getInstance().log("Watching...", LogLevel::INFO); - DWORD returned; - winrt::check_bool(ReadDirectoryChangesW( - _dir.get(), - _notify.get(), - c_bufferSize, - TRUE, - FILE_NOTIFY_CHANGE_ATTRIBUTES | FILE_NOTIFY_CHANGE_FILE_NAME | FILE_NOTIFY_CHANGE_DIR_NAME | FILE_NOTIFY_CHANGE_SIZE, - &returned, - &_overlapped, - nullptr)); - - DWORD transferred; - if (!GetOverlappedResult(_dir.get(), &_overlapped, &transferred, TRUE)) - { - DWORD error = GetLastError(); - if (error != ERROR_OPERATION_ABORTED) - { - throw winrt::hresult_error(HRESULT_FROM_WIN32(error)); - } - break; - } - - std::list result; - std::list addedFiles; - std::list removedFiles; - - FILE_NOTIFY_INFORMATION *next = _notify.get(); - while (next != nullptr) - { - std::wstring fullPath(_path); - fullPath.append(L"\\"); - fullPath.append(std::wstring_view(next->FileName, next->FileNameLength / sizeof(wchar_t))); - - FileChange fc; - fc.path = fullPath; - bool isTmpFile = IsTemporaryFile(fullPath); - - DWORD fileAttributes = GetFileAttributesW(fullPath.c_str()); - - bool isDirectory = (fileAttributes != INVALID_FILE_ATTRIBUTES) && (fileAttributes & FILE_ATTRIBUTE_DIRECTORY); - bool fileExists = (fileAttributes != INVALID_FILE_ATTRIBUTES); - bool isHidden = (fileAttributes & FILE_ATTRIBUTE_HIDDEN) != 0; - - if ((next->Action == FILE_ACTION_ADDED || (next->Action == FILE_ACTION_MODIFIED && !fileExists)) && !isTmpFile && !isDirectory && !isHidden) - { - Logger::getInstance().log("New File: " + Logger::fromWStringToString(fullPath), LogLevel::INFO); - if (isFileValid(fullPath, result, fc)) - { - fc.type = NEW_FILE; - fc.item_added = true; - result.push_back(fc); - } - } - else if (next->Action == FILE_ACTION_ADDED && isDirectory && !isHidden) - { - ExploreDirectory(fullPath, result, fc); - } - - else - { - fc.type = OTHER; - fc.item_added = false; - result.push_back(fc); - } - - // else if (next->Action == FILE_ACTION_MODIFIED && fileExists && !isTmpFile && !isDirectory && !isHidden) { - // wprintf(L"modified file1: %s\n", fullPath.c_str()); - // fc.type = MODIFIED_FILE; - // fc.item_added = true; - // result.push_back(fc); - // } - - // fc.file_added =( next->Action == FILE_ACTION_ADDED || (next->Action == FILE_ACTION_MODIFIED && !fileExists)) && !isTmpFile && !isDirectory; - - // wprintf(L"next->FileName: %ls\n", next->FileName); - // wprintf(L"next->Action: %d\n", next->Action); - // wprintf(L"fileExists: %d\n", fileExists); - // wprintf(L"isTmpFile: %d\n", isTmpFile); - // wprintf(L"isDirectory: %d\n", isDirectory); - - if (next->NextEntryOffset) - { - next = reinterpret_cast(reinterpret_cast(next) + next->NextEntryOffset); - } - else - { - next = nullptr; - } - } - - // for (auto path : addedFiles) { - - // std::wstring *dataToSend = new std::wstring(path); - // napi_status status = napi_call_threadsafe_function(_input.notify_file_added_threadsafe_callback, dataToSend, napi_tsfn_blocking); - - // CfConvertToPlaceholder(path.c_str()); - - // if (status != napi_ok) { - // napi_throw_error(_env, NULL, "Unable to call notify_file_added_threadsafe_callback"); - // } - // } - result.sort([](const FileChange &a, const FileChange &b) - { return std::tie(a.path, a.type) < std::tie(b.path, b.type); }); - - // Use unique to remove duplicates - result.unique([](const FileChange &a, const FileChange &b) - { return a.path == b.path && a.type == b.type; }); - - // ordernar de primero las paths de folders y luego las de archivos - result.sort([](const FileChange &a, const FileChange &b) - { - bool a_is_folder = a.path.back() == L'\\' || a.path.back() == L'/'; - bool b_is_folder = b.path.back() == L'\\' || b.path.back() == L'/'; - if (a_is_folder && !b_is_folder) - return true; - if (!a_is_folder && b_is_folder) - return false; - return a.path < b.path; }); - // ademas siempre por tamaño de primero los mas pesados - result.sort([](const FileChange &a, const FileChange &b) - { - std::uintmax_t a_size = 0; - std::uintmax_t b_size = 0; - if (a.type == NEW_FILE) - { - a_size = fs::file_size(a.path); - } - if (b.type == NEW_FILE) - { - b_size = fs::file_size(b.path); - } - return a_size > b_size; }); - // TODO: delete this, but it is used to Debug the results from watcher - // for (auto &change : result) - // { - // Logger::getInstance().log("Change: " + Logger::fromWStringToString(change.path), LogLevel::INFO); - // } - _callback(result, _env, _input); - } -} - -void DirectoryWatcher::Cancel() -{ - Logger::getInstance().log("Canceling DirectoryWatcher.\n", LogLevel::INFO); - - // Modificar la condición del bucle para verificar el estado adecuado de _readTask - while (_readTask && - (_readTask.Status() == winrt::AsyncStatus::Started || - _readTask.Status() == winrt::AsyncStatus::Canceled || - _readTask.Status() == winrt::AsyncStatus::Error) && - !CancelIoEx(_dir.get(), &_overlapped)) - { - Logger::getInstance().log("CancelIoEx failed.\n", LogLevel::ERROR); - Sleep(10); - } -} \ No newline at end of file diff --git a/native-src/sync_root_watcher/SyncRootWatcher.cpp b/native-src/sync_root_watcher/SyncRootWatcher.cpp deleted file mode 100644 index 80b52013..00000000 --- a/native-src/sync_root_watcher/SyncRootWatcher.cpp +++ /dev/null @@ -1,215 +0,0 @@ -#include "stdafx.h" -#include "SyncRootWatcher.h" -#include "DownloadMutexManager.h" -#include "DirectoryWatcher.h" -#include "Callbacks.h" -#include -#include -#include -#include - -namespace fs = std::filesystem; -#include "SyncRoot.h" -namespace winrt -{ - using namespace winrt::Windows::Foundation; - using namespace winrt::Windows::Storage::Provider; -} - -#include -#include - -DirectoryWatcher SyncRootWatcher::s_directoryWatcher; -bool SyncRootWatcher::s_shutdownWatcher; -winrt::StorageProviderState SyncRootWatcher::s_state; -winrt::event> SyncRootWatcher::s_statusChanged; - -void SyncRootWatcher::WatchAndWait(const wchar_t *syncRootPath, napi_env env, InputSyncCallbacksThreadsafe input) -{ - watcherThread = std::make_shared([this, syncRootPath, env, input] - { WatcherTask(syncRootPath, env, input); }); -} - -void SyncRootWatcher::WatcherTask(const wchar_t *syncRootPath, napi_env env, InputSyncCallbacksThreadsafe input) -{ - SetConsoleCtrlHandler(Stop, TRUE); - InitDirectoryWatcher(syncRootPath, env, input); - - if (syncRootPath == nullptr) - { - Logger::getInstance().log("syncRootPath null.", LogLevel::ERROR); - throw std::invalid_argument("syncRootPath must be a valid path."); - } - while (true) - { - try - { - auto task = s_directoryWatcher.ReadChangesAsync(); - - while (task.Status() == winrt::AsyncStatus::Started) - { - Sleep(1000); - - if (s_shutdownWatcher) - { - s_directoryWatcher.Cancel(); - } - } - - if (s_shutdownWatcher) - { - break; - } - } - catch (...) - { - Logger::getInstance().log("CloudProviderSyncRootWatcher watcher failed. Unknown error.", LogLevel::ERROR); - throw; - } - } -} - -void SyncRootWatcher::OnSyncRootFileChanges(_In_ std::list &changes, napi_env env, InputSyncCallbacksThreadsafe input) -{ - auto start = GetTickCount64(); - s_state = winrt::StorageProviderState::Syncing; - s_statusChanged(nullptr, nullptr); - - for (auto change : changes) - { - // TODO: it should be just one callback for all the errors -> need refactor - if ( - change.type == ERROR_FILE_SIZE_EXCEEDED || - change.type == ERROR_FOLDER_SIZE_EXCEEDED || - change.type == ERROR_FILE_ZERO_SIZE || - change.type == ERROR_FILE_NON_EXTENSION) - { - change.message = change.path.c_str(); - register_threadsafe_message_callback(change, "message", env, input); - } - else - { - // FileState fileState = DirectoryWatcher::getPlaceholderInfo(change.path); - DWORD attrib = GetFileAttributesW(change.path.c_str()); - if (!(attrib & FILE_ATTRIBUTE_DIRECTORY) && !change.item_added) - { - winrt::handle placeholder(CreateFileW(change.path.c_str(), 0, FILE_READ_DATA, nullptr, OPEN_EXISTING, 0, nullptr)); - - LARGE_INTEGER offset; - offset.QuadPart = 0; - LARGE_INTEGER length; - GetFileSizeEx(placeholder.get(), &length); - // length.QuadPart = MAXLONGLONG; - // bool isHydrated = fileState.pinstate == PinState::AlwaysLocal && fileState.syncstate == SyncState::InSync; - if (attrib & FILE_ATTRIBUTE_PINNED) // && !(isHydrated) - { - Logger::getInstance().log("Hydration file ", LogLevel::INFO); - - auto start = std::chrono::steady_clock::now(); - - HRESULT hr = CfHydratePlaceholder(placeholder.get(), offset, length, CF_HYDRATE_FLAG_NONE, NULL); - - if (FAILED(hr)) - { - Logger::getInstance().log("Error hydrating file " + Logger::fromWStringToString(change.path), LogLevel::ERROR); - } - - auto end = std::chrono::steady_clock::now(); - auto elapsedMilliseconds = std::chrono::duration_cast(end - start).count(); - - if (elapsedMilliseconds < 200) - { - Logger::getInstance().log("Already Hydrated: " + std::to_string(elapsedMilliseconds) + " ms", LogLevel::WARN); - } - else - { - Logger::getInstance().log("Hydration finished " + Logger::fromWStringToString(change.path), LogLevel::INFO); - Logger::getInstance() - .log("Mutex waiting for " + Logger::fromWStringToString(change.path), LogLevel::INFO); - DownloadMutexManager &mutexManager = DownloadMutexManager::getInstance(); - mutexManager.waitReady(); - Logger::getInstance().log("Mutex ready for " + Logger::fromWStringToString(change.path), LogLevel::INFO); - mutexManager.resetReady(); - Logger::getInstance().log("resetReady for " + Logger::fromWStringToString(change.path), LogLevel::INFO); - } - // Sleep(250); - // std::wstring folder = change.path.substr(0, change.path.find_last_of(L"\\")); - // Logger::getInstance().log("Marking folder as in sync" + Logger::fromWStringToString(folder), LogLevel::INFO); - // Placeholders::UpdateSyncStatus(folder, true, true); - } - else if (attrib & FILE_ATTRIBUTE_UNPINNED) - { - Logger::getInstance().log("Dehydrating file" + Logger::fromWStringToString(change.path), LogLevel::INFO); - HRESULT hr = CfDehydratePlaceholder(placeholder.get(), offset, length, CF_DEHYDRATE_FLAG_NONE, NULL); - - if (FAILED(hr)) - { - Logger::getInstance().log("Error dehydrating file " + Logger::fromWStringToString(change.path), LogLevel::ERROR); - } - else - { - Logger::getInstance().log("Dehydration finished " + Logger::fromWStringToString(change.path), LogLevel::INFO); - Placeholders::UpdateSyncStatus(change.path, true, fs::is_directory(change.path)); - Placeholders::UpdatePinState(change.path, PinState::OnlineOnly); - } - } - } - - if (change.type == NEW_FILE || change.type == NEW_FOLDER) - { - Sleep(250); - register_threadsafe_notify_file_added_callback(change, "file_added", env, input); - } - // else if ( change.type == MODIFIED_FILE) { - // wprintf(L"MODIFIED_FILE\n"); - // wprintf(L"change.path: %s\n", change.path.c_str()); - // MarkFileAsInSync(change.path); - // } - } - } - - try - { - - auto elapsed = GetTickCount64() - start; - if (elapsed < 3000) - { - Sleep(static_cast(3000 - elapsed)); - } - } - catch (...) - { - Logger::getInstance().log("Error sleeping the thread.", LogLevel::ERROR); - throw; - } - - s_state = winrt::StorageProviderState::InSync; - s_statusChanged(nullptr, nullptr); -} - -void SyncRootWatcher::InitDirectoryWatcher(const wchar_t *syncRootPath, napi_env env, InputSyncCallbacksThreadsafe input) -{ - try - { - s_directoryWatcher.Initialize(syncRootPath, OnSyncRootFileChanges, env, input); - } - catch (std::exception &e) - { - Logger::getInstance().log("Error initializing directory watcher: " + std::string(e.what()), LogLevel::ERROR); - throw; - } - catch (...) - { - Logger::getInstance().log("Could not init directory watcher.", LogLevel::ERROR); - throw; - } -} - -BOOL WINAPI -SyncRootWatcher::Stop(DWORD /*dwReason*/) -{ - Logger::getInstance().log("Stopping SyncRootWatcher.", LogLevel::INFO); - SyncRoot::DisconnectSyncRoot(); - s_shutdownWatcher = TRUE; - return TRUE; -} diff --git a/native-src/virtual_drive/Wrappers.cpp b/native-src/virtual_drive/Wrappers.cpp index 8638df06..a81e57e1 100644 --- a/native-src/virtual_drive/Wrappers.cpp +++ b/native-src/virtual_drive/Wrappers.cpp @@ -1,13 +1,10 @@ #include "stdafx.h" #include #include "Placeholders.h" -#include "SyncRoot.h" -#include "SyncRootWatcher.h" #include "Callbacks.h" #include "LoggerPath.h" -#include "DownloadMutexManager.h" -#include "DirectoryWatcher.h" #include +#include napi_value CreatePlaceholderFile(napi_env env, napi_callback_info args) { @@ -314,121 +311,6 @@ napi_value ConnectSyncRootWrapper(napi_env env, napi_callback_info args) } } -napi_value WatchAndWaitWrapper(napi_env env, napi_callback_info args) -{ - size_t argc = 2; - napi_value argv[2]; - - napi_get_cb_info(env, args, &argc, argv, nullptr, nullptr); - - if (argc < 2) - { - napi_throw_error(env, nullptr, "Se requieren más argumentos para WatchAndWait"); - return nullptr; - } - - InputCallbacks input = {}; - - // [CALLBACKS] file_added - napi_value notifyFileAddedCallback; - - if (napi_get_named_property(env, argv[1], "notifyFileAddedCallback", ¬ifyFileAddedCallback) == napi_ok) - { - napi_create_reference(env, notifyFileAddedCallback, 1, &input.notify_file_added_callback_ref); - } - - napi_valuetype valuetype; - napi_status type_status = napi_typeof(env, notifyFileAddedCallback, &valuetype); - if (type_status != napi_ok || valuetype != napi_function) - { - napi_throw_error(env, nullptr, "notifyFileAddedCallback should be a function."); - return nullptr; - } - - napi_value resource_name_value; - - std::string resource_name = "notify_file_added_callback"; - std::u16string converted_resource_name = std::u16string(resource_name.begin(), resource_name.end()); - - napi_create_string_utf16(env, converted_resource_name.c_str(), NAPI_AUTO_LENGTH, &resource_name_value); - - napi_value notify_file_added_callback_value; - napi_status status_ref = napi_get_reference_value(env, input.notify_file_added_callback_ref, ¬ify_file_added_callback_value); - - napi_threadsafe_function notify_file_added_threadsafe_callback; - - napi_status status_threadsafe = napi_create_threadsafe_function( - env, - notify_file_added_callback_value, - NULL, - resource_name_value, - 0, - 1, - NULL, - NULL, - NULL, - notify_file_added_call, - ¬ify_file_added_threadsafe_callback); - - // [CALLBACKS] notify_message - napi_value notifyMessageCallback; - - if (napi_get_named_property(env, argv[1], "notifyMessageCallback", ¬ifyMessageCallback) == napi_ok) - { - napi_create_reference(env, notifyMessageCallback, 1, &input.notify_message_callback_ref); - } - - napi_valuetype valuetype_message; - napi_status type_status_message = napi_typeof(env, notifyMessageCallback, &valuetype_message); - if (type_status_message != napi_ok || valuetype_message != napi_function) - { - napi_throw_error(env, nullptr, "notifyMessageCallback should be a function."); - return nullptr; - } - - napi_value resource_name_value_message; - - std::string resource_name_message = "notify_message_callback"; - std::u16string converted_resource_name_message = std::u16string(resource_name_message.begin(), resource_name_message.end()); - - napi_create_string_utf16(env, converted_resource_name_message.c_str(), NAPI_AUTO_LENGTH, &resource_name_value_message); - - napi_value notify_message_callback_value; - napi_status status_ref_message = napi_get_reference_value(env, input.notify_message_callback_ref, ¬ify_message_callback_value); - - napi_threadsafe_function notify_message_threadsafe_callback; - - napi_status status_threadsafe_message = napi_create_threadsafe_function( - env, - notify_message_callback_value, - NULL, - resource_name_value_message, - 0, - 1, - NULL, - NULL, - NULL, - notify_message_call, - ¬ify_message_threadsafe_callback); - - InputSyncCallbacksThreadsafe inputThreadsafe = {}; - inputThreadsafe.notify_file_added_threadsafe_callback = notify_file_added_threadsafe_callback; - inputThreadsafe.notify_message_threadsafe_callback = notify_message_threadsafe_callback; - - LPCWSTR syncRootPath; - size_t pathLength; - napi_get_value_string_utf16(env, argv[0], nullptr, 0, &pathLength); - syncRootPath = new WCHAR[pathLength + 1]; - napi_get_value_string_utf16(env, argv[0], reinterpret_cast(const_cast(syncRootPath)), pathLength + 1, nullptr); - - SyncRootWatcher watcher; - watcher.WatchAndWait(syncRootPath, env, inputThreadsafe); - - delete[] syncRootPath; - - return nullptr; -} - napi_value CreateEntryWrapper(napi_env env, napi_callback_info args) { size_t argc = 9; @@ -704,7 +586,7 @@ napi_value GetPlaceholderStateWrapper(napi_env env, napi_callback_info args) napi_get_value_string_utf16(env, argv[0], reinterpret_cast(widePath.get()), pathLength + 1, nullptr); // DWORD state = Placeholders::GetPlaceholderState(widePath.get()); - FileState state = DirectoryWatcher::getPlaceholderInfo(widePath.get()); + FileState state = Placeholders::GetPlaceholderInfo(widePath.get()); napi_value result; napi_create_object(env, &result); @@ -829,18 +711,6 @@ napi_value UpdateFileIdentityWrapper(napi_env env, napi_callback_info args) return result; } -napi_value CloseMutexWrapper(napi_env env, napi_callback_info args) -{ - - DownloadMutexManager &mutexManager = DownloadMutexManager::getInstance(); - mutexManager.setReady(true); - - napi_value result; - napi_get_boolean(env, true, &result); - - return result; -} - napi_value HydrateFileWrapper(napi_env env, napi_callback_info args) { size_t argc = 1; diff --git a/src/addon.ts b/src/addon.ts index 81a2cc54..f397e169 100644 --- a/src/addon.ts +++ b/src/addon.ts @@ -28,7 +28,6 @@ export type TAddon = { lastAccessTime: number, path: string, ): any; - closeMutex(): any; hydrateFile(path: string): Promise>; getPlaceholderAttribute(path: string): z.infer; dehydrateFile(path: string): z.infer; diff --git a/src/virtual-drive.ts b/src/virtual-drive.ts index 95ac662d..bc450801 100644 --- a/src/virtual-drive.ts +++ b/src/virtual-drive.ts @@ -119,26 +119,6 @@ class VirtualDrive { return result; } - getExtraCallbacks(): ExtraCallbacks { - const extraCallbackKeys: (keyof ExtraCallbacks)[] = [ - "notifyFileAddedCallback", - "notifyMessageCallback", - ]; - - const result: ExtraCallbacks = {}; - if (this.callbacks === undefined) { - throw new Error("Callbacks are not defined"); - } - - for (const key of extraCallbackKeys) { - if (this.callbacks[key] !== undefined) { - result[key] = this.callbacks[key]; - } - } - - return result; - } - createSyncRootFolder() { if (!fs.existsSync(this.syncRootPath)) { fs.mkdirSync(this.syncRootPath, { recursive: true }); @@ -297,7 +277,6 @@ class VirtualDrive { }; this.watcher.watchAndWait(); - // addon.watchAndWait(path, this.getExtraCallbacks()); } createFileByPath( @@ -472,10 +451,6 @@ class VirtualDrive { addon.updateFileIdentity(itemPath, id, isDirectory); } - closeDownloadMutex(): void { - return addon.closeMutex(); - } - async dehydrateFile(itemPath: string) { return addon.dehydrateFile(itemPath); }