diff --git a/include/limestone/api/limestone_exception.h b/include/limestone/api/limestone_exception.h index 221b68ce..3dc2b92a 100644 --- a/include/limestone/api/limestone_exception.h +++ b/include/limestone/api/limestone_exception.h @@ -22,6 +22,7 @@ #include #include + namespace limestone::api { class limestone_exception : public std::runtime_error { @@ -32,7 +33,7 @@ class limestone_exception : public std::runtime_error { explicit limestone_exception(const std::string& message, int error_code) : std::runtime_error(message), error_code_(error_code) {} - int error_code() const noexcept { return error_code_; } + [[nodiscard]] int error_code() const noexcept { return error_code_; } private: int error_code_{0}; @@ -54,26 +55,4 @@ class limestone_io_exception : public limestone_exception { } }; -// Macro to throw exceptions with file and line information - -#define THROW_LIMESTONE_EXCEPTION(message) \ - throw limestone_exception(std::string(message) + " (at " + std::filesystem::path(__FILE__).filename().string() + ":" + std::to_string(__LINE__) + ")") - -#define THROW_LIMESTONE_IO_EXCEPTION(message, error_code) \ - throw limestone_io_exception(std::string(message) + " (at " + std::filesystem::path(__FILE__).filename().string() + ":" + std::to_string(__LINE__) + ")", error_code) - -#define LOG_AND_THROW_EXCEPTION(message) \ - { \ - LOG_LP(ERROR) << message; \ - THROW_LIMESTONE_EXCEPTION(message); \ - } - -#define LOG_AND_THROW_IO_EXCEPTION(message, error_code) \ - { \ - std::string full_message = limestone_io_exception::format_message(message, error_code); \ - LOG_LP(ERROR) << full_message; \ - THROW_LIMESTONE_IO_EXCEPTION(message, error_code); \ - } - - } // namespace limestone::api diff --git a/src/limestone/compaction_catalog.cpp b/src/limestone/compaction_catalog.cpp index 58f0f261..0a8fdc77 100644 --- a/src/limestone/compaction_catalog.cpp +++ b/src/limestone/compaction_catalog.cpp @@ -27,7 +27,7 @@ #include "compaction_catalog.h" #include "logging_helper.h" #include "limestone/api/epoch_id_type.h" -#include "limestone/api/limestone_exception.h" +#include "limestone_exception_helper.h" namespace limestone::internal { diff --git a/src/limestone/compaction_catalog.h b/src/limestone/compaction_catalog.h index ab0383fd..2c421896 100644 --- a/src/limestone/compaction_catalog.h +++ b/src/limestone/compaction_catalog.h @@ -223,8 +223,8 @@ class compaction_catalog { // needed for database startup or recovery, and can be safely deleted. boost::filesystem::path backup_file_path_; - // Helper methods protected: + // Helper methods void load(); void restore_from_backup(); void load_catalog_file(const boost::filesystem::path &directory_path); @@ -232,7 +232,6 @@ class compaction_catalog { [[nodiscard]] std::string create_catalog_content() const; // for only testing -protected: void set_file_operations(std::unique_ptr file_ops); void reset_file_operations(); }; diff --git a/src/limestone/file_operations.h b/src/limestone/file_operations.h index 6cb5687c..74e03856 100644 --- a/src/limestone/file_operations.h +++ b/src/limestone/file_operations.h @@ -22,25 +22,27 @@ namespace limestone::internal { /** - * @brief Interface and implementation for file operations abstraction. + * @brief Abstract interface for mocking file operations in test environments. * - * This header defines the abstract interface `file_operations` for handling file - * operations such as opening, writing, flushing, closing, and syncing files. - * It also provides a concrete class `real_file_operations`, which uses the C standard - * library functions (e.g., fopen, fwrite, fflush, fclose, and fsync) to perform - * actual file operations. + * This interface abstracts file operations to simulate file handling through mocking + * in test environments. It provides unified methods for handling both C-style file + * operations (e.g., fopen, fwrite, fflush) and C++-style file operations + * (e.g., std::ifstream). * - * The purpose of this abstraction is to enable dependency injection for file operations, - * allowing easier testing and mocking in various parts of the system. - * For instance, in tests, a mock implementation of this interface can be used to simulate - * file operations without actually interacting with the file system. + * Implementing classes like `real_file_operations` use the C standard library and + * C++ iostreams to perform actual file operations. * - * Note: This file is intended to be used in multiple parts of the project, and it - * should be placed alongside other source files for consistency. + * It also supports Boost filesystem operations, allowing for the mocking of + * cross-platform file system paths and error code handling. */ class file_operations { public: virtual ~file_operations() = default; + file_operations() = default; + file_operations(const file_operations&) = delete; + file_operations& operator=(const file_operations&) = delete; + file_operations(file_operations&&) = delete; + file_operations& operator=(file_operations&&) = delete; // ----------------------------------------- // C-style file operations diff --git a/src/limestone/limestone_exception_helper.h b/src/limestone/limestone_exception_helper.h new file mode 100644 index 00000000..de7d896e --- /dev/null +++ b/src/limestone/limestone_exception_helper.h @@ -0,0 +1,61 @@ +/* + * Copyright 2022-2024 Project Tsurugi. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include +#include "logging_helper.h" + +#include + +#pragma once + +namespace limestone { + +using limestone::api::limestone_exception; +using limestone::api::limestone_io_exception; + +inline void throw_limestone_exception(const std::string& message, const char* file, int line) { + throw limestone_exception(message + " (at " + std::filesystem::path(file).filename().string() + ":" + std::to_string(line) + ")"); +} + +inline void throw_limestone_io_exception(const std::string& message, int error_code, const char* file, int line) { + throw limestone_io_exception(message + " (at " + std::filesystem::path(file).filename().string() + ":" + std::to_string(line) + ")", error_code); +} + +inline void log_and_throw_exception(const std::string& message, const char* file, int line) { + LOG_LP(ERROR) << message; + throw_limestone_exception(message, file, line); +} + +inline void log_and_throw_io_exception(const std::string& message, int error_code, const char* file, int line) { + std::string full_message = limestone_io_exception::format_message(message, error_code); + LOG_LP(ERROR) << full_message; + throw_limestone_io_exception(message, error_code, file, line); +} + +// NOLINTNEXTLINE +#define THROW_LIMESTONE_EXCEPTION(message) throw_limestone_exception(message, __FILE__, __LINE__) + +// NOLINTNEXTLINE +#define THROW_LIMESTONE_IO_EXCEPTION(message, error_code) throw_limestone_io_exception(message, error_code, __FILE__, __LINE__) + +// NOLINTNEXTLINE +#define LOG_AND_THROW_EXCEPTION(message) log_and_throw_exception(message, __FILE__, __LINE__) + +// NOLINTNEXTLINE +#define LOG_AND_THROW_IO_EXCEPTION(message, error_code) log_and_throw_io_exception(message, error_code, __FILE__, __LINE__) + +} // namespace limestone \ No newline at end of file