19#include <vrs/DiskFile.h>
21#if VRS_ASYNC_DISKFILE_SUPPORTED()
29#define POSIX_AIO_SUPPORTED() (IS_MAC_PLATFORM() || IS_LINUX_PLATFORM())
31#if IS_WINDOWS_PLATFORM()
34#elif POSIX_AIO_SUPPORTED()
44#include <condition_variable>
51#include <vrs/ErrorCode.h>
52#include <vrs/VrsExport.h>
53#include <vrs/os/Platform.h>
55#define VRS_DISKFILECHUNK "AsyncDiskFileChunk"
59#if IS_WINDOWS_PLATFORM()
61using ssize_t = int64_t;
62#define O_DIRECT 0x80000000U
64struct VRS_API AsyncWindowsHandle {
65 AsyncWindowsHandle() : h_(INVALID_HANDLE_VALUE) {}
66 AsyncWindowsHandle(HANDLE h) : h_(h) {}
67 AsyncWindowsHandle(AsyncWindowsHandle&& rhs) : h_(rhs.h_) {
68 rhs.h_ = INVALID_HANDLE_VALUE;
70 AsyncWindowsHandle(AsyncWindowsHandle& rhs) : h_(rhs.h_) {}
71 AsyncWindowsHandle& operator=(AsyncWindowsHandle&& rhs) {
73 rhs.h_ = INVALID_HANDLE_VALUE;
77 bool isOpened()
const;
78 int open(
const std::string& path,
const char* modes,
int flags);
80 int pwrite(
const void* buf,
size_t count, int64_t offset,
size_t& outWriteSize);
81 int read(
void* buf,
size_t count, int64_t offset,
size_t& outReadSize);
82 int truncate(int64_t newSize);
83 int seek(int64_t pos,
int origin, int64_t& outFilepos);
86 int _readwrite(
bool readNotWrite,
void* buf,
size_t count, int64_t offset,
size_t& outSize);
89 HANDLE h_ = INVALID_HANDLE_VALUE;
92using AsyncHandle = AsyncWindowsHandle;
94struct VRS_API AsyncFileDescriptor {
95 static constexpr int INVALID_FILE_DESCRIPTOR = -1;
97 AsyncFileDescriptor() =
default;
98 explicit AsyncFileDescriptor(
int fd) : fd_(fd) {}
99 AsyncFileDescriptor(AsyncFileDescriptor&& rhs) noexcept : fd_(rhs.fd_) {
100 rhs.fd_ = INVALID_FILE_DESCRIPTOR;
102 AsyncFileDescriptor(
const AsyncFileDescriptor& rhs)
noexcept =
delete;
103 AsyncFileDescriptor& operator=(AsyncFileDescriptor&& rhs)
noexcept {
105 rhs.fd_ = INVALID_FILE_DESCRIPTOR;
108 AsyncFileDescriptor& operator=(
const AsyncFileDescriptor& rhs) =
delete;
110 bool operator==(
int fd)
const {
114 int open(
const std::string& path,
const char* modes,
int flags);
115 [[nodiscard]]
bool isOpened()
const;
116 int read(
void* ptr,
size_t bufferSize,
size_t offset,
size_t& outReadSize);
117 int truncate(int64_t newSize);
118 int seek(int64_t pos,
int origin, int64_t& outFilepos);
119 int pwrite(
const void* buf,
size_t count, off_t offset,
size_t& written);
122 int fd_ = INVALID_FILE_DESCRIPTOR;
124using AsyncHandle = AsyncFileDescriptor;
127class VRS_API AlignedBuffer {
129 void* aligned_buffer_ =
nullptr;
130 size_t capacity_ = 0;
134 AlignedBuffer(
size_t size,
size_t memalign,
size_t lenalign);
135 virtual ~AlignedBuffer();
137 [[nodiscard]]
inline size_t size()
const {
140 [[nodiscard]]
inline size_t capacity()
const {
143 [[nodiscard]]
inline bool empty()
const {
146 [[nodiscard]]
inline bool full()
const {
147 return size() == capacity();
152 [[nodiscard]]
inline void* data()
const {
153 return aligned_buffer_;
155 [[nodiscard]]
inline char* bdata()
const {
156 return reinterpret_cast<char*
>(aligned_buffer_);
158 [[nodiscard]] ssize_t add(
const void* buffer,
size_t size);
162#if IS_WINDOWS_PLATFORM()
163struct VRS_API AsyncOVERLAPPED {
170class VRS_API AsyncBuffer :
public AlignedBuffer {
172 using complete_write_callback = std::function<void(ssize_t io_return,
int io_errno)>;
174 AsyncBuffer(
size_t size,
size_t memalign,
size_t lenalign)
175 : AlignedBuffer(size, memalign, lenalign) {}
176 ~AsyncBuffer()
override =
default;
178 void complete_write(ssize_t io_return,
int io_errno);
180 start_write(
const AsyncHandle& file, int64_t offset, complete_write_callback on_complete);
183#if IS_WINDOWS_PLATFORM()
185 static void CompletedWriteRoutine(DWORD dwErr, DWORD cbBytesWritten, LPOVERLAPPED lpOverlapped);
186#elif POSIX_AIO_SUPPORTED()
187 struct aiocb aiocb_{};
188 static void SigEvNotifyFunction(
union sigval val);
190 complete_write_callback on_complete_ =
nullptr;
193class VRS_API AsyncDiskFileChunk {
195 AsyncDiskFileChunk() =
default;
196 AsyncDiskFileChunk(std::string path, int64_t offset, int64_t size)
197 : path_{std::move(path)}, offset_{offset}, size_{size} {}
198 AsyncDiskFileChunk(AsyncDiskFileChunk&& other)
noexcept;
201 AsyncDiskFileChunk(
const AsyncDiskFileChunk& other)
noexcept =
delete;
202 AsyncDiskFileChunk& operator=(
const AsyncDiskFileChunk& other)
noexcept =
delete;
203 AsyncDiskFileChunk& operator=(AsyncDiskFileChunk&& rhs)
noexcept =
delete;
205 ~AsyncDiskFileChunk();
207 int create(
const std::string& newpath,
const FileSpec::Extras& options);
208 int open(
bool readOnly,
const FileSpec::Extras& options);
211 [[nodiscard]]
bool eof()
const;
213 int write(
const void* buffer,
size_t count,
size_t& outWrittenSize);
214 void setSize(int64_t newSize);
216 int truncate(int64_t newSize);
217 int read(
void* buffer,
size_t count,
size_t& outReadSize);
218 [[nodiscard]] int64_t getSize()
const;
219 [[nodiscard]]
bool contains(int64_t fileOffset)
const;
220 int tell(int64_t& outFilepos)
const;
221 int seek(int64_t pos,
int origin);
222 [[nodiscard]]
const std::string& getPath()
const;
223 void setOffset(int64_t newOffset);
224 [[nodiscard]] int64_t getOffset()
const;
226 enum class IoEngine {
234 AsyncBuffer* buffer_;
237 const AsyncHandle& file_;
239 AsyncBuffer::complete_write_callback callback_;
244 AsyncBuffer::complete_write_callback callback)
245 : buffer_(buffer), file_(file), offset_(offset), callback_(std::move(callback)) {}
248 int flushWriteBuffer();
249 int ensureOpenNonDirect();
250 int ensureOpenDirect();
251 int ensureOpen_(
int requested_flags);
252 void complete_write(AsyncBuffer* buffer, ssize_t io_return,
int io_errno);
253 AsyncBuffer* get_free_buffer_locked(std::unique_lock<std::mutex>& lock);
254 AsyncBuffer* get_free_buffer();
255 void free_buffer(AsyncBuffer*& buffer);
256 void free_buffer_locked(std::unique_lock<std::mutex>& lock, AsyncBuffer*& buffer);
258 void pump_buffers_locked();
259 int alloc_write_buffers();
260 int free_write_buffers();
261 int init_parameters(
const FileSpec::Extras& options);
269 int64_t file_position_ = 0;
271 const char* file_mode_ =
nullptr;
274 int current_flags_ = 0;
276 int supported_flags_ = 0;
281 std::mutex buffers_mutex_;
283 std::condition_variable buffer_freed_cv_;
285 std::vector<AsyncBuffer*> buffers_free_;
287 std::deque<QueuedWrite> buffers_queued_;
292 size_t buffers_writing_ = 0;
295 std::vector<std::unique_ptr<AsyncBuffer>> buffers_;
298 AsyncBuffer* current_buffer_ =
nullptr;
302 std::atomic<int> async_error_ = SUCCESS;
306 IoEngine ioengine_ = IoEngine::AIO;
307 bool use_directio_ =
true;
309 size_t num_buffers_ = 0;
311 size_t buffer_size_ = 0;
315 size_t offset_align_ = 0;
317 size_t mem_align_ = 0;
int write(const string &cacheFile, const set< StreamId > &streamIds, const map< string, string > &fileTags, const map< StreamId, StreamTags > &streamTags, const vector< IndexRecord::RecordInfo > &recordIndex, bool fileHasIndex)
Definition FileDetailsCache.cpp:225
int read(const string &cacheFile, set< StreamId > &outStreamIds, map< string, string > &outFileTags, map< StreamId, StreamTags > &outStreamTags, vector< IndexRecord::RecordInfo > &outRecordIndex, bool &outFileHasIndex)
Definition FileDetailsCache.cpp:266
Definition Compressor.cpp:113