file_handle.hpp
1 /*
2  * SPDX-FileCopyrightText: Copyright (c) 2021-2025, NVIDIA CORPORATION.
3  * SPDX-License-Identifier: Apache-2.0
4  */
5 #pragma once
6 
7 #include <sys/stat.h>
8 #include <sys/types.h>
9 
10 #include <cstddef>
11 #include <cstdlib>
12 
13 #include <kvikio/buffer.hpp>
14 #include <kvikio/compat_mode.hpp>
15 #include <kvikio/compat_mode_manager.hpp>
16 #include <kvikio/cufile/config.hpp>
17 #include <kvikio/defaults.hpp>
18 #include <kvikio/error.hpp>
19 #include <kvikio/file_utils.hpp>
20 #include <kvikio/shim/cufile.hpp>
21 #include <kvikio/shim/cufile_h_wrapper.hpp>
22 #include <kvikio/stream.hpp>
23 #include <kvikio/threadpool_wrapper.hpp>
24 #include <kvikio/utils.hpp>
25 
26 namespace kvikio {
27 
33 class FileHandle {
34  private:
35  // We use two file descriptors, one opened with the O_DIRECT flag and one without.
36  FileWrapper _file_direct_on{};
37  FileWrapper _file_direct_off{};
38  bool _initialized{false};
39  mutable std::size_t _nbytes{0}; // The size of the underlying file, zero means unknown.
40  CUFileHandleWrapper _cufile_handle{};
41  CompatModeManager _compat_mode_manager;
42  friend class CompatModeManager;
43  ThreadPool* _thread_pool{};
44 
45  public:
46  // 644 is a common setting of Unix file permissions: read and write for owner, read-only for group
47  // and others.
48  static constexpr mode_t m644 = S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH;
49  FileHandle() noexcept = default;
50 
67  FileHandle(std::string const& file_path,
68  std::string const& flags = "r",
69  mode_t mode = m644,
70  CompatMode compat_mode = defaults::compat_mode());
71 
75  FileHandle(FileHandle const&) = delete;
76  FileHandle& operator=(FileHandle const&) = delete;
77  FileHandle(FileHandle&& o) noexcept;
78  FileHandle& operator=(FileHandle&& o) noexcept;
79  ~FileHandle() noexcept;
80 
86  [[nodiscard]] bool closed() const noexcept;
87 
91  void close() noexcept;
92 
101  [[nodiscard]] CUfileHandle_t handle();
102 
112  [[nodiscard]] int fd(bool o_direct = false) const noexcept;
113 
124  [[nodiscard]] int fd_open_flags(bool o_direct = false) const;
125 
133  [[nodiscard]] std::size_t nbytes() const;
134 
165  std::size_t read(void* devPtr_base,
166  std::size_t size,
167  std::size_t file_offset,
168  std::size_t devPtr_offset,
169  bool sync_default_stream = true);
170 
202  std::size_t write(void const* devPtr_base,
203  std::size_t size,
204  std::size_t file_offset,
205  std::size_t devPtr_offset,
206  bool sync_default_stream = true);
207 
242  std::future<std::size_t> pread(void* buf,
243  std::size_t size,
244  std::size_t file_offset = 0,
245  std::size_t task_size = defaults::task_size(),
246  std::size_t gds_threshold = defaults::gds_threshold(),
247  bool sync_default_stream = true,
248  ThreadPool* thread_pool = &defaults::thread_pool());
249 
284  std::future<std::size_t> pwrite(void const* buf,
285  std::size_t size,
286  std::size_t file_offset = 0,
287  std::size_t task_size = defaults::task_size(),
288  std::size_t gds_threshold = defaults::gds_threshold(),
289  bool sync_default_stream = true,
290  ThreadPool* thread_pool = &defaults::thread_pool());
291 
323  void read_async(void* devPtr_base,
324  std::size_t* size_p,
325  off_t* file_offset_p,
326  off_t* devPtr_offset_p,
327  ssize_t* bytes_read_p,
328  CUstream stream);
329 
352  [[nodiscard]] StreamFuture read_async(void* devPtr_base,
353  std::size_t size,
354  off_t file_offset = 0,
355  off_t devPtr_offset = 0,
356  CUstream stream = nullptr);
357 
390  void write_async(void* devPtr_base,
391  std::size_t* size_p,
392  off_t* file_offset_p,
393  off_t* devPtr_offset_p,
394  ssize_t* bytes_written_p,
395  CUstream stream);
396 
419  [[nodiscard]] StreamFuture write_async(void* devPtr_base,
420  std::size_t size,
421  off_t file_offset = 0,
422  off_t devPtr_offset = 0,
423  CUstream stream = nullptr);
424 
433 
442  bool is_direct_io_supported() const noexcept;
443 };
444 
445 } // namespace kvikio
Class that provides RAII for the cuFile handle.
Definition: file_utils.hpp:75
Store and manage the compatibility mode data associated with a FileHandle.
Handle of an open file registered with cufile.
Definition: file_handle.hpp:33
void close() noexcept
Deregister the file and close the two files.
int fd(bool o_direct=false) const noexcept
Get one of the file descriptors.
void read_async(void *devPtr_base, std::size_t *size_p, off_t *file_offset_p, off_t *devPtr_offset_p, ssize_t *bytes_read_p, CUstream stream)
Reads specified bytes from the file into the device memory asynchronously.
int fd_open_flags(bool o_direct=false) const
Get the flags of one of the file descriptors (see open(2))
std::size_t write(void const *devPtr_base, std::size_t size, std::size_t file_offset, std::size_t devPtr_offset, bool sync_default_stream=true)
Writes specified bytes from the device memory into the file.
CUfileHandle_t handle()
Get the underlying cuFile file handle.
const CompatModeManager & get_compat_mode_manager() const noexcept
Get the associated compatibility mode manager, which can be used to query the original requested comp...
FileHandle(std::string const &file_path, std::string const &flags="r", mode_t mode=m644, CompatMode compat_mode=defaults::compat_mode())
Construct a file handle from a file path.
bool closed() const noexcept
Whether the file is closed according to its initialization status.
std::future< std::size_t > pread(void *buf, std::size_t size, std::size_t file_offset=0, std::size_t task_size=defaults::task_size(), std::size_t gds_threshold=defaults::gds_threshold(), bool sync_default_stream=true, ThreadPool *thread_pool=&defaults::thread_pool())
Reads specified bytes from the file into the device or host memory in parallel.
std::future< std::size_t > pwrite(void const *buf, std::size_t size, std::size_t file_offset=0, std::size_t task_size=defaults::task_size(), std::size_t gds_threshold=defaults::gds_threshold(), bool sync_default_stream=true, ThreadPool *thread_pool=&defaults::thread_pool())
Writes specified bytes from device or host memory into the file in parallel.
void write_async(void *devPtr_base, std::size_t *size_p, off_t *file_offset_p, off_t *devPtr_offset_p, ssize_t *bytes_written_p, CUstream stream)
Writes specified bytes from the device memory into the file asynchronously.
std::size_t nbytes() const
Get the file size.
std::size_t read(void *devPtr_base, std::size_t size, std::size_t file_offset, std::size_t devPtr_offset, bool sync_default_stream=true)
Reads specified bytes from the file into the device memory.
bool is_direct_io_supported() const noexcept
Whether Direct I/O is supported on this file handle. This is determined by two factors:
FileHandle(FileHandle const &)=delete
FileHandle support move semantic but isn't copyable.
Class that provides RAII for file handling.
Definition: file_utils.hpp:16
Future of an asynchronous IO operation.
Definition: stream.hpp:35
Singleton class of default values used throughout KvikIO.
Definition: defaults.hpp:112
static CompatMode compat_mode()
Return whether the KvikIO library is running in compatibility mode or not.
KvikIO namespace.
Definition: batch.hpp:16
BS::thread_pool ThreadPool
Thread pool type used for parallel I/O operations.
CompatMode
I/O compatibility mode.
Definition: compat_mode.hpp:15