Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

core: Add C++ classes for read-only memory-mapped files and UNIX file descriptors; Remove Zstandard's dependency on Boost. #445

Merged
merged 9 commits into from
Jun 17, 2024
5 changes: 5 additions & 0 deletions components/core/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -324,6 +324,8 @@ set(SOURCE_FILES_unitTest
src/clp/ffi/search/Subquery.hpp
src/clp/ffi/search/WildcardToken.cpp
src/clp/ffi/search/WildcardToken.hpp
src/clp/FileDescriptor.cpp
src/clp/FileDescriptor.hpp
src/clp/FileReader.cpp
src/clp/FileReader.hpp
src/clp/FileWriter.cpp
Expand Down Expand Up @@ -361,6 +363,8 @@ set(SOURCE_FILES_unitTest
src/clp/LogTypeDictionaryWriter.cpp
src/clp/LogTypeDictionaryWriter.hpp
src/clp/math_utils.hpp
src/clp/MemoryMappedFileView.cpp
src/clp/MemoryMappedFileView.hpp
src/clp/MessageParser.cpp
src/clp/MessageParser.hpp
src/clp/MySQLDB.cpp
Expand Down Expand Up @@ -456,6 +460,7 @@ set(SOURCE_FILES_unitTest
tests/test-kql.cpp
tests/test-main.cpp
tests/test-math_utils.cpp
tests/test-MemoryMappedFile.cpp
tests/test-NetworkReader.cpp
tests/test-ParserWithUserSchema.cpp
tests/test-query_methods.cpp
Expand Down
55 changes: 55 additions & 0 deletions components/core/src/clp/FileDescriptor.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
#include "FileDescriptor.hpp"

#include <fcntl.h>
#include <sys/stat.h>
#include <unistd.h>

#include <cerrno>
#include <cstddef>
#include <string_view>

#include "ErrorCode.hpp"
#include "type_utils.hpp"

namespace clp {
FileDescriptor::FileDescriptor(
std::string_view path,
Mode mode,
CloseFailureCallback close_failure_callback
)
: m_fd{open(path.data(), enum_to_underlying_type(mode))},
kirkrodrigues marked this conversation as resolved.
Show resolved Hide resolved
m_mode{mode},
m_close_failure_callback{close_failure_callback} {
if (-1 == m_fd) {
throw OperationFailed(
ErrorCode_errno,
__FILE__,
__LINE__,
"Failed to open file descriptor in path: " + std::string{path}
LinZhihao-723 marked this conversation as resolved.
Show resolved Hide resolved
);
}
}

FileDescriptor::~FileDescriptor() {
if (-1 == m_fd) {
return;
}
if (0 != close(m_fd) && nullptr != m_close_failure_callback) {
m_close_failure_callback(errno);
}
}

auto FileDescriptor::get_size() const -> size_t {
struct stat stat_result {};

if (0 != fstat(m_fd, &stat_result)) {
throw OperationFailed(
ErrorCode_errno,
__FILE__,
__LINE__,
"Failed to stat file using file descriptor."
);
}
return static_cast<size_t>(stat_result.st_size);
}
} // namespace clp
98 changes: 98 additions & 0 deletions components/core/src/clp/FileDescriptor.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,98 @@
#ifndef CLP_FILEDESCRIPTOR_HPP
#define CLP_FILEDESCRIPTOR_HPP

#include <fcntl.h>

#include <cstddef>
#include <string>
#include <string_view>
#include <utility>

#include "ErrorCode.hpp"
#include "TraceableException.hpp"

namespace clp {
/**
* A class to wrap C style file descriptor.
LinZhihao-723 marked this conversation as resolved.
Show resolved Hide resolved
*/
class FileDescriptor {
public:
// Types
/**
* `close` is called in the destructor to close the file descriptor. However, `close` may return
* an error indicated by `errno`. This type alias defines a callback to handle the `close`
* failure in the destructor.
* The signature of the callback: void close_failure_callback(int errno)
*/
using CloseFailureCallback = void (*)(int);

class OperationFailed : public TraceableException {
public:
OperationFailed(
ErrorCode error_code,
char const* const filename,
int line_number,
std::string msg
)
: TraceableException{error_code, filename, line_number},
m_msg{std::move(msg)} {}

[[nodiscard]] auto what() const noexcept -> char const* override { return m_msg.c_str(); }

private:
std::string m_msg;
};

/**
* A C++ wrapper for Unix oflag that describes the operation mode.
*/
// NOLINTNEXTLINE(performance-enum-size)
enum class Mode : int {
LinZhihao-723 marked this conversation as resolved.
Show resolved Hide resolved
ReadOnly = O_RDONLY,
CreateForWrite = O_WRONLY | O_CREAT | O_TRUNC,
LinZhihao-723 marked this conversation as resolved.
Show resolved Hide resolved
};

// Constructors
/**
* @param path
* @param mode
* @param close_failure_callback
*/
LinZhihao-723 marked this conversation as resolved.
Show resolved Hide resolved
FileDescriptor(
std::string_view path,
Mode mode,
LinZhihao-723 marked this conversation as resolved.
Show resolved Hide resolved
CloseFailureCallback close_failure_callback = nullptr
);

// Destructor
~FileDescriptor();

// Disable copy/move constructors/assignment operators
FileDescriptor(FileDescriptor const&) = delete;
FileDescriptor(FileDescriptor&&) = delete;
auto operator=(FileDescriptor const&) -> FileDescriptor& = delete;
auto operator=(FileDescriptor&&) -> FileDescriptor& = delete;

/**
* @return The raw fd.
*/
[[nodiscard]] auto get_raw_fd() const -> int { return m_fd; }

/**
* @return The size of the file.
*/
[[nodiscard]] auto get_size() const -> size_t;

/**
* @return The operation mode.
*/
[[nodiscard]] auto get_mode() const -> Mode { return m_mode; }

private:
int m_fd{-1};
Mode m_mode;
CloseFailureCallback m_close_failure_callback{nullptr};
};
} // namespace clp

#endif
41 changes: 41 additions & 0 deletions components/core/src/clp/MemoryMappedFileView.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
#include "MemoryMappedFileView.hpp"

#include <sys/mman.h>

#include <string>
#include <string_view>

#include "ErrorCode.hpp"
#include "FileDescriptor.hpp"

namespace clp {
MemoryMappedFileView::MemoryMappedFileView(std::string_view path) {
FileDescriptor const fd{path, FileDescriptor::Mode::ReadOnly};
auto const file_size{fd.get_size()};
if (0 == file_size) {
// If the file is empty, we should call `mmap` since a length greater than 0 is expected.
// The default construct should already set buffer length to 0.
LinZhihao-723 marked this conversation as resolved.
Show resolved Hide resolved
return;
}
auto* mmap_ptr{mmap(nullptr, file_size, PROT_READ, MAP_PRIVATE, fd.get_raw_fd(), 0)};
if (MAP_FAILED == mmap_ptr) {
throw OperationFailed(
ErrorCode_errno,
__FILE__,
__LINE__,
"`mmap` failed to map the file in path: " + std::string{path}
LinZhihao-723 marked this conversation as resolved.
Show resolved Hide resolved
);
}
m_data = mmap_ptr;
m_buf_size = file_size;
}

MemoryMappedFileView::~MemoryMappedFileView() {
if (0 == m_buf_size) {
// If the mapped region has a length of 0, we should not call `munmap` since 0 is an invalid
// length to unmap a region.
LinZhihao-723 marked this conversation as resolved.
Show resolved Hide resolved
return;
}
munmap(m_data, m_buf_size);
LinZhihao-723 marked this conversation as resolved.
Show resolved Hide resolved
}
} // namespace clp
66 changes: 66 additions & 0 deletions components/core/src/clp/MemoryMappedFileView.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
#ifndef CLP_MEMORYMAPPEDFILEVIEW_HPP
#define CLP_MEMORYMAPPEDFILEVIEW_HPP

#include <cstddef>
#include <span>
#include <string>
#include <string_view>
#include <utility>

#include "ErrorCode.hpp"
#include "TraceableException.hpp"

namespace clp {
/**
* A class for mapping a read-only file into memory. It maintains the memory buffer created by the
* underlying `mmap` system call and provides methods to get a view of the memory buffer.
*/
class MemoryMappedFileView {
LinZhihao-723 marked this conversation as resolved.
Show resolved Hide resolved
public:
// Types
class OperationFailed : public TraceableException {
public:
OperationFailed(
ErrorCode error_code,
char const* const filename,
int line_number,
std::string msg
)
: TraceableException{error_code, filename, line_number},
m_msg{std::move(msg)} {}

[[nodiscard]] auto what() const noexcept -> char const* override { return m_msg.c_str(); }

private:
std::string m_msg;
};

// Constructors
/**
* @param path The path of the file to map.
*/
MemoryMappedFileView(std::string_view path);
LinZhihao-723 marked this conversation as resolved.
Show resolved Hide resolved

// Destructor
~MemoryMappedFileView();

// Disable copy/move constructors/assignment operators
MemoryMappedFileView(MemoryMappedFileView const&) = delete;
MemoryMappedFileView(MemoryMappedFileView&&) = delete;
auto operator=(MemoryMappedFileView const&) -> MemoryMappedFileView& = delete;
auto operator=(MemoryMappedFileView&&) -> MemoryMappedFileView& = delete;

/**
* @return A view to the mapped file in memory.
LinZhihao-723 marked this conversation as resolved.
Show resolved Hide resolved
*/
[[nodiscard]] auto get_view() const -> std::span<char> {
return std::span<char>{static_cast<char*>(m_data), m_buf_size};
}

private:
void* m_data{nullptr};
size_t m_buf_size{0};
};
} // namespace clp

#endif
4 changes: 4 additions & 0 deletions components/core/src/clp/clg/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,8 @@ set(
../ffi/ir_stream/decoding_methods.cpp
../ffi/ir_stream/decoding_methods.hpp
../ffi/ir_stream/decoding_methods.inc
../FileDescriptor.cpp
../FileDescriptor.hpp
../FileReader.cpp
../FileReader.hpp
../FileWriter.cpp
Expand All @@ -41,6 +43,8 @@ set(
../LogTypeDictionaryEntry.cpp
../LogTypeDictionaryEntry.hpp
../LogTypeDictionaryReader.hpp
../MemoryMappedFileView.cpp
../MemoryMappedFileView.hpp
../MySQLDB.cpp
../MySQLDB.hpp
../MySQLParamBindings.cpp
Expand Down
4 changes: 4 additions & 0 deletions components/core/src/clp/clo/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,8 @@ set(
../ffi/ir_stream/decoding_methods.cpp
../ffi/ir_stream/decoding_methods.hpp
../ffi/ir_stream/decoding_methods.inc
../FileDescriptor.cpp
../FileDescriptor.hpp
../FileReader.cpp
../FileReader.hpp
../FileWriter.cpp
Expand All @@ -36,6 +38,8 @@ set(
../LogTypeDictionaryEntry.cpp
../LogTypeDictionaryEntry.hpp
../LogTypeDictionaryReader.hpp
../MemoryMappedFileView.cpp
../MemoryMappedFileView.hpp
../networking/socket_utils.cpp
../networking/socket_utils.hpp
../networking/SocketOperationFailed.hpp
Expand Down
4 changes: 4 additions & 0 deletions components/core/src/clp/clp/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,8 @@ set(
../ffi/ir_stream/encoding_methods.hpp
../ffi/ir_stream/utils.cpp
../ffi/ir_stream/utils.hpp
../FileDescriptor.cpp
../FileDescriptor.hpp
../FileReader.cpp
../FileReader.hpp
../FileWriter.cpp
Expand Down Expand Up @@ -62,6 +64,8 @@ set(
../LogTypeDictionaryWriter.cpp
../LogTypeDictionaryWriter.hpp
../math_utils.hpp
../MemoryMappedFileView.cpp
../MemoryMappedFileView.hpp
../MessageParser.cpp
../MessageParser.hpp
../MySQLDB.cpp
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@ set(
../dictionary_utils.hpp
../DictionaryEntry.hpp
../DictionaryReader.hpp
../FileDescriptor.cpp
../FileDescriptor.hpp
../FileReader.cpp
../FileReader.hpp
../FileWriter.cpp
Expand All @@ -13,6 +15,8 @@ set(
../LogTypeDictionaryEntry.cpp
../LogTypeDictionaryEntry.hpp
../LogTypeDictionaryReader.hpp
../MemoryMappedFileView.cpp
../MemoryMappedFileView.hpp
../ParsedMessage.cpp
../ParsedMessage.hpp
../ReaderInterface.cpp
Expand Down
Loading
Loading