diff options
| author | Dimitris <dimstav23@gmail.com> | 2025-07-15 15:11:36 +0200 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2025-07-15 15:11:36 +0200 |
| commit | 73e505f04d17eba36c41fce7b48bc4d6884b8fd0 (patch) | |
| tree | 44b5f4627309a48d6f22b54bb2ad9a2976e8601b /archive/2025/summer/bsc_karidas/include/SegmentedStorage.hpp | |
| parent | ca92e7ad181a02890496872012ecc6c1d08b1658 (diff) | |
| parent | d8c365681a41961ebe2daea5701a4d56f5400d1d (diff) | |
| download | research-work-archive-artifacts-73e505f04d17eba36c41fce7b48bc4d6884b8fd0.tar.gz research-work-archive-artifacts-73e505f04d17eba36c41fce7b48bc4d6884b8fd0.zip | |
Merge pull request #6 from chriskari/upload-artifacts
Add bsc_karidas
Diffstat (limited to 'archive/2025/summer/bsc_karidas/include/SegmentedStorage.hpp')
| -rw-r--r-- | archive/2025/summer/bsc_karidas/include/SegmentedStorage.hpp | 144 |
1 files changed, 144 insertions, 0 deletions
diff --git a/archive/2025/summer/bsc_karidas/include/SegmentedStorage.hpp b/archive/2025/summer/bsc_karidas/include/SegmentedStorage.hpp new file mode 100644 index 000000000..3984aea79 --- /dev/null +++ b/archive/2025/summer/bsc_karidas/include/SegmentedStorage.hpp @@ -0,0 +1,144 @@ +#ifndef SEGMENTED_STORAGE_HPP +#define SEGMENTED_STORAGE_HPP + +#include <string> +#include <vector> +#include <atomic> +#include <mutex> +#include <shared_mutex> +#include <filesystem> +#include <cstdint> +#include <unordered_map> +#include <fcntl.h> // for open flags +#include <unistd.h> // for close, pwrite, fsync +#include <chrono> +#include <thread> +#include <stdexcept> +#include <list> // For LRU cache + +class SegmentedStorage +{ +public: + SegmentedStorage(const std::string &basePath, + const std::string &baseFilename, + size_t maxSegmentSize = 100 * 1024 * 1024, // 100 MB default + size_t maxAttempts = 5, + std::chrono::milliseconds baseRetryDelay = std::chrono::milliseconds(1), + size_t maxOpenFiles = 512); + + ~SegmentedStorage(); + + size_t write(std::vector<uint8_t> &&data); + size_t writeToFile(const std::string &filename, std::vector<uint8_t> &&data); + void flush(); + +private: + std::string m_basePath; + std::string m_baseFilename; + size_t m_maxSegmentSize; + size_t m_maxAttempts; + std::chrono::milliseconds m_baseRetryDelay; + size_t m_maxOpenFiles; // Max number of cache entries + + struct CacheEntry + { + int fd{-1}; + std::atomic<size_t> segmentIndex{0}; + std::atomic<size_t> currentOffset{0}; + std::string currentSegmentPath; + mutable std::shared_mutex fileMutex; // shared for writes, exclusive for rotate/flush + }; + + // Unified LRU Cache for both file descriptors and segment information + class LRUCache + { + public: + LRUCache(size_t capacity, SegmentedStorage *parent) : m_capacity(capacity), m_parent(parent) {} + + std::shared_ptr<CacheEntry> get(const std::string &filename); + void flush(const std::string &filename); + void flushAll(); + void closeAll(); + + private: + size_t m_capacity; + SegmentedStorage *m_parent; + + // LRU list of filenames + std::list<std::string> m_lruList; + // Map from filename to cache entry and iterator in LRU list + struct CacheData + { + std::shared_ptr<CacheEntry> entry; + std::list<std::string>::iterator lruIt; + }; + std::unordered_map<std::string, CacheData> m_cache; + mutable std::mutex m_mutex; // Protects m_lruList and m_cache + + void evictLRU(); + std::shared_ptr<CacheEntry> reconstructState(const std::string &filename); + }; + + LRUCache m_cache; + + std::string rotateSegment(const std::string &filename, std::shared_ptr<CacheEntry> entry); + std::string generateSegmentPath(const std::string &filename, size_t segmentIndex) const; + size_t getFileSize(const std::string &path) const; + size_t findLatestSegmentIndex(const std::string &filename) const; + + // Retry helpers use member-configured parameters + template <typename Func> + auto retryWithBackoff(Func &&f) + { + for (size_t attempt = 1;; ++attempt) + { + try + { + return f(); + } + catch (const std::runtime_error &) + { + if (attempt >= m_maxAttempts) + throw; + auto delay = m_baseRetryDelay * (1 << (attempt - 1)); + std::this_thread::sleep_for(delay); + } + } + } + + int openWithRetry(const char *path, int flags, mode_t mode) + { + return retryWithBackoff([&]() + { + int fd = ::open(path, flags, mode); + if (fd < 0) throw std::runtime_error("open failed"); + return fd; }); + } + + size_t pwriteFull(int fd, const uint8_t *buf, size_t count, off_t offset) + { + size_t total = 0; + while (total < count) + { + ssize_t written = ::pwrite(fd, buf + total, count - total, offset + total); + if (written < 0) + { + if (errno == EINTR) + continue; + throw std::runtime_error("pwrite failed"); + } + total += written; + } + return total; + } + + void fsyncRetry(int fd) + { + retryWithBackoff([&]() + { + if (::fsync(fd) < 0) throw std::runtime_error("fsync failed"); + return 0; }); + } +}; + +#endif \ No newline at end of file |