file.h 8.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236
  1. #pragma once
  2. #include "fhandle.h"
  3. #include "flock.h"
  4. #include <util/generic/flags.h>
  5. #include <util/generic/fwd.h>
  6. #include <util/generic/ptr.h>
  7. #include <util/generic/noncopyable.h>
  8. #include <cstdio>
  9. enum EOpenModeFlag {
  10. OpenExisting = 0, // Opens a file. It fails if the file does not exist.
  11. TruncExisting = 1, // Opens a file and truncates it to zero size. It fails if the file does not exist.
  12. OpenAlways = 2, // Opens a file, always. If a file does not exist, it creates a file.
  13. CreateNew = 3, // Creates a new file. It fails if a specified file exists.
  14. CreateAlways = 4, // Creates a new file, always. If a file exists, it overwrites the file.
  15. MaskCreation = 7,
  16. RdOnly = 8, // open for reading only
  17. WrOnly = 16, // open for writing only
  18. RdWr = 24, // open for reading and writing
  19. MaskRW = 24,
  20. Seq = 0x20, // file access is primarily sequential (POSIX_FADV_SEQUENTIAL)
  21. Direct = 0x40, // file is being opened with no system caching (Does not work as intended! See implementation)
  22. Temp = 0x80, // avoid writing data back to disk if sufficient cache memory is available (no op for linux)
  23. ForAppend = 0x100, // write appends data to the end of file (O_APPEND)
  24. Transient = 0x200, // actually, temporary file - 'delete on close' for windows, unlink after creation for unix
  25. NoReuse = 0x400, // no second access expected (POSIX_FADV_NOREUSE)
  26. CloseOnExec = 0x800, // set close-on-exec right at open (O_CLOEXEC)
  27. DirectAligned = 0x1000, // file is actually being opened with no system caching (may require buffer alignment) (O_DIRECT)
  28. Sync = 0x2000, // no write call will return before the data is transferred to the disk (O_SYNC)
  29. NoReadAhead = 0x4000, // no sequential access expected, opposite for Seq (POSIX_FADV_RANDOM)
  30. AXOther = 0x00010000,
  31. AWOther = 0x00020000,
  32. AROther = 0x00040000,
  33. AXGroup = 0x00100000,
  34. AWGroup = 0x00200000,
  35. ARGroup = 0x00400000,
  36. AXUser = 0x01000000,
  37. AWUser = 0x02000000,
  38. ARUser = 0x04000000,
  39. AX = AXUser | AXGroup | AXOther,
  40. AW = AWUser | AWGroup,
  41. AR = ARUser | ARGroup | AROther,
  42. ARW = AR | AW,
  43. AMask = 0x0FFF0000,
  44. };
  45. Y_DECLARE_FLAGS(EOpenMode, EOpenModeFlag);
  46. Y_DECLARE_OPERATORS_FOR_FLAGS(EOpenMode);
  47. TString DecodeOpenMode(ui32 openMode);
  48. enum SeekDir {
  49. sSet = 0,
  50. sCur = 1,
  51. sEnd = 2,
  52. };
  53. class TFileHandle: TMoveOnly {
  54. public:
  55. constexpr TFileHandle() = default;
  56. /// Warning: takes ownership of fd, so closes it in destructor.
  57. inline TFileHandle(FHANDLE fd) noexcept
  58. : Fd_(fd)
  59. {
  60. }
  61. inline TFileHandle(TFileHandle&& other) noexcept
  62. : Fd_(other.Fd_)
  63. {
  64. other.Fd_ = INVALID_FHANDLE;
  65. }
  66. TFileHandle(const char* fName, EOpenMode oMode) noexcept;
  67. TFileHandle(const TString& fName, EOpenMode oMode) noexcept;
  68. TFileHandle(const std::filesystem::path& path, EOpenMode oMode) noexcept;
  69. inline ~TFileHandle() {
  70. Close();
  71. }
  72. TFileHandle& operator=(TFileHandle&& other) noexcept {
  73. Close();
  74. Fd_ = other.Release();
  75. return *this;
  76. }
  77. bool Close() noexcept;
  78. inline FHANDLE Release() noexcept {
  79. FHANDLE ret = Fd_;
  80. Fd_ = INVALID_FHANDLE;
  81. return ret;
  82. }
  83. inline void Swap(TFileHandle& r) noexcept {
  84. DoSwap(Fd_, r.Fd_);
  85. }
  86. inline operator FHANDLE() const noexcept {
  87. return Fd_;
  88. }
  89. inline bool IsOpen() const noexcept {
  90. return Fd_ != INVALID_FHANDLE;
  91. }
  92. i64 GetPosition() const noexcept;
  93. i64 GetLength() const noexcept;
  94. i64 Seek(i64 offset, SeekDir origin) noexcept;
  95. bool Resize(i64 length) noexcept;
  96. bool Reserve(i64 length) noexcept;
  97. bool FallocateNoResize(i64 length) noexcept;
  98. bool ShrinkToFit() noexcept;
  99. bool Flush() noexcept;
  100. // flush data only, without file metadata
  101. bool FlushData() noexcept;
  102. i32 Read(void* buffer, ui32 byteCount) noexcept;
  103. i32 Write(const void* buffer, ui32 byteCount) noexcept;
  104. i32 Pread(void* buffer, ui32 byteCount, i64 offset) const noexcept;
  105. i32 Pwrite(const void* buffer, ui32 byteCount, i64 offset) const noexcept;
  106. int Flock(int op) noexcept;
  107. FHANDLE Duplicate() const noexcept;
  108. int Duplicate2Posix(int dstHandle) const noexcept;
  109. // dup2 - like semantics, return true on success
  110. bool LinkTo(const TFileHandle& fh) const noexcept;
  111. // very low-level methods
  112. bool SetDirect();
  113. void ResetDirect();
  114. /* Manual file cache management, length = 0 means "as much as possible" */
  115. // measure amount of cached data in bytes, returns -1 if failed
  116. i64 CountCache(i64 offset = 0, i64 length = 0) const noexcept;
  117. // read data into cache and optionally wait for completion
  118. void PrefetchCache(i64 offset = 0, i64 length = 0, bool wait = true) const noexcept;
  119. // remove clean and unused data from cache
  120. void EvictCache(i64 offset = 0, i64 length = 0) const noexcept;
  121. // flush unwritten data in this range and optionally wait for completion
  122. bool FlushCache(i64 offset = 0, i64 length = 0, bool wait = true) noexcept;
  123. private:
  124. FHANDLE Fd_ = INVALID_FHANDLE;
  125. };
  126. class TFile {
  127. public:
  128. TFile();
  129. /// Takes ownership of handle, so closes it when the last holder of descriptor dies.
  130. explicit TFile(FHANDLE fd);
  131. TFile(FHANDLE fd, const TString& fname);
  132. TFile(const char* fName, EOpenMode oMode);
  133. TFile(const TString& fName, EOpenMode oMode);
  134. TFile(const std::filesystem::path& path, EOpenMode oMode);
  135. ~TFile();
  136. void Close();
  137. const TString& GetName() const noexcept;
  138. i64 GetPosition() const noexcept;
  139. i64 GetLength() const noexcept;
  140. bool IsOpen() const noexcept;
  141. FHANDLE GetHandle() const noexcept;
  142. i64 Seek(i64 offset, SeekDir origin);
  143. void Resize(i64 length);
  144. void Reserve(i64 length);
  145. void FallocateNoResize(i64 length);
  146. void ShrinkToFit();
  147. void Flush();
  148. void FlushData();
  149. void LinkTo(const TFile& f) const;
  150. TFile Duplicate() const;
  151. // Reads up to 1 GB without retrying, returns -1 on error
  152. i32 RawRead(void* buf, size_t len);
  153. // Reads up to 1 GB without retrying, throws on error
  154. size_t ReadOrFail(void* buf, size_t len);
  155. // Retries incomplete reads until EOF, throws on error
  156. size_t Read(void* buf, size_t len);
  157. // Reads exactly len bytes, throws on premature EOF or error
  158. void Load(void* buf, size_t len);
  159. // Retries incomplete writes, will either write len bytes or throw
  160. void Write(const void* buf, size_t len);
  161. // Retries incomplete reads until EOF, throws on error
  162. size_t Pread(void* buf, size_t len, i64 offset) const;
  163. // Single pread call
  164. i32 RawPread(void* buf, ui32 len, i64 offset) const;
  165. // Reads exactly len bytes, throws on premature EOF or error
  166. void Pload(void* buf, size_t len, i64 offset) const;
  167. // Retries incomplete writes, will either write len bytes or throw
  168. void Pwrite(const void* buf, size_t len, i64 offset) const;
  169. void Flock(int op);
  170. // do not use, their meaning very platform-dependant
  171. void SetDirect();
  172. void ResetDirect();
  173. /* Manual file cache management, length = 0 means "as much as possible" */
  174. // measure amount of cached data in bytes, returns -1 if failed
  175. i64 CountCache(i64 offset = 0, i64 length = 0) const noexcept;
  176. // read data into cache and optionally wait for completion
  177. void PrefetchCache(i64 offset = 0, i64 length = 0, bool wait = true) const noexcept;
  178. // remove clean and unused data from cache, incomplete pages could stay
  179. void EvictCache(i64 offset = 0, i64 length = 0) const noexcept;
  180. // flush unwritten data in this range and optionally wait for completion
  181. void FlushCache(i64 offset = 0, i64 length = 0, bool wait = true);
  182. static TFile Temporary(const TString& prefix);
  183. static TFile ForAppend(const TString& path);
  184. private:
  185. class TImpl;
  186. TSimpleIntrusivePtr<TImpl> Impl_;
  187. };
  188. TFile Duplicate(FILE*);
  189. TFile Duplicate(int);
  190. bool PosixDisableReadAhead(FHANDLE fileHandle, void* addr) noexcept;