forked from mooncake-track/Mooncake
177 lines
5.7 KiB
C++
177 lines
5.7 KiB
C++
#pragma once
|
|
|
|
#include <string>
|
|
#include <unordered_map>
|
|
#include <sys/uio.h>
|
|
#include <cstdio>
|
|
#include "types.h"
|
|
#include <atomic>
|
|
#include <thread>
|
|
#include <sys/file.h>
|
|
|
|
namespace mooncake {
|
|
class FileLockRAII {
|
|
public:
|
|
enum class LockType { READ, WRITE };
|
|
|
|
FileLockRAII(int fd, LockType type) : fd_(fd), locked_(false) {
|
|
if (type == LockType::READ) {
|
|
locked_ = (flock(fd_, LOCK_SH) == 0);
|
|
} else {
|
|
locked_ = (flock(fd_, LOCK_EX) == 0);
|
|
}
|
|
}
|
|
|
|
~FileLockRAII() {
|
|
if (locked_) {
|
|
flock(fd_, LOCK_UN);
|
|
}
|
|
}
|
|
|
|
FileLockRAII(const FileLockRAII &) = delete;
|
|
FileLockRAII &operator=(const FileLockRAII &) = delete;
|
|
|
|
FileLockRAII(FileLockRAII &&other) noexcept
|
|
: fd_(other.fd_), locked_(other.locked_) {
|
|
other.locked_ = false;
|
|
}
|
|
|
|
bool is_locked() const { return locked_; }
|
|
|
|
private:
|
|
int fd_;
|
|
bool locked_;
|
|
};
|
|
|
|
/**
|
|
* @class LocalFile
|
|
* @brief RAII wrapper for file operations with thread-safe locking support
|
|
*
|
|
* Provides thread-safe file I/O operations including read/write and vectorized
|
|
* I/O. Implements proper resource management through RAII pattern.
|
|
*/
|
|
class StorageFile {
|
|
public:
|
|
StorageFile(const std::string &filename, int fd)
|
|
: filename_(filename),
|
|
fd_(fd),
|
|
error_code_(ErrorCode::OK),
|
|
is_locked_(false) {}
|
|
/**
|
|
* @brief Destructor
|
|
* @note Automatically closes the file and releases resources
|
|
*/
|
|
virtual ~StorageFile() = default;
|
|
|
|
/**
|
|
* @brief Writes data from buffer to file
|
|
* @param buffer Input buffer containing data to write
|
|
* @param length Number of bytes to write
|
|
* @return tl::expected<size_t, ErrorCode> containing number of bytes
|
|
* written on success, or ErrorCode on failure
|
|
* @note Thread-safe operation with write locking
|
|
*/
|
|
virtual tl::expected<size_t, ErrorCode> write(const std::string &buffer,
|
|
size_t length) = 0;
|
|
|
|
/**
|
|
* @brief Writes data from buffer to file
|
|
* @param data Input span containing data to write
|
|
* @param length Number of bytes to write
|
|
* @return tl::expected<size_t, ErrorCode> containing number of bytes
|
|
* written on success, or ErrorCode on failure
|
|
* @note Thread-safe operation with write locking
|
|
*/
|
|
virtual tl::expected<size_t, ErrorCode> write(std::span<const char> data,
|
|
size_t length) = 0;
|
|
|
|
/**
|
|
* @brief Reads data from file into buffer
|
|
* @param buffer Output buffer for read data
|
|
* @param length Maximum number of bytes to read
|
|
* @return tl::expected<size_t, ErrorCode> containing number of bytes read
|
|
* on success, or ErrorCode on failure
|
|
* @note Thread-safe operation with read locking
|
|
*/
|
|
virtual tl::expected<size_t, ErrorCode> read(std::string &buffer,
|
|
size_t length) = 0;
|
|
|
|
/**
|
|
* @brief Scattered write at specified file offset
|
|
* @param iov Array of I/O vectors
|
|
* @param iovcnt Number of elements in iov array
|
|
* @param offset File offset to write at
|
|
* @return tl::expected<size_t, ErrorCode> containing total bytes written on
|
|
* success, or ErrorCode on failure
|
|
* @note Thread-safe operation with write locking
|
|
*/
|
|
virtual tl::expected<size_t, ErrorCode> vector_write(const iovec *iov,
|
|
int iovcnt,
|
|
off_t offset) = 0;
|
|
|
|
/**
|
|
* @brief Scattered read from specified file offset
|
|
* @param iov Array of I/O vectors
|
|
* @param iovcnt Number of elements in iov array
|
|
* @param offset File offset to read from
|
|
* @return tl::expected<size_t, ErrorCode> containing total bytes read on
|
|
* success, or ErrorCode on failure
|
|
* @note Thread-safe operation with read locking
|
|
*/
|
|
virtual tl::expected<size_t, ErrorCode> vector_read(const iovec *iov,
|
|
int iovcnt,
|
|
off_t offset) = 0;
|
|
|
|
template <typename T>
|
|
tl::expected<T, ErrorCode> make_error(ErrorCode code) {
|
|
error_code_ = code;
|
|
return tl::make_unexpected(code);
|
|
}
|
|
|
|
/**
|
|
* @brief file locking mechanism
|
|
*/
|
|
FileLockRAII acquire_write_lock() {
|
|
return FileLockRAII(fd_, FileLockRAII::LockType::WRITE);
|
|
}
|
|
|
|
FileLockRAII acquire_read_lock() {
|
|
return FileLockRAII(fd_, FileLockRAII::LockType::READ);
|
|
}
|
|
|
|
/**
|
|
* @brief Gets the current error code
|
|
* @return Current error code
|
|
*/
|
|
ErrorCode get_error_code() { return error_code_; }
|
|
|
|
protected:
|
|
std::string filename_;
|
|
int fd_;
|
|
ErrorCode error_code_{ErrorCode::OK};
|
|
std::atomic<bool> is_locked_{false};
|
|
};
|
|
|
|
class PosixFile : public StorageFile {
|
|
public:
|
|
PosixFile(const std::string &filename, int fd);
|
|
~PosixFile() override;
|
|
|
|
tl::expected<size_t, ErrorCode> write(const std::string &buffer,
|
|
size_t length) override;
|
|
tl::expected<size_t, ErrorCode> write(std::span<const char> data,
|
|
size_t length) override;
|
|
tl::expected<size_t, ErrorCode> read(std::string &buffer,
|
|
size_t length) override;
|
|
tl::expected<size_t, ErrorCode> vector_write(const iovec *iov, int iovcnt,
|
|
off_t offset) override;
|
|
tl::expected<size_t, ErrorCode> vector_read(const iovec *iov, int iovcnt,
|
|
off_t offset) override;
|
|
};
|
|
|
|
} // namespace mooncake
|
|
|
|
#ifdef USE_3FS
|
|
#include <hf3fs/hf3fs.h>
|
|
#endif
|