refactor event system

This commit is contained in:
2025-01-23 09:37:45 -06:00
parent e1c35624f6
commit 4241adb4d3
33 changed files with 1101 additions and 106 deletions

View File

@ -21,6 +21,7 @@
* Fixed invalid directory nullptr error on remote mounts * Fixed invalid directory nullptr error on remote mounts
* Fixed memory leak in event system * Fixed memory leak in event system
* Refactored application shutdown * Refactored application shutdown
* Refactored event system
* Updated build system to Alpine 3.21.0 * Updated build system to Alpine 3.21.0
* Updated build system to MinGW-w64 12.0.0 * Updated build system to MinGW-w64 12.0.0
* Updated copyright to 2018-2025 * Updated copyright to 2018-2025

View File

@ -25,8 +25,8 @@
#include "app_config.hpp" #include "app_config.hpp"
#include "comm/curl/multi_request.hpp" #include "comm/curl/multi_request.hpp"
#include "comm/i_http_comm.hpp" #include "comm/i_http_comm.hpp"
#include "events/event_system.hpp" #include "events/event_system2.hpp"
#include "events/events.hpp" #include "events/types/curl_error.hpp"
#include "utils/encryption.hpp" #include "utils/encryption.hpp"
namespace repertory { namespace repertory {
@ -137,6 +137,8 @@ public:
[[nodiscard]] static auto [[nodiscard]] static auto
make_request(const host_config &cfg, const request_type &request, make_request(const host_config &cfg, const request_type &request,
long &response_code, stop_type &stop_requested) -> bool { long &response_code, stop_type &stop_requested) -> bool {
REPERTORY_USES_FUNCTION_NAME();
if (request.decryption_token.has_value() && if (request.decryption_token.has_value() &&
not request.decryption_token.value().empty()) { not request.decryption_token.value().empty()) {
return make_encrypted_request(cfg, request, response_code, return make_encrypted_request(cfg, request, response_code,
@ -223,7 +225,8 @@ public:
} }
if (curl_code != CURLE_OK) { if (curl_code != CURLE_OK) {
event_system::instance().raise<curl_error>(url, curl_code); event_system2::instance().raise<curl_error>(curl_code, function_name,
url);
return false; return false;
} }

View File

@ -0,0 +1,123 @@
/*
Copyright <2018-2025> <scott.e.graves@protonmail.com>
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
*/
#ifndef REPERTORY_INCLUDE_EVENTS_EVENT_SYSTEM2_HPP_
#define REPERTORY_INCLUDE_EVENTS_EVENT_SYSTEM2_HPP_
namespace repertory {
class i_event;
class event_system2 final {
private:
static constexpr const std::uint8_t max_queue_retry{
30U,
};
const std::uint32_t max_queue_size{
std::thread::hardware_concurrency() * 4U,
};
static constexpr const std::chrono::seconds queue_wait_secs{
5s,
};
public:
event_system2(const event_system2 &) = delete;
event_system2(event_system2 &&) = delete;
auto operator=(const event_system2 &) -> event_system2 & = delete;
auto operator=(event_system2 &&) -> event_system2 & = delete;
protected:
event_system2() = default;
~event_system2() { stop(); }
public:
class event_consumer final {
public:
explicit event_consumer(std::function<void(const i_event &)> callback)
: callback_(std::move(callback)) {
event_system2::instance().attach(this);
}
event_consumer(std::string_view event_name,
std::function<void(const i_event &)> callback)
: callback_(std::move(callback)) {
event_system2::instance().attach(event_name, this);
}
~event_consumer() { event_system2::instance().release(this); }
public:
event_consumer(const event_consumer &) = delete;
event_consumer(event_consumer &&) = delete;
auto operator=(const event_consumer &) -> event_consumer & = delete;
auto operator=(event_consumer &&) -> event_consumer & = delete;
private:
std::function<void(const i_event &)> callback_;
public:
void notify_event(const i_event &event) { callback_(event); }
};
private:
static event_system2 event_system_;
public:
static auto instance() -> event_system2 &;
private:
std::unordered_map<std::string, std::deque<event_consumer *>>
event_consumers_;
std::recursive_mutex consumer_mutex_;
std::vector<std::shared_ptr<i_event>> event_list_;
std::condition_variable event_notify_;
std::mutex event_mutex_;
std::unique_ptr<std::thread> event_thread_;
std::mutex run_mutex_;
stop_type stop_requested_{false};
private:
[[nodiscard]] auto get_stop_requested() const -> bool;
void process_events();
void queue_event(std::shared_ptr<i_event> evt);
public:
void attach(event_consumer *consumer);
void attach(std::string_view event_name, event_consumer *consumer);
template <typename evt_t, typename... arg_t> void raise(arg_t &&...args) {
queue_event(std::make_shared<evt_t>(std::forward<arg_t>(args)...));
}
void release(event_consumer *consumer);
void start();
void stop();
};
} // namespace repertory
#endif // REPERTORY_INCLUDE_EVENTS_EVENT_SYSTEM2_HPP_

View File

@ -28,44 +28,6 @@
namespace repertory { namespace repertory {
// clang-format off // clang-format off
E_SIMPLE2(curl_error, error,
std::string, url, url, E_FROM_STRING,
CURLcode, res, res, E_FROM_CURL_CODE
);
E_SIMPLE3(debug_log, debug,
std::string, function, func, E_FROM_STRING,
std::string, api_path, ap, E_FROM_STRING,
std::string, data, data, E_FROM_STRING
);
E_SIMPLE1(directory_removed, debug,
std::string, api_path, ap, E_FROM_STRING
);
E_SIMPLE2(directory_removed_externally, warn,
std::string, api_path, ap, E_FROM_STRING,
std::string, source, src, E_FROM_STRING
);
E_SIMPLE2(directory_remove_failed, error,
std::string, api_path, ap, E_FROM_STRING,
std::string, error, err, E_FROM_STRING
);
E_SIMPLE2(drive_mount_failed, error,
std::string, location, loc, E_FROM_STRING,
std::string, result, res, E_FROM_STRING
);
E_SIMPLE1(drive_mounted, info,
std::string, location, loc, E_FROM_STRING
);
E_SIMPLE1(drive_mount_result, info,
std::string, result, res, E_FROM_STRING
);
E_SIMPLE1(drive_unmount_pending, info, E_SIMPLE1(drive_unmount_pending, info,
std::string, location, loc, E_FROM_STRING std::string, location, loc, E_FROM_STRING
); );

View File

@ -0,0 +1,40 @@
/*
Copyright <2018-2025> <scott.e.graves@protonmail.com>
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
*/
#ifndef REPERTORY_INCLUDE_EVENTS_I_EVENT_HPP_
#define REPERTORY_INCLUDE_EVENTS_I_EVENT_HPP_
#include "types/repertory.hpp"
namespace repertory {
class i_event {
INTERFACE_SETUP(i_event);
public:
[[nodiscard]] virtual auto get_event_level() const -> event_level = 0;
[[nodiscard]] virtual auto get_name() const -> std::string_view = 0;
[[nodiscard]] virtual auto get_single_line() const -> std::string = 0;
};
} // namespace repertory
#endif // REPERTORY_INCLUDE_EVENTS_EVENT_HPP_

View File

@ -0,0 +1,73 @@
/*
Copyright <2018-2025> <scott.e.graves@protonmail.com>
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
*/
#ifndef REPERTORY_INCLUDE_EVENTS_TYPES_CURL_ERROR_HPP_
#define REPERTORY_INCLUDE_EVENTS_TYPES_CURL_ERROR_HPP_
#include "events/i_event.hpp"
#include "types/repertory.hpp"
namespace repertory {
struct curl_error final : public i_event {
curl_error() = default;
curl_error(CURLcode code_, std::string_view function_name_, std::string url_)
: code(code_),
function_name(std::string{function_name_}),
url(std::move(url_)) {}
static constexpr const std::string_view name{"curl_error"};
CURLcode code{};
std::string function_name;
std::string url;
[[nodiscard]] auto get_event_level() const -> event_level override {
return event_level::error;
}
[[nodiscard]] auto get_name() const -> std::string_view override {
return name;
}
[[nodiscard]] auto get_single_line() const -> std::string override {
return fmt::format("{}|func|{}|url|{}|code|{}", name, function_name, url,
static_cast<int>(code));
}
};
} // namespace repertory
NLOHMANN_JSON_NAMESPACE_BEGIN
template <> struct adl_serializer<repertory::curl_error> {
static void to_json(json &data, const repertory::curl_error &value) {
data["code"] = value.code;
data["function_name"] = value.function_name;
data["url"] = value.url;
}
static void from_json(const json &data, repertory::curl_error &value) {
data.at("code").get_to<CURLcode>(value.code);
data.at("function_name").get_to<std::string>(value.function_name);
data.at("url").get_to<std::string>(value.url);
}
};
NLOHMANN_JSON_NAMESPACE_END
#endif // REPERTORY_INCLUDE_EVENTS_TYPES_CURL_ERROR_HPP_

View File

@ -0,0 +1,67 @@
/*
Copyright <2018-2025> <scott.e.graves@protonmail.com>
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
*/
#ifndef REPERTORY_INCLUDE_EVENTS_TYPES_DEBUG_LOG_HPP_
#define REPERTORY_INCLUDE_EVENTS_TYPES_DEBUG_LOG_HPP_
#include "events/i_event.hpp"
#include "types/repertory.hpp"
namespace repertory {
struct debug_log final : public i_event {
debug_log() = default;
debug_log(std::string_view function_name_, std::string msg_)
: function_name(std::string(function_name_)), msg(std::move(msg_)) {}
static constexpr const std::string_view name{"debug_log"};
std::string function_name;
std::string msg;
[[nodiscard]] auto get_event_level() const -> event_level override {
return event_level::debug;
}
[[nodiscard]] auto get_name() const -> std::string_view override {
return name;
}
[[nodiscard]] auto get_single_line() const -> std::string override {
return fmt::format("{}|func|{}|msg|{}", name, function_name, msg);
}
};
} // namespace repertory
NLOHMANN_JSON_NAMESPACE_BEGIN
template <> struct adl_serializer<repertory::debug_log> {
static void to_json(json &data, const repertory::debug_log &value) {
data["function_name"] = value.function_name;
data["msg"] = value.msg;
}
static void from_json(const json &data, repertory::debug_log &value) {
data.at("function_name").get_to<std::string>(value.function_name);
data.at("msg").get_to<std::string>(value.msg);
}
};
NLOHMANN_JSON_NAMESPACE_END
#endif // REPERTORY_INCLUDE_EVENTS_TYPES_DEBUG_LOG_HPP_

View File

@ -0,0 +1,77 @@
/*
Copyright <2018-2025> <scott.e.graves@protonmail.com>
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
*/
#ifndef REPERTORY_INCLUDE_EVENTS_TYPES_DIRECTORY_REMOVE_FAILED_HPP_
#define REPERTORY_INCLUDE_EVENTS_TYPES_DIRECTORY_REMOVE_FAILED_HPP_
#include "events/i_event.hpp"
#include "types/repertory.hpp"
namespace repertory {
struct directory_remove_failed final : public i_event {
directory_remove_failed() = default;
directory_remove_failed(std::string api_path_, api_error error_,
std::string_view function_name_)
: api_path(std::move(api_path_)),
error(error_),
function_name(std::string(function_name_)) {}
static constexpr const std::string_view name{"directory_remove_failed"};
std::string api_path;
api_error error{};
std::string function_name;
[[nodiscard]] auto get_event_level() const -> event_level override {
return event_level::error;
}
[[nodiscard]] auto get_name() const -> std::string_view override {
return name;
}
[[nodiscard]] auto get_single_line() const -> std::string override {
return fmt::format("{}|func|{}|ap|{}|error|{}", name, function_name,
api_path, api_error_to_string(error));
}
};
} // namespace repertory
NLOHMANN_JSON_NAMESPACE_BEGIN
template <> struct adl_serializer<repertory::directory_remove_failed> {
static void to_json(json &data,
const repertory::directory_remove_failed &value) {
data["api_path"] = value.api_path;
data["error"] = repertory::api_error_to_string(value.error);
data["function_name"] = value.function_name;
}
static void from_json(const json &data,
repertory::directory_remove_failed &value) {
data.at("api_path").get_to<std::string>(value.api_path);
value.error =
repertory::api_error_from_string(data.at("error").get<std::string>());
data.at("function_name").get_to<std::string>(value.function_name);
}
};
NLOHMANN_JSON_NAMESPACE_END
#endif // REPERTORY_INCLUDE_EVENTS_TYPES_DIRECTORY_REMOVE_FAILED_HPP_

View File

@ -0,0 +1,68 @@
/*
Copyright <2018-2025> <scott.e.graves@protonmail.com>
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
*/
#ifndef REPERTORY_INCLUDE_EVENTS_TYPES_DIRECTORY_REMOVED_HPP_
#define REPERTORY_INCLUDE_EVENTS_TYPES_DIRECTORY_REMOVED_HPP_
#include "events/i_event.hpp"
#include "types/repertory.hpp"
namespace repertory {
struct directory_removed final : public i_event {
directory_removed() = default;
directory_removed(std::string api_path_, std::string_view function_name_)
: api_path(std::move(api_path_)),
function_name(std::string(function_name_)) {}
static constexpr const std::string_view name{"directory_removed"};
std::string api_path;
std::string function_name;
[[nodiscard]] auto get_event_level() const -> event_level override {
return event_level::debug;
}
[[nodiscard]] auto get_name() const -> std::string_view override {
return name;
}
[[nodiscard]] auto get_single_line() const -> std::string override {
return fmt::format("{}|func|{}|ap|{}", name, function_name, api_path);
}
};
} // namespace repertory
NLOHMANN_JSON_NAMESPACE_BEGIN
template <> struct adl_serializer<repertory::directory_removed> {
static void to_json(json &data, const repertory::directory_removed &value) {
data["api_path"] = value.api_path;
data["function_name"] = value.function_name;
}
static void from_json(const json &data, repertory::directory_removed &value) {
data.at("api_path").get_to<std::string>(value.api_path);
data.at("function_name").get_to<std::string>(value.function_name);
}
};
NLOHMANN_JSON_NAMESPACE_END
#endif // REPERTORY_INCLUDE_EVENTS_TYPES_DIRECTORY_REMOVED_HPP_

View File

@ -0,0 +1,77 @@
/*
Copyright <2018-2025> <scott.e.graves@protonmail.com>
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
*/
#ifndef REPERTORY_INCLUDE_EVENTS_TYPES_DIRECTORY_REMOVED_EXTERNALLY_HPP_
#define REPERTORY_INCLUDE_EVENTS_TYPES_DIRECTORY_REMOVED_EXTERNALLY_HPP_
#include "events/i_event.hpp"
#include "types/repertory.hpp"
namespace repertory {
struct directory_removed_externally final : public i_event {
directory_removed_externally() = default;
directory_removed_externally(std::string api_path_,
std::string_view function_name_,
std::string source_path_)
: api_path(std::move(api_path_)),
function_name(std::string(function_name_)),
source_path(std::move(source_path_)) {}
static constexpr const std::string_view name{"directory_removed_externally"};
std::string api_path;
std::string function_name;
std::string source_path;
[[nodiscard]] auto get_event_level() const -> event_level override {
return event_level::warn;
}
[[nodiscard]] auto get_name() const -> std::string_view override {
return name;
}
[[nodiscard]] auto get_single_line() const -> std::string override {
return fmt::format("{}|func|{}|ap|{}|src|{}", name, function_name, api_path,
source_path);
}
};
} // namespace repertory
NLOHMANN_JSON_NAMESPACE_BEGIN
template <> struct adl_serializer<repertory::directory_removed_externally> {
static void to_json(json &data,
const repertory::directory_removed_externally &value) {
data["api_path"] = value.api_path;
data["function_name"] = value.function_name;
data["source_path"] = value.source_path;
}
static void from_json(const json &data,
repertory::directory_removed_externally &value) {
data.at("api_path").get_to<std::string>(value.api_path);
data.at("function_name").get_to<std::string>(value.function_name);
data.at("source_path").get_to<std::string>(value.source_path);
}
};
NLOHMANN_JSON_NAMESPACE_END
#endif // REPERTORY_INCLUDE_EVENTS_TYPES_DIRECTORY_REMOVED_EXTERNALLY_HPP_

View File

@ -0,0 +1,77 @@
/*
Copyright <2018-2025> <scott.e.graves@protonmail.com>
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
*/
#ifndef REPERTORY_INCLUDE_EVENTS_TYPES_DRIVE_MOUNT_FAILED_HPP_
#define REPERTORY_INCLUDE_EVENTS_TYPES_DRIVE_MOUNT_FAILED_HPP_
#if defined(_WIN32)
#include "events/i_event.hpp"
#include "types/repertory.hpp"
namespace repertory {
struct drive_mount_failed final : public i_event {
drive_mount_failed() = default;
drive_mount_failed(std::string_view function_name_,
std::string mount_location_, NTSTATUS status_)
: function_name(std::string(function_name_)),
mount_location(std::move(mount_location_)),
status(status_) {}
static constexpr const std::string_view name{"drive_mount_failed"};
std::string function_name;
std::string mount_location;
NTSTATUS status{};
[[nodiscard]] auto get_event_level() const -> event_level override {
return event_level::error;
}
[[nodiscard]] auto get_name() const -> std::string_view override {
return name;
}
[[nodiscard]] auto get_single_line() const -> std::string override {
return fmt::format("{}|func|{}|location|{}|status|{}", name, function_name,
mount_location, status);
}
};
} // namespace repertory
NLOHMANN_JSON_NAMESPACE_BEGIN
template <> struct adl_serializer<repertory::drive_mount_failed> {
static void to_json(json &data, const repertory::drive_mount_failed &value) {
data["function_name"] = value.function_name;
data["mount_location"] = value.mount_location;
data["status"] = value.status;
}
static void from_json(const json &data,
repertory::drive_mount_failed &value) {
data.at("function_name").get_to<std::string>(value.function_name);
data.at("mount_location").get_to<std::string>(value.mount_location);
data.at("status").get_to<NTSTATUS>(value.status);
}
};
NLOHMANN_JSON_NAMESPACE_END
#endif // defined(_WIN32)
#endif // REPERTORY_INCLUDE_EVENTS_TYPES_DRIVE_MOUNT_FAILED_HPP_

View File

@ -0,0 +1,75 @@
/*
Copyright <2018-2025> <scott.e.graves@protonmail.com>
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
*/
#ifndef REPERTORY_INCLUDE_EVENTS_TYPES_DRIVE_MOUNT_RESULT_HPP_
#define REPERTORY_INCLUDE_EVENTS_TYPES_DRIVE_MOUNT_RESULT_HPP_
#include "events/i_event.hpp"
#include "types/repertory.hpp"
namespace repertory {
struct drive_mount_result final : public i_event {
drive_mount_result() = default;
drive_mount_result(std::string_view function_name_,
std::string mount_location_, std::string result_)
: function_name(std::string(function_name_)),
mount_location(std::move(mount_location_)),
result(std::move(result_)) {}
static constexpr const std::string_view name{"drive_mount_result"};
std::string function_name;
std::string mount_location;
std::string result;
[[nodiscard]] auto get_event_level() const -> event_level override {
return event_level::info;
}
[[nodiscard]] auto get_name() const -> std::string_view override {
return name;
}
[[nodiscard]] auto get_single_line() const -> std::string override {
return fmt::format("{}|func|{}|location|{}|result|{}", name, function_name,
mount_location, result);
}
};
} // namespace repertory
NLOHMANN_JSON_NAMESPACE_BEGIN
template <> struct adl_serializer<repertory::drive_mount_result> {
static void to_json(json &data, const repertory::drive_mount_result &value) {
data["function_name"] = value.function_name;
data["mount_location"] = value.mount_location;
data["result"] = value.result;
}
static void from_json(const json &data,
repertory::drive_mount_result &value) {
data.at("function_name").get_to<std::string>(value.function_name);
data.at("mount_location").get_to<std::string>(value.mount_location);
data.at("result").get_to<std::string>(value.result);
}
};
NLOHMANN_JSON_NAMESPACE_END
#endif // REPERTORY_INCLUDE_EVENTS_TYPES_DRIVE_MOUNT_RESULT_HPP_

View File

@ -0,0 +1,69 @@
/*
Copyright <2018-2025> <scott.e.graves@protonmail.com>
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
*/
#ifndef REPERTORY_INCLUDE_EVENTS_TYPES_DRIVE_MOUNTED_HPP_
#define REPERTORY_INCLUDE_EVENTS_TYPES_DRIVE_MOUNTED_HPP_
#include "events/i_event.hpp"
#include "types/repertory.hpp"
namespace repertory {
struct drive_mounted final : public i_event {
drive_mounted() = default;
drive_mounted(std::string_view function_name_, std::string mount_location_)
: function_name(std::string(function_name_)),
mount_location(std::move(mount_location_)) {}
static constexpr const std::string_view name{"drive_mounted"};
std::string function_name;
std::string mount_location;
[[nodiscard]] auto get_event_level() const -> event_level override {
return event_level::info;
}
[[nodiscard]] auto get_name() const -> std::string_view override {
return name;
}
[[nodiscard]] auto get_single_line() const -> std::string override {
return fmt::format("{}|func|{}|location|{}", name, function_name,
mount_location);
}
};
} // namespace repertory
NLOHMANN_JSON_NAMESPACE_BEGIN
template <> struct adl_serializer<repertory::drive_mounted> {
static void to_json(json &data, const repertory::drive_mounted &value) {
data["function_name"] = value.function_name;
data["mount_location"] = value.mount_location;
}
static void from_json(const json &data, repertory::drive_mounted &value) {
data.at("function_name").get_to<std::string>(value.function_name);
data.at("mount_location").get_to<std::string>(value.mount_location);
}
};
NLOHMANN_JSON_NAMESPACE_END
#endif // REPERTORY_INCLUDE_EVENTS_TYPES_DRIVE_MOUNTED_HPP_

View File

@ -31,7 +31,10 @@
#include "events/consumers/console_consumer.hpp" #include "events/consumers/console_consumer.hpp"
#include "events/consumers/logging_consumer.hpp" #include "events/consumers/logging_consumer.hpp"
#include "events/event_system.hpp" #include "events/event_system.hpp"
#include "events/event_system2.hpp"
#include "events/events.hpp" #include "events/events.hpp"
#include "events/types/drive_mount_result.hpp"
#include "events/types/drive_mounted.hpp"
#include "platform/platform.hpp" #include "platform/platform.hpp"
#include "providers/i_provider.hpp" #include "providers/i_provider.hpp"
#include "rpc/server/full_server.hpp" #include "rpc/server/full_server.hpp"
@ -576,6 +579,7 @@ void *fuse_drive::init_impl(struct fuse_conn_info *conn) {
logging_consumer_ = std::make_unique<logging_consumer>( logging_consumer_ = std::make_unique<logging_consumer>(
config_.get_event_level(), config_.get_log_directory()); config_.get_event_level(), config_.get_log_directory());
event_system::instance().start(); event_system::instance().start();
event_system2::instance().start();
was_mounted_ = true; was_mounted_ = true;
fm_ = std::make_unique<file_manager>(config_, provider_); fm_ = std::make_unique<file_manager>(config_, provider_);
@ -611,7 +615,8 @@ void *fuse_drive::init_impl(struct fuse_conn_info *conn) {
utils::error::raise_error(function_name, "failed to set mount state"); utils::error::raise_error(function_name, "failed to set mount state");
} }
event_system::instance().raise<drive_mounted>(get_mount_location()); event_system2::instance().raise<drive_mounted>(function_name,
get_mount_location());
} catch (const std::exception &e) { } catch (const std::exception &e) {
utils::error::raise_error(function_name, e, "exception during fuse init"); utils::error::raise_error(function_name, e, "exception during fuse init");
@ -659,8 +664,10 @@ auto fuse_drive::mkdir_impl(std::string api_path, mode_t mode) -> api_error {
void fuse_drive::notify_fuse_main_exit(int &ret) { void fuse_drive::notify_fuse_main_exit(int &ret) {
if (was_mounted_) { if (was_mounted_) {
event_system::instance().raise<drive_mount_result>(std::to_string(ret)); event_system2::instance().raise<drive_mount_result>(
function_name, get_mount_location(), std::to_string(ret));
event_system::instance().stop(); event_system::instance().stop();
event_system2::instance().stop();
logging_consumer_.reset(); logging_consumer_.reset();
console_consumer_.reset(); console_consumer_.reset();
} }

View File

@ -28,7 +28,10 @@
#include "events/consumers/console_consumer.hpp" #include "events/consumers/console_consumer.hpp"
#include "events/consumers/logging_consumer.hpp" #include "events/consumers/logging_consumer.hpp"
#include "events/event_system.hpp" #include "events/event_system.hpp"
#include "events/event_system2.hpp"
#include "events/events.hpp" #include "events/events.hpp"
#include "events/types/drive_mount_result.hpp"
#include "events/types/drive_mounted.hpp"
#include "platform/platform.hpp" #include "platform/platform.hpp"
#include "rpc/server/server.hpp" #include "rpc/server/server.hpp"
#include "types/remote.hpp" #include "types/remote.hpp"
@ -40,8 +43,8 @@
#include "utils/utils.hpp" #include "utils/utils.hpp"
namespace repertory::remote_fuse { namespace repertory::remote_fuse {
auto remote_fuse_drive::access_impl(std::string api_path, auto remote_fuse_drive::access_impl(std::string api_path, int mask)
int mask) -> api_error { -> api_error {
return utils::to_api_error( return utils::to_api_error(
remote_instance_->fuse_access(api_path.c_str(), mask)); remote_instance_->fuse_access(api_path.c_str(), mask));
} }
@ -59,8 +62,8 @@ auto remote_fuse_drive::chmod_impl(std::string api_path, mode_t mode,
struct fuse_file_info * /*f_info*/) struct fuse_file_info * /*f_info*/)
-> api_error { -> api_error {
#else #else
auto remote_fuse_drive::chmod_impl(std::string api_path, auto remote_fuse_drive::chmod_impl(std::string api_path, mode_t mode)
mode_t mode) -> api_error { -> api_error {
#endif #endif
return utils::to_api_error(remote_instance_->fuse_chmod( return utils::to_api_error(remote_instance_->fuse_chmod(
api_path.c_str(), static_cast<remote::file_mode>(mode))); api_path.c_str(), static_cast<remote::file_mode>(mode)));
@ -71,8 +74,8 @@ auto remote_fuse_drive::chown_impl(std::string api_path, uid_t uid, gid_t gid,
struct fuse_file_info * /*f_info*/) struct fuse_file_info * /*f_info*/)
-> api_error { -> api_error {
#else #else
auto remote_fuse_drive::chown_impl(std::string api_path, uid_t uid, auto remote_fuse_drive::chown_impl(std::string api_path, uid_t uid, gid_t gid)
gid_t gid) -> api_error { -> api_error {
#endif #endif
return utils::to_api_error( return utils::to_api_error(
remote_instance_->fuse_chown(api_path.c_str(), uid, gid)); remote_instance_->fuse_chown(api_path.c_str(), uid, gid));
@ -116,9 +119,10 @@ void remote_fuse_drive::destroy_impl(void *ptr) {
fuse_base::destroy_impl(ptr); fuse_base::destroy_impl(ptr);
} }
auto remote_fuse_drive::fgetattr_impl( auto remote_fuse_drive::fgetattr_impl(std::string api_path,
std::string api_path, struct stat *unix_st, struct stat *unix_st,
struct fuse_file_info *f_info) -> api_error { struct fuse_file_info *f_info)
-> api_error {
remote::stat r_stat{}; remote::stat r_stat{};
auto directory = false; auto directory = false;
@ -179,8 +183,8 @@ auto remote_fuse_drive::getattr_impl(std::string api_path, struct stat *unix_st,
struct fuse_file_info * /*f_info*/) struct fuse_file_info * /*f_info*/)
-> api_error { -> api_error {
#else #else
auto remote_fuse_drive::getattr_impl(std::string api_path, auto remote_fuse_drive::getattr_impl(std::string api_path, struct stat *unix_st)
struct stat *unix_st) -> api_error { -> api_error {
#endif #endif
bool directory = false; bool directory = false;
remote::stat r_stat{}; remote::stat r_stat{};
@ -242,6 +246,7 @@ auto remote_fuse_drive::init_impl(struct fuse_conn_info *conn) -> void * {
logging_consumer_ = std::make_shared<logging_consumer>( logging_consumer_ = std::make_shared<logging_consumer>(
config_.get_event_level(), config_.get_log_directory()); config_.get_event_level(), config_.get_log_directory());
event_system::instance().start(); event_system::instance().start();
event_system2::instance().start();
if (not lock_data_.set_mount_state(true, get_mount_location(), getpid())) { if (not lock_data_.set_mount_state(true, get_mount_location(), getpid())) {
utils::error::raise_error(function_name, "failed to set mount state"); utils::error::raise_error(function_name, "failed to set mount state");
@ -257,22 +262,27 @@ auto remote_fuse_drive::init_impl(struct fuse_conn_info *conn) -> void * {
} else { } else {
server_ = std::make_shared<server>(config_); server_ = std::make_shared<server>(config_);
server_->start(); server_->start();
event_system::instance().raise<drive_mounted>(get_mount_location()); event_system2::instance().raise<drive_mounted>(function_name,
get_mount_location());
} }
return ret; return ret;
} }
auto remote_fuse_drive::mkdir_impl(std::string api_path, auto remote_fuse_drive::mkdir_impl(std::string api_path, mode_t mode)
mode_t mode) -> api_error { -> api_error {
return utils::to_api_error(remote_instance_->fuse_mkdir( return utils::to_api_error(remote_instance_->fuse_mkdir(
api_path.c_str(), static_cast<remote::file_mode>(mode))); api_path.c_str(), static_cast<remote::file_mode>(mode)));
} }
void remote_fuse_drive::notify_fuse_main_exit(int &ret) { void remote_fuse_drive::notify_fuse_main_exit(int &ret) {
REPERTORY_USES_FUNCTION_NAME();
if (was_mounted_) { if (was_mounted_) {
event_system::instance().raise<drive_mount_result>(std::to_string(ret)); event_system2::instance().raise<drive_mount_result>(
function_name, get_mount_location(), std::to_string(ret));
event_system::instance().stop(); event_system::instance().stop();
event_system2::instance().stop();
logging_consumer_.reset(); logging_consumer_.reset();
console_consumer_.reset(); console_consumer_.reset();
} }
@ -286,8 +296,9 @@ auto remote_fuse_drive::open_impl(std::string api_path,
f_info->fh)); f_info->fh));
} }
auto remote_fuse_drive::opendir_impl( auto remote_fuse_drive::opendir_impl(std::string api_path,
std::string api_path, struct fuse_file_info *f_info) -> api_error { struct fuse_file_info *f_info)
-> api_error {
if ((f_info->flags & O_APPEND) == O_APPEND || if ((f_info->flags & O_APPEND) == O_APPEND ||
(f_info->flags & O_EXCL) == O_EXCL) { (f_info->flags & O_EXCL) == O_EXCL) {
return api_error::directory_exists; return api_error::directory_exists;
@ -364,14 +375,18 @@ auto remote_fuse_drive::read_impl(std::string api_path, char *buffer,
} }
#if FUSE_USE_VERSION >= 30 #if FUSE_USE_VERSION >= 30
auto remote_fuse_drive::readdir_impl( auto remote_fuse_drive::readdir_impl(std::string api_path, void *buf,
std::string api_path, void *buf, fuse_fill_dir_t fuse_fill_dir, fuse_fill_dir_t fuse_fill_dir,
off_t offset, struct fuse_file_info *f_info, off_t offset,
fuse_readdir_flags /*flags*/) -> api_error { struct fuse_file_info *f_info,
fuse_readdir_flags /*flags*/)
-> api_error {
#else #else
auto remote_fuse_drive::readdir_impl( auto remote_fuse_drive::readdir_impl(std::string api_path, void *buf,
std::string api_path, void *buf, fuse_fill_dir_t fuse_fill_dir, fuse_fill_dir_t fuse_fill_dir,
off_t offset, struct fuse_file_info *f_info) -> api_error { off_t offset,
struct fuse_file_info *f_info)
-> api_error {
#endif #endif
std::string item_path; std::string item_path;
int res = 0; int res = 0;
@ -399,14 +414,16 @@ auto remote_fuse_drive::readdir_impl(
return utils::to_api_error(res); return utils::to_api_error(res);
} }
auto remote_fuse_drive::release_impl( auto remote_fuse_drive::release_impl(std::string api_path,
std::string api_path, struct fuse_file_info *f_info) -> api_error { struct fuse_file_info *f_info)
-> api_error {
return utils::to_api_error( return utils::to_api_error(
remote_instance_->fuse_release(api_path.c_str(), f_info->fh)); remote_instance_->fuse_release(api_path.c_str(), f_info->fh));
} }
auto remote_fuse_drive::releasedir_impl( auto remote_fuse_drive::releasedir_impl(std::string api_path,
std::string api_path, struct fuse_file_info *f_info) -> api_error { struct fuse_file_info *f_info)
-> api_error {
return utils::to_api_error( return utils::to_api_error(
remote_instance_->fuse_releasedir(api_path.c_str(), f_info->fh)); remote_instance_->fuse_releasedir(api_path.c_str(), f_info->fh));
} }
@ -503,8 +520,8 @@ api_error remote_fuse_drive::statfs_x_impl(std::string api_path,
return utils::to_api_error(res); return utils::to_api_error(res);
} }
#else // __APPLE__ #else // __APPLE__
auto remote_fuse_drive::statfs_impl(std::string api_path, auto remote_fuse_drive::statfs_impl(std::string api_path, struct statvfs *stbuf)
struct statvfs *stbuf) -> api_error { -> api_error {
auto res = statvfs(config_.get_data_directory().c_str(), stbuf); auto res = statvfs(config_.get_data_directory().c_str(), stbuf);
if (res == 0) { if (res == 0) {
remote::statfs r_stat{}; remote::statfs r_stat{};
@ -531,8 +548,8 @@ auto remote_fuse_drive::truncate_impl(std::string api_path, off_t size,
struct fuse_file_info * /*f_info*/) struct fuse_file_info * /*f_info*/)
-> api_error { -> api_error {
#else #else
auto remote_fuse_drive::truncate_impl(std::string api_path, auto remote_fuse_drive::truncate_impl(std::string api_path, off_t size)
off_t size) -> api_error { -> api_error {
#endif #endif
return utils::to_api_error(remote_instance_->fuse_truncate( return utils::to_api_error(remote_instance_->fuse_truncate(
api_path.c_str(), static_cast<remote::file_offset>(size))); api_path.c_str(), static_cast<remote::file_offset>(size)));
@ -543,9 +560,10 @@ auto remote_fuse_drive::unlink_impl(std::string api_path) -> api_error {
} }
#if FUSE_USE_VERSION >= 30 #if FUSE_USE_VERSION >= 30
auto remote_fuse_drive::utimens_impl( auto remote_fuse_drive::utimens_impl(std::string api_path,
std::string api_path, const struct timespec tv[2], const struct timespec tv[2],
struct fuse_file_info * /*f_info*/) -> api_error { struct fuse_file_info * /*f_info*/)
-> api_error {
#else #else
auto remote_fuse_drive::utimens_impl(std::string api_path, auto remote_fuse_drive::utimens_impl(std::string api_path,
const struct timespec tv[2]) -> api_error { const struct timespec tv[2]) -> api_error {

View File

@ -23,8 +23,9 @@
#include "app_config.hpp" #include "app_config.hpp"
#include "drives/winfsp/remotewinfsp/i_remote_instance.hpp" #include "drives/winfsp/remotewinfsp/i_remote_instance.hpp"
#include "events/event_system.hpp" #include "events/event_system2.hpp"
#include "events/events.hpp" #include "events/events.hpp"
#include "events/types/drive_mounted.hpp"
#include "types/repertory.hpp" #include "types/repertory.hpp"
#include "utils/path.hpp" #include "utils/path.hpp"
#include "version.hpp" #include "version.hpp"
@ -361,7 +362,7 @@ auto remote_client::winfsp_mounted(const std::wstring &location)
auto mount_location{ auto mount_location{
utils::string::to_utf8(location), utils::string::to_utf8(location),
}; };
event_system::instance().raise<drive_mounted>(mount_location); event_system2::instance().raise<drive_mounted>(function_name, mount_location);
RAISE_REMOTE_WINFSP_CLIENT_EVENT(function_name, mount_location, ret); RAISE_REMOTE_WINFSP_CLIENT_EVENT(function_name, mount_location, ret);
return ret; return ret;

View File

@ -26,7 +26,10 @@
#include "app_config.hpp" #include "app_config.hpp"
#include "events/consumers/console_consumer.hpp" #include "events/consumers/console_consumer.hpp"
#include "events/consumers/logging_consumer.hpp" #include "events/consumers/logging_consumer.hpp"
#include "events/event_system2.hpp"
#include "events/events.hpp" #include "events/events.hpp"
#include "events/types/drive_mount_failed.hpp"
#include "events/types/drive_mount_result.hpp"
#include "platform/platform.hpp" #include "platform/platform.hpp"
#include "rpc/server/server.hpp" #include "rpc/server/server.hpp"
#include "utils/collection.hpp" #include "utils/collection.hpp"
@ -74,8 +77,8 @@ auto remote_winfsp_drive::winfsp_service::OnStart(ULONG, PWSTR *) -> NTSTATUS {
} }
if (ret != STATUS_SUCCESS) { if (ret != STATUS_SUCCESS) {
event_system::instance().raise<drive_mount_failed>(mount_location, event_system2::instance().raise<drive_mount_failed>(
std::to_string(ret)); function_name, mount_location, std::to_string(ret));
if (not lock_.set_mount_state(false, "", -1)) { if (not lock_.set_mount_state(false, "", -1)) {
utils::error::raise_error(function_name, "failed to set mount state"); utils::error::raise_error(function_name, "failed to set mount state");
} }
@ -233,6 +236,8 @@ auto remote_winfsp_drive::Init(PVOID host) -> NTSTATUS {
auto remote_winfsp_drive::mount(const std::vector<std::string> &drive_args) auto remote_winfsp_drive::mount(const std::vector<std::string> &drive_args)
-> int { -> int {
REPERTORY_USES_FUNCTION_NAME();
std::vector<std::string> parsed_drive_args; std::vector<std::string> parsed_drive_args;
auto force_no_console = utils::collection::includes(drive_args, "-nc"); auto force_no_console = utils::collection::includes(drive_args, "-nc");
@ -254,9 +259,14 @@ auto remote_winfsp_drive::mount(const std::vector<std::string> &drive_args)
c = std::make_unique<console_consumer>(config_.get_event_level()); c = std::make_unique<console_consumer>(config_.get_event_level());
} }
event_system::instance().start(); event_system::instance().start();
event_system2::instance().start();
auto ret = winfsp_service(lock_, *this, parsed_drive_args, config_).Run(); auto ret = winfsp_service(lock_, *this, parsed_drive_args, config_).Run();
event_system::instance().raise<drive_mount_result>(std::to_string(ret));
event_system2::instance().raise<drive_mount_result>(function_name, "",
std::to_string(ret));
event_system::instance().stop(); event_system::instance().stop();
event_system2::instance().stop();
c.reset(); c.reset();
return static_cast<int>(ret); return static_cast<int>(ret);
} }

View File

@ -27,7 +27,11 @@
#include "drives/directory_iterator.hpp" #include "drives/directory_iterator.hpp"
#include "events/consumers/console_consumer.hpp" #include "events/consumers/console_consumer.hpp"
#include "events/consumers/logging_consumer.hpp" #include "events/consumers/logging_consumer.hpp"
#include "events/event_system2.hpp"
#include "events/events.hpp" #include "events/events.hpp"
#include "events/types/drive_mount_failed.hpp"
#include "events/types/drive_mount_result.hpp"
#include "events/types/drive_mounted.hpp"
#include "platform/platform.hpp" #include "platform/platform.hpp"
#include "providers/i_provider.hpp" #include "providers/i_provider.hpp"
#include "types/repertory.hpp" #include "types/repertory.hpp"
@ -131,8 +135,8 @@ auto winfsp_drive::winfsp_service::OnStart(ULONG /*Argc*/, PWSTR * /*Argv*/)
utils::error::raise_error(function_name, ret, "failed to set mount state"); utils::error::raise_error(function_name, ret, "failed to set mount state");
} }
event_system::instance().raise<drive_mount_failed>(mount_location, event_system2::instance().raise<drive_mount_failed>(function_name,
std::to_string(ret)); mount_location, ret);
return ret; return ret;
} }
@ -619,12 +623,17 @@ auto winfsp_drive::mount(const std::vector<std::string> &drive_args) -> int {
if (enable_console) { if (enable_console) {
cons = std::make_unique<console_consumer>(config_.get_event_level()); cons = std::make_unique<console_consumer>(config_.get_event_level());
} }
event_system::instance().start(); event_system::instance().start();
event_system2::instance().start();
auto svc = winfsp_service(lock_, *this, parsed_drive_args, config_); auto svc = winfsp_service(lock_, *this, parsed_drive_args, config_);
auto ret = svc.Run(); auto ret = svc.Run();
event_system::instance().raise<drive_mount_result>(std::to_string(ret)); event_system2::instance().raise<drive_mount_result>(function_name, "",
std::to_string(ret));
event_system::instance().stop(); event_system::instance().stop();
event_system2::instance().stop();
cons.reset(); cons.reset();
return static_cast<int>(ret); return static_cast<int>(ret);
@ -676,7 +685,8 @@ auto winfsp_drive::Mounted(PVOID host) -> NTSTATUS {
utils::error::raise_error(function_name, "failed to set mount state"); utils::error::raise_error(function_name, "failed to set mount state");
} }
event_system::instance().raise<drive_mounted>(mount_location); event_system2::instance().raise<drive_mounted>(function_name,
mount_location);
return STATUS_SUCCESS; return STATUS_SUCCESS;
} catch (const std::exception &e) { } catch (const std::exception &e) {
utils::error::raise_error(function_name, e, "exception occurred"); utils::error::raise_error(function_name, e, "exception occurred");

View File

@ -0,0 +1,166 @@
/*
Copyright <2018-2025> <scott.e.graves@protonmail.com>
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
*/
#include "events/event_system2.hpp"
#include "app_config.hpp"
#include "events/i_event.hpp"
#include "utils/collection.hpp"
namespace repertory {
void event_system2::attach(event_consumer *consumer) {
recur_mutex_lock lock(consumer_mutex_);
event_consumers_[""].push_back(consumer);
}
void event_system2::attach(std::string_view event_name,
event_consumer *consumer) {
recur_mutex_lock lock(consumer_mutex_);
event_consumers_[std::string{event_name}].push_back(consumer);
}
[[nodiscard]] auto event_system2::get_stop_requested() const -> bool {
return stop_requested_ || app_config::get_stop_requested();
}
void event_system2::process_events() {
std::vector<std::shared_ptr<i_event>> events;
unique_mutex_lock lock(event_mutex_);
const auto lock_and_notify = [this, &lock]() {
lock.lock();
event_notify_.notify_all();
lock.unlock();
};
if (not get_stop_requested() && event_list_.empty()) {
event_notify_.wait_for(lock, queue_wait_secs);
}
if (not event_list_.empty()) {
events.insert(events.end(), event_list_.begin(), event_list_.end());
event_list_.clear();
}
lock.unlock();
if (events.empty()) {
lock_and_notify();
return;
}
const auto notify_events = [this](std::string_view name,
const i_event &event) {
std::deque<std::future<void>> futures;
recur_mutex_lock consumer_lock(consumer_mutex_);
for (auto *consumer : event_consumers_[std::string{name}]) {
futures.emplace_back(std::async(std::launch::async, [consumer, &event]() {
consumer->notify_event(event);
}));
}
while (not futures.empty()) {
futures.front().get();
futures.pop_front();
}
};
for (const auto &evt : events) {
notify_events("", *evt.get());
notify_events(evt->get_name(), *evt.get());
}
lock_and_notify();
}
void event_system2::queue_event(std::shared_ptr<i_event> evt) {
unique_mutex_lock lock(event_mutex_);
event_list_.push_back(std::move(evt));
auto size = event_list_.size();
event_notify_.notify_all();
lock.unlock();
for (std::uint8_t retry{0U};
size > max_queue_size && retry < max_queue_retry &&
not get_stop_requested();
++retry) {
lock.lock();
size = event_list_.size();
if (size > max_queue_size) {
event_notify_.wait_for(lock, queue_wait_secs);
size = event_list_.size();
}
event_notify_.notify_all();
lock.unlock();
}
}
void event_system2::release(event_consumer *consumer) {
recur_mutex_lock lock(consumer_mutex_);
auto iter =
std::ranges::find_if(event_consumers_, [&](const auto &item) -> bool {
return utils::collection::includes(item.second, consumer);
});
if (iter != event_consumers_.end()) {
utils::collection::remove_element((*iter).second, consumer);
}
}
void event_system2::start() {
mutex_lock lock(run_mutex_);
if (event_thread_) {
event_notify_.notify_all();
return;
}
stop_requested_ = false;
event_thread_ = std::make_unique<std::thread>([this]() {
while (not get_stop_requested()) {
process_events();
}
});
event_notify_.notify_all();
}
void event_system2::stop() {
unique_mutex_lock lock(run_mutex_);
if (not event_thread_) {
event_notify_.notify_all();
return;
}
stop_requested_ = true;
std::unique_ptr<std::thread> thread{nullptr};
std::swap(thread, event_thread_);
event_notify_.notify_all();
lock.unlock();
thread->join();
thread.reset();
process_events();
}
} // namespace repertory

View File

@ -24,7 +24,11 @@
#include "app_config.hpp" #include "app_config.hpp"
#include "db/meta_db.hpp" #include "db/meta_db.hpp"
#include "events/event_system.hpp" #include "events/event_system.hpp"
#include "events/event_system2.hpp"
#include "events/events.hpp" #include "events/events.hpp"
#include "events/types/directory_remove_failed.hpp"
#include "events/types/directory_removed.hpp"
#include "events/types/directory_removed_externally.hpp"
#include "file_manager/cache_size_mgr.hpp" #include "file_manager/cache_size_mgr.hpp"
#include "file_manager/i_file_manager.hpp" #include "file_manager/i_file_manager.hpp"
#include "platform/platform.hpp" #include "platform/platform.hpp"
@ -34,6 +38,7 @@
#include "utils/polling.hpp" #include "utils/polling.hpp"
#include "utils/tasks.hpp" #include "utils/tasks.hpp"
#include "utils/time.hpp" #include "utils/time.hpp"
#include <utils/config.hpp>
namespace repertory { namespace repertory {
void base_provider::add_all_items(stop_type &stop_requested) { void base_provider::add_all_items(stop_type &stop_requested) {
@ -442,6 +447,8 @@ auto base_provider::is_file_writeable(const std::string &api_path) const
void base_provider::process_removed_directories( void base_provider::process_removed_directories(
std::deque<removed_item> removed_list, stop_type &stop_requested) { std::deque<removed_item> removed_list, stop_type &stop_requested) {
REPERTORY_USES_FUNCTION_NAME();
const auto get_stop_requested = [&stop_requested]() -> bool { const auto get_stop_requested = [&stop_requested]() -> bool {
return stop_requested || app_config::get_stop_requested(); return stop_requested || app_config::get_stop_requested();
}; };
@ -456,8 +463,8 @@ void base_provider::process_removed_directories(
} }
db3_->remove_api_path(item.api_path); db3_->remove_api_path(item.api_path);
event_system::instance().raise<directory_removed_externally>( event_system2::instance().raise<directory_removed_externally>(
item.api_path, item.source_path); item.api_path, function_name, item.source_path);
} }
} }
@ -655,12 +662,15 @@ auto base_provider::remove_file(const std::string &api_path) -> api_error {
} }
auto base_provider::remove_directory(const std::string &api_path) -> api_error { auto base_provider::remove_directory(const std::string &api_path) -> api_error {
REPERTORY_USES_FUNCTION_NAME();
const auto notify_end = [&api_path](api_error error) -> api_error { const auto notify_end = [&api_path](api_error error) -> api_error {
if (error == api_error::success) { if (error == api_error::success) {
event_system::instance().raise<directory_removed>(api_path); event_system2::instance().raise<directory_removed>(api_path,
function_name);
} else { } else {
event_system::instance().raise<directory_remove_failed>( event_system2::instance().raise<directory_remove_failed>(api_path, error,
api_path, api_error_to_string(error)); function_name);
} }
return error; return error;
}; };

View File

@ -23,7 +23,9 @@
#include "db/file_db.hpp" #include "db/file_db.hpp"
#include "events/event_system.hpp" #include "events/event_system.hpp"
#include "events/event_system2.hpp"
#include "events/events.hpp" #include "events/events.hpp"
#include "events/types/directory_removed_externally.hpp"
#include "types/repertory.hpp" #include "types/repertory.hpp"
#include "types/startup_exception.hpp" #include "types/startup_exception.hpp"
#include "utils/collection.hpp" #include "utils/collection.hpp"
@ -849,8 +851,8 @@ void encrypt_provider::remove_deleted_files(stop_type &stop_requested) {
} }
if (item.directory) { if (item.directory) {
event_system::instance().raise<directory_removed_externally>( event_system2::instance().raise<directory_removed_externally>(
item.api_path, item.source_path); item.api_path, function_name, item.source_path);
continue; continue;
} }

View File

@ -57,7 +57,7 @@ auto create_rocksdb(
auto db_dir = utils::path::combine(cfg.get_data_directory(), {"db"}); auto db_dir = utils::path::combine(cfg.get_data_directory(), {"db"});
if (not utils::file::directory{db_dir}.create_directory()) { if (not utils::file::directory{db_dir}.create_directory()) {
throw startup_exception( throw startup_exception(
fmt::format("failed to create db directory|", db_dir)); fmt::format("failed to create db directory|{}", db_dir));
} }
auto path = utils::path::combine(db_dir, {name}); auto path = utils::path::combine(db_dir, {name});
@ -76,8 +76,8 @@ auto create_rocksdb(
auto status = rocksdb::TransactionDB::Open( auto status = rocksdb::TransactionDB::Open(
options, rocksdb::TransactionDBOptions{}, path, families, &handles, &ptr); options, rocksdb::TransactionDBOptions{}, path, families, &handles, &ptr);
if (not status.ok()) { if (not status.ok()) {
throw startup_exception(fmt::format("failed to open rocksdb|path{}|error{}", throw startup_exception(fmt::format(
path, status.ToString())); "failed to open rocksdb|path|{}|error{}", path, status.ToString()));
} }
return std::unique_ptr<rocksdb::TransactionDB>(ptr); return std::unique_ptr<rocksdb::TransactionDB>(ptr);

View File

@ -42,6 +42,8 @@ protected:
static std::uint64_t idx{}; static std::uint64_t idx{};
event_system::instance().start(); event_system::instance().start();
event_system2::instance().start();
auto cfg_directory = utils::path::combine(test::get_test_output_dir(), auto cfg_directory = utils::path::combine(test::get_test_output_dir(),
{ {
"file_db_test", "file_db_test",
@ -55,6 +57,7 @@ protected:
file_db.reset(); file_db.reset();
config.reset(); config.reset();
event_system::instance().stop(); event_system::instance().stop();
event_system2::instance().stop();
} }
}; };

View File

@ -42,6 +42,8 @@ protected:
static std::uint64_t idx{}; static std::uint64_t idx{};
event_system::instance().start(); event_system::instance().start();
event_system2::instance().start();
auto cfg_directory = utils::path::combine(test::get_test_output_dir(), auto cfg_directory = utils::path::combine(test::get_test_output_dir(),
{ {
"file_mgr_db_test", "file_mgr_db_test",
@ -55,6 +57,7 @@ protected:
file_mgr_db.reset(); file_mgr_db.reset();
config.reset(); config.reset();
event_system::instance().stop(); event_system::instance().stop();
event_system2::instance().stop();
} }
}; };

View File

@ -42,6 +42,8 @@ protected:
static std::uint64_t idx{}; static std::uint64_t idx{};
event_system::instance().start(); event_system::instance().start();
event_system2::instance().start();
auto cfg_directory = utils::path::combine(test::get_test_output_dir(), auto cfg_directory = utils::path::combine(test::get_test_output_dir(),
{ {
"meta_db_test", "meta_db_test",
@ -55,6 +57,7 @@ protected:
meta_db.reset(); meta_db.reset();
config.reset(); config.reset();
event_system::instance().stop(); event_system::instance().stop();
event_system2::instance().stop();
} }
}; };

View File

@ -28,6 +28,7 @@ REPERTORY_IGNORE_WARNINGS_DISABLE()
#include "events/consumers/console_consumer.hpp" #include "events/consumers/console_consumer.hpp"
#include "events/event_system.hpp" #include "events/event_system.hpp"
#include "events/event_system2.hpp"
#include "events/events.hpp" #include "events/events.hpp"
#endif // REPERTORY_TEST_INCLUDE_TEST_COMMON_HPP_ #endif // REPERTORY_TEST_INCLUDE_TEST_COMMON_HPP_

View File

@ -52,9 +52,13 @@ public:
std::to_string(++idx), std::to_string(++idx),
}); });
event_system::instance().start(); event_system::instance().start();
event_system2::instance().start();
} }
void TearDown() override { event_system::instance().stop(); } void TearDown() override {
event_system::instance().stop();
event_system2::instance().stop();
}
}; };
std::atomic<std::uint64_t> config_test::idx{0U}; std::atomic<std::uint64_t> config_test::idx{0U};

View File

@ -35,9 +35,15 @@ public:
mock_provider provider; mock_provider provider;
protected: protected:
void SetUp() override { event_system::instance().start(); } void SetUp() override {
event_system::instance().start();
event_system2::instance().start();
}
void TearDown() override { event_system::instance().stop(); } void TearDown() override {
event_system::instance().stop();
event_system2::instance().stop();
}
}; };
TEST_F(direct_open_file_test, read_full_file) { TEST_F(direct_open_file_test, read_full_file) {

View File

@ -61,6 +61,7 @@ public:
protected: protected:
void SetUp() override { void SetUp() override {
event_system::instance().start(); event_system::instance().start();
event_system2::instance().start();
file_manager_dir = repertory::utils::path::combine( file_manager_dir = repertory::utils::path::combine(
repertory::test::get_test_output_dir(), repertory::test::get_test_output_dir(),
@ -72,7 +73,10 @@ protected:
cache_size_mgr::instance().initialize(cfg.get()); cache_size_mgr::instance().initialize(cfg.get());
} }
void TearDown() override { event_system::instance().stop(); } void TearDown() override {
event_system::instance().stop();
event_system2::instance().stop();
}
}; };
std::atomic<std::size_t> file_manager_test::inst{0U}; std::atomic<std::size_t> file_manager_test::inst{0U};

View File

@ -46,6 +46,7 @@ public:
protected: protected:
void SetUp() override { void SetUp() override {
event_system::instance().start(); event_system::instance().start();
event_system2::instance().start();
auto open_file_dir = repertory::utils::path::combine( auto open_file_dir = repertory::utils::path::combine(
repertory::test::get_test_output_dir(), repertory::test::get_test_output_dir(),
@ -56,7 +57,10 @@ protected:
cache_size_mgr::instance().initialize(cfg.get()); cache_size_mgr::instance().initialize(cfg.get());
} }
void TearDown() override { event_system::instance().stop(); } void TearDown() override {
event_system::instance().stop();
event_system2::instance().stop();
}
}; };
std::atomic<std::size_t> open_file_test::inst{0U}; std::atomic<std::size_t> open_file_test::inst{0U};
@ -590,6 +594,7 @@ TEST_F(open_file_test, resize_file_by_full_chunk) {
TEST_F(open_file_test, can_add_handle) { TEST_F(open_file_test, can_add_handle) {
event_system::instance().start(); event_system::instance().start();
event_system2::instance().start();
console_consumer c; console_consumer c;
const auto source_path = const auto source_path =
test::generate_test_file_name("file_manager_open_file_test"); test::generate_test_file_name("file_manager_open_file_test");
@ -644,12 +649,15 @@ TEST_F(open_file_test, can_add_handle) {
capture.wait_for_empty(); capture.wait_for_empty();
event_system::instance().stop(); event_system::instance().stop();
event_system2::instance().stop();
} }
TEST_F(open_file_test, can_remove_handle) { TEST_F(open_file_test, can_remove_handle) {
event_system::instance().start();
console_consumer c; console_consumer c;
event_system::instance().start();
event_system2::instance().start();
const auto source_path = const auto source_path =
test::generate_test_file_name("file_manager_open_file_test"); test::generate_test_file_name("file_manager_open_file_test");
@ -706,6 +714,7 @@ TEST_F(open_file_test, can_remove_handle) {
capture.wait_for_empty(); capture.wait_for_empty();
event_system::instance().stop(); event_system::instance().stop();
event_system2::instance().stop();
} }
TEST_F(open_file_test, TEST_F(open_file_test,

View File

@ -635,6 +635,8 @@ TEST(providers, encrypt_provider) {
console_consumer consumer{}; console_consumer consumer{};
event_system::instance().start(); event_system::instance().start();
event_system2::instance().start();
{ {
app_config cfg(provider_type::encrypt, config_path); app_config cfg(provider_type::encrypt, config_path);
@ -668,7 +670,9 @@ TEST(providers, encrypt_provider) {
provider.stop(); provider.stop();
mgr.stop(); mgr.stop();
} }
event_system::instance().stop(); event_system::instance().stop();
event_system2::instance().stop();
} }
TEST(providers, s3_provider) { TEST(providers, s3_provider) {
@ -677,6 +681,8 @@ TEST(providers, s3_provider) {
console_consumer consumer{}; console_consumer consumer{};
event_system::instance().start(); event_system::instance().start();
event_system2::instance().start();
{ {
app_config cfg(provider_type::s3, config_path); app_config cfg(provider_type::s3, config_path);
{ {
@ -706,7 +712,9 @@ TEST(providers, s3_provider) {
provider.stop(); provider.stop();
mgr.stop(); mgr.stop();
} }
event_system::instance().stop(); event_system::instance().stop();
event_system2::instance().stop();
} }
TEST(providers, sia_provider) { TEST(providers, sia_provider) {
@ -715,6 +723,8 @@ TEST(providers, sia_provider) {
console_consumer consumer{}; console_consumer consumer{};
event_system::instance().start(); event_system::instance().start();
event_system2::instance().start();
{ {
app_config cfg(provider_type::sia, config_path); app_config cfg(provider_type::sia, config_path);
{ {
@ -744,7 +754,9 @@ TEST(providers, sia_provider) {
provider.stop(); provider.stop();
mgr.stop(); mgr.stop();
} }
event_system::instance().stop(); event_system::instance().stop();
event_system2::instance().stop();
} }
} // namespace repertory } // namespace repertory

View File

@ -45,9 +45,15 @@ public:
mock_provider provider; mock_provider provider;
protected: protected:
void SetUp() override { event_system::instance().start(); } void SetUp() override {
event_system::instance().start();
event_system2::instance().start();
}
void TearDown() override { event_system::instance().stop(); } void TearDown() override {
event_system::instance().stop();
event_system2::instance().stop();
}
}; };
TEST_F(ring_buffer_open_file_test, can_forward_to_last_chunk) { TEST_F(ring_buffer_open_file_test, can_forward_to_last_chunk) {

View File

@ -32,6 +32,7 @@ TEST(upload, can_upload_a_valid_file) {
console_consumer con; console_consumer con;
event_system::instance().start(); event_system::instance().start();
event_system2::instance().start();
const auto source_path = test::generate_test_file_name("upload_test"); const auto source_path = test::generate_test_file_name("upload_test");
@ -69,12 +70,14 @@ TEST(upload, can_upload_a_valid_file) {
EXPECT_FALSE(upload.is_cancelled()); EXPECT_FALSE(upload.is_cancelled());
event_system::instance().stop(); event_system::instance().stop();
event_system2::instance().stop();
} }
TEST(upload, can_cancel_upload) { TEST(upload, can_cancel_upload) {
console_consumer con; console_consumer con;
event_system::instance().start(); event_system::instance().start();
event_system2::instance().start();
const auto source_path = test::generate_test_file_name("upload_test"); const auto source_path = test::generate_test_file_name("upload_test");
@ -135,12 +138,14 @@ TEST(upload, can_cancel_upload) {
EXPECT_TRUE(upload.is_cancelled()); EXPECT_TRUE(upload.is_cancelled());
event_system::instance().stop(); event_system::instance().stop();
event_system2::instance().stop();
} }
TEST(upload, can_stop_upload) { TEST(upload, can_stop_upload) {
console_consumer con; console_consumer con;
event_system::instance().start(); event_system::instance().start();
event_system2::instance().start();
const auto source_path = test::generate_test_file_name("upload_test"); const auto source_path = test::generate_test_file_name("upload_test");
@ -173,10 +178,13 @@ TEST(upload, can_stop_upload) {
event_capture evt_cap({"file_upload_completed"}); event_capture evt_cap({"file_upload_completed"});
{ upload upload(fsi, mock_provider); } {
upload upload(fsi, mock_provider);
}
evt_cap.wait_for_empty(); evt_cap.wait_for_empty();
event_system::instance().stop(); event_system::instance().stop();
event_system2::instance().stop();
} }
} // namespace repertory } // namespace repertory