file_handle.hpp
1 /*
2  * Copyright (c) 2021-2025, NVIDIA CORPORATION.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 #pragma once
17 
18 #include <sys/stat.h>
19 #include <sys/types.h>
20 
21 #include <cstddef>
22 #include <cstdlib>
23 
24 #include <kvikio/buffer.hpp>
25 #include <kvikio/compat_mode.hpp>
26 #include <kvikio/compat_mode_manager.hpp>
27 #include <kvikio/cufile/config.hpp>
28 #include <kvikio/defaults.hpp>
29 #include <kvikio/error.hpp>
30 #include <kvikio/file_utils.hpp>
31 #include <kvikio/parallel_operation.hpp>
32 #include <kvikio/posix_io.hpp>
33 #include <kvikio/shim/cufile.hpp>
34 #include <kvikio/shim/cufile_h_wrapper.hpp>
35 #include <kvikio/stream.hpp>
36 #include <kvikio/utils.hpp>
37 
38 namespace kvikio {
39 
45 class FileHandle {
46  private:
47  // We use two file descriptors, one opened with the O_DIRECT flag and one without.
48  FileWrapper _file_direct_on{};
49  FileWrapper _file_direct_off{};
50  bool _initialized{false};
51  mutable std::size_t _nbytes{0}; // The size of the underlying file, zero means unknown.
52  CUFileHandleWrapper _cufile_handle{};
53  CompatModeManager _compat_mode_manager;
54  friend class CompatModeManager;
55 
56  public:
57  // 644 is a common setting of Unix file permissions: read and write for owner, read-only for group
58  // and others.
59  static constexpr mode_t m644 = S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH;
60  FileHandle() noexcept = default;
61 
78  FileHandle(std::string const& file_path,
79  std::string const& flags = "r",
80  mode_t mode = m644,
81  CompatMode compat_mode = defaults::compat_mode());
82 
86  FileHandle(FileHandle const&) = delete;
87  FileHandle& operator=(FileHandle const&) = delete;
88  FileHandle(FileHandle&& o) noexcept;
89  FileHandle& operator=(FileHandle&& o) noexcept;
90  ~FileHandle() noexcept;
91 
97  [[nodiscard]] bool closed() const noexcept;
98 
102  void close() noexcept;
103 
112  [[nodiscard]] CUfileHandle_t handle();
113 
123  [[nodiscard]] int fd(bool o_direct = false) const noexcept;
124 
135  [[nodiscard]] int fd_open_flags(bool o_direct = false) const;
136 
144  [[nodiscard]] std::size_t nbytes() const;
145 
176  std::size_t read(void* devPtr_base,
177  std::size_t size,
178  std::size_t file_offset,
179  std::size_t devPtr_offset,
180  bool sync_default_stream = true);
181 
213  std::size_t write(void const* devPtr_base,
214  std::size_t size,
215  std::size_t file_offset,
216  std::size_t devPtr_offset,
217  bool sync_default_stream = true);
218 
249  std::future<std::size_t> pread(void* buf,
250  std::size_t size,
251  std::size_t file_offset = 0,
252  std::size_t task_size = defaults::task_size(),
253  std::size_t gds_threshold = defaults::gds_threshold(),
254  bool sync_default_stream = true);
255 
286  std::future<std::size_t> pwrite(void const* buf,
287  std::size_t size,
288  std::size_t file_offset = 0,
289  std::size_t task_size = defaults::task_size(),
290  std::size_t gds_threshold = defaults::gds_threshold(),
291  bool sync_default_stream = true);
292 
327  void read_async(void* devPtr_base,
328  std::size_t* size_p,
329  off_t* file_offset_p,
330  off_t* devPtr_offset_p,
331  ssize_t* bytes_read_p,
332  CUstream stream);
333 
359  [[nodiscard]] StreamFuture read_async(void* devPtr_base,
360  std::size_t size,
361  off_t file_offset = 0,
362  off_t devPtr_offset = 0,
363  CUstream stream = nullptr);
364 
400  void write_async(void* devPtr_base,
401  std::size_t* size_p,
402  off_t* file_offset_p,
403  off_t* devPtr_offset_p,
404  ssize_t* bytes_written_p,
405  CUstream stream);
406 
432  [[nodiscard]] StreamFuture write_async(void* devPtr_base,
433  std::size_t size,
434  off_t file_offset = 0,
435  off_t devPtr_offset = 0,
436  CUstream stream = nullptr);
437 
446 };
447 
448 } // namespace kvikio
Class that provides RAII for the cuFile handle.
Definition: file_utils.hpp:86
Store and manage the compatibility mode data associated with a FileHandle.
Handle of an open file registered with cufile.
Definition: file_handle.hpp:45
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.
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)
Reads specified bytes from the file into the device or host memory in parallel.
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::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)
Writes specified bytes from device or host memory into the file in parallel.
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.
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.
FileHandle(FileHandle const &)=delete
FileHandle support move semantic but isn't copyable.
Class that provides RAII for file handling.
Definition: file_utils.hpp:27
Future of an asynchronous IO operation.
Definition: stream.hpp:46
Singleton class of default values used throughout KvikIO.
Definition: defaults.hpp:123
static CompatMode compat_mode()
Return whether the KvikIO library is running in compatibility mode or not.
KvikIO namespace.
Definition: batch.hpp:27
CompatMode
I/O compatibility mode.
Definition: compat_mode.hpp:26