summaryrefslogtreecommitdiffstats
path: root/util/system/file.cpp
diff options
context:
space:
mode:
authorkhlebnikov <[email protected]>2022-02-10 16:50:08 +0300
committerDaniil Cherednik <[email protected]>2022-02-10 16:50:08 +0300
commit6cffcf9a14a1dd07278bd534c7cca706ec2827b3 (patch)
tree48eb57e1d9fd00d624ca68bb3418c3c041d1b096 /util/system/file.cpp
parent1977f1c7bcb225f59f789f5f8735e03eb0c87e1c (diff)
Restoring authorship annotation for <[email protected]>. Commit 1 of 2.
Diffstat (limited to 'util/system/file.cpp')
-rw-r--r--util/system/file.cpp694
1 files changed, 347 insertions, 347 deletions
diff --git a/util/system/file.cpp b/util/system/file.cpp
index 4a261d020cb..c0be8759709 100644
--- a/util/system/file.cpp
+++ b/util/system/file.cpp
@@ -2,11 +2,11 @@
#include "flock.h"
#include "fstat.h"
#include "sysstat.h"
-#include "align.h"
+#include "align.h"
#include "info.h"
-#include <array>
-
+#include <array>
+
#include <util/string/util.h>
#include <util/string/cast.h>
#include <util/string/builder.h>
@@ -67,12 +67,12 @@ TFileHandle::TFileHandle(const TString& fName, EOpenMode oMode) noexcept {
ui32 fcMode = 0;
EOpenMode createMode = oMode & MaskCreation;
Y_VERIFY(!IsStupidFlagCombination(oMode), "oMode %d makes no sense", static_cast<int>(oMode));
- if (!(oMode & MaskRW)) {
+ if (!(oMode & MaskRW)) {
oMode |= RdWr;
- }
- if (!(oMode & AMask)) {
+ }
+ if (!(oMode & AMask)) {
oMode |= ARW;
- }
+ }
#ifdef _win_
@@ -98,13 +98,13 @@ TFileHandle::TFileHandle(const TString& fName, EOpenMode oMode) noexcept {
}
ui32 faMode = 0;
- if (oMode & RdOnly) {
+ if (oMode & RdOnly) {
faMode |= GENERIC_READ;
- }
- if (oMode & WrOnly) {
- // WrOnly or RdWr
+ }
+ if (oMode & WrOnly) {
+ // WrOnly or RdWr
faMode |= GENERIC_WRITE;
- }
+ }
if (oMode & ::ForAppend) {
faMode |= GENERIC_WRITE;
faMode |= FILE_APPEND_DATA;
@@ -116,29 +116,29 @@ TFileHandle::TFileHandle(const TString& fName, EOpenMode oMode) noexcept {
ui32 shMode = FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE;
ui32 attrMode = FILE_ATTRIBUTE_NORMAL;
- if ((createMode == OpenExisting || createMode == OpenAlways) && ((oMode & AMask) == (oMode & AR))) {
+ if ((createMode == OpenExisting || createMode == OpenAlways) && ((oMode & AMask) == (oMode & AR))) {
attrMode |= FILE_ATTRIBUTE_READONLY;
- }
- if (oMode & Seq) {
+ }
+ if (oMode & Seq) {
attrMode |= FILE_FLAG_SEQUENTIAL_SCAN;
- }
- if (oMode & Temp) {
- // we use TTempFile instead of FILE_FLAG_DELETE_ON_CLOSE
- attrMode |= FILE_ATTRIBUTE_TEMPORARY;
- }
- if (oMode & Transient) {
+ }
+ if (oMode & Temp) {
+ // we use TTempFile instead of FILE_FLAG_DELETE_ON_CLOSE
+ attrMode |= FILE_ATTRIBUTE_TEMPORARY;
+ }
+ if (oMode & Transient) {
attrMode |= FILE_FLAG_DELETE_ON_CLOSE;
- }
- if ((oMode & (Direct | DirectAligned)) && (oMode & WrOnly)) {
- // WrOnly or RdWr
+ }
+ if ((oMode & (Direct | DirectAligned)) && (oMode & WrOnly)) {
+ // WrOnly or RdWr
attrMode |= /*FILE_FLAG_NO_BUFFERING |*/ FILE_FLAG_WRITE_THROUGH;
- }
+ }
Fd_ = NFsPrivate::CreateFileWithUtf8Name(fName, faMode, shMode, fcMode, attrMode, inheritHandle);
- if ((oMode & ::ForAppend) && (Fd_ != INVALID_FHANDLE)) {
+ if ((oMode & ::ForAppend) && (Fd_ != INVALID_FHANDLE)) {
::SetFilePointer(Fd_, 0, 0, FILE_END);
- }
+ }
#elif defined(_unix_)
@@ -163,13 +163,13 @@ TFileHandle::TFileHandle(const TString& fName, EOpenMode oMode) noexcept {
break;
}
- if ((oMode & RdOnly) && (oMode & WrOnly)) {
+ if ((oMode & RdOnly) && (oMode & WrOnly)) {
fcMode |= O_RDWR;
- } else if (oMode & RdOnly) {
+ } else if (oMode & RdOnly) {
fcMode |= O_RDONLY;
- } else if (oMode & WrOnly) {
+ } else if (oMode & WrOnly) {
fcMode |= O_WRONLY;
- }
+ }
if (oMode & ::ForAppend) {
fcMode |= O_APPEND;
@@ -194,9 +194,9 @@ TFileHandle::TFileHandle(const TString& fName, EOpenMode oMode) noexcept {
#elif defined(_linux_)
if (oMode & DirectAligned) {
/*
- * O_DIRECT in Linux requires aligning request size and buffer address
- * to size of hardware sector (see hw_sector_size or ioctl BLKSSZGET).
- * Usually 512 bytes, but modern hardware works better with 4096 bytes.
+ * O_DIRECT in Linux requires aligning request size and buffer address
+ * to size of hardware sector (see hw_sector_size or ioctl BLKSSZGET).
+ * Usually 512 bytes, but modern hardware works better with 4096 bytes.
*/
fcMode |= O_DIRECT;
}
@@ -210,33 +210,33 @@ TFileHandle::TFileHandle(const TString& fName, EOpenMode oMode) noexcept {
#endif
ui32 permMode = 0;
- if (oMode & AXOther) {
+ if (oMode & AXOther) {
permMode |= S_IXOTH;
- }
- if (oMode & AWOther) {
+ }
+ if (oMode & AWOther) {
permMode |= S_IWOTH;
- }
- if (oMode & AROther) {
+ }
+ if (oMode & AROther) {
permMode |= S_IROTH;
- }
- if (oMode & AXGroup) {
+ }
+ if (oMode & AXGroup) {
permMode |= S_IXGRP;
- }
- if (oMode & AWGroup) {
+ }
+ if (oMode & AWGroup) {
permMode |= S_IWGRP;
- }
- if (oMode & ARGroup) {
+ }
+ if (oMode & ARGroup) {
permMode |= S_IRGRP;
- }
- if (oMode & AXUser) {
+ }
+ if (oMode & AXUser) {
permMode |= S_IXUSR;
- }
- if (oMode & AWUser) {
+ }
+ if (oMode & AWUser) {
permMode |= S_IWUSR;
- }
- if (oMode & ARUser) {
+ }
+ if (oMode & ARUser) {
permMode |= S_IRUSR;
- }
+ }
do {
Fd_ = ::open(fName.data(), fcMode, permMode);
@@ -245,21 +245,21 @@ TFileHandle::TFileHandle(const TString& fName, EOpenMode oMode) noexcept {
#if HAVE_POSIX_FADVISE
if (Fd_ >= 0) {
if (oMode & NoReuse) {
- ::posix_fadvise(Fd_, 0, 0, POSIX_FADV_NOREUSE);
+ ::posix_fadvise(Fd_, 0, 0, POSIX_FADV_NOREUSE);
}
if (oMode & Seq) {
- ::posix_fadvise(Fd_, 0, 0, POSIX_FADV_SEQUENTIAL);
- }
-
- if (oMode & NoReadAhead) {
- ::posix_fadvise(Fd_, 0, 0, POSIX_FADV_RANDOM);
+ ::posix_fadvise(Fd_, 0, 0, POSIX_FADV_SEQUENTIAL);
}
+
+ if (oMode & NoReadAhead) {
+ ::posix_fadvise(Fd_, 0, 0, POSIX_FADV_RANDOM);
+ }
}
#endif
//temp file
- if (Fd_ >= 0 && (oMode & Transient)) {
+ if (Fd_ >= 0 && (oMode & Transient)) {
unlink(fName.data());
}
#else
@@ -270,17 +270,17 @@ TFileHandle::TFileHandle(const TString& fName, EOpenMode oMode) noexcept {
bool TFileHandle::Close() noexcept {
bool isOk = true;
#ifdef _win_
- if (Fd_ != INVALID_FHANDLE) {
+ if (Fd_ != INVALID_FHANDLE) {
isOk = (::CloseHandle(Fd_) != 0);
- }
+ }
if (!isOk) {
Y_VERIFY(GetLastError() != ERROR_INVALID_HANDLE,
"must not quietly close invalid handle");
}
#elif defined(_unix_)
- if (Fd_ != INVALID_FHANDLE) {
+ if (Fd_ != INVALID_FHANDLE) {
isOk = (::close(Fd_) == 0 || errno == EINTR);
- }
+ }
if (!isOk) {
// Do not quietly close bad descriptor,
// because often it means double close
@@ -295,17 +295,17 @@ bool TFileHandle::Close() noexcept {
}
static inline i64 DoSeek(FHANDLE h, i64 offset, SeekDir origin) noexcept {
- if (h == INVALID_FHANDLE) {
+ if (h == INVALID_FHANDLE) {
return -1L;
- }
+ }
#if defined(_win_)
static ui32 dir[] = {FILE_BEGIN, FILE_CURRENT, FILE_END};
LARGE_INTEGER pos;
pos.QuadPart = offset;
pos.LowPart = ::SetFilePointer(h, pos.LowPart, &pos.HighPart, dir[origin]);
- if (pos.LowPart == INVALID_SET_FILE_POINTER && GetLastError() != NO_ERROR) {
+ if (pos.LowPart == INVALID_SET_FILE_POINTER && GetLastError() != NO_ERROR) {
pos.QuadPart = -1;
- }
+ }
return pos.QuadPart;
#elif defined(_unix_)
static int dir[] = {SEEK_SET, SEEK_CUR, SEEK_END};
@@ -329,32 +329,32 @@ i64 TFileHandle::Seek(i64 offset, SeekDir origin) noexcept {
i64 TFileHandle::GetLength() const noexcept {
// XXX: returns error code, but does not set errno
- if (!IsOpen()) {
+ if (!IsOpen()) {
return -1L;
- }
+ }
return GetFileLength(Fd_);
}
bool TFileHandle::Resize(i64 length) noexcept {
- if (!IsOpen()) {
+ if (!IsOpen()) {
return false;
- }
+ }
i64 currentLength = GetLength();
- if (length == currentLength) {
+ if (length == currentLength) {
return true;
- }
+ }
#if defined(_win_)
i64 currentPosition = GetPosition();
- if (currentPosition == -1L) {
+ if (currentPosition == -1L) {
return false;
- }
+ }
Seek(length, sSet);
- if (!::SetEndOfFile(Fd_)) {
+ if (!::SetEndOfFile(Fd_)) {
return false;
- }
- if (currentPosition < length) {
+ }
+ if (currentPosition < length) {
Seek(currentPosition, sSet);
- }
+ }
return true;
#elif defined(_unix_)
return (0 == ftruncate(Fd_, (off_t)length));
@@ -364,17 +364,17 @@ bool TFileHandle::Resize(i64 length) noexcept {
}
bool TFileHandle::Reserve(i64 length) noexcept {
- // FIXME this should reserve disk space with fallocate
- if (!IsOpen()) {
+ // FIXME this should reserve disk space with fallocate
+ if (!IsOpen()) {
return false;
- }
+ }
i64 currentLength = GetLength();
- if (length <= currentLength) {
+ if (length <= currentLength) {
return true;
- }
- if (!Resize(length)) {
+ }
+ if (!Resize(length)) {
return false;
- }
+ }
#if defined(_win_)
if (!::SetFileValidData(Fd_, length)) {
Resize(currentLength);
@@ -413,29 +413,29 @@ bool TFileHandle::ShrinkToFit() noexcept {
}
bool TFileHandle::Flush() noexcept {
- if (!IsOpen()) {
+ if (!IsOpen()) {
return false;
- }
+ }
#if defined(_win_)
bool ok = ::FlushFileBuffers(Fd_) != 0;
- /*
- * FlushFileBuffers fails if hFile is a handle to the console output.
- * That is because the console output is not buffered.
- * The function returns FALSE, and GetLastError returns ERROR_INVALID_HANDLE.
- */
- return ok || GetLastError() == ERROR_INVALID_HANDLE;
+ /*
+ * FlushFileBuffers fails if hFile is a handle to the console output.
+ * That is because the console output is not buffered.
+ * The function returns FALSE, and GetLastError returns ERROR_INVALID_HANDLE.
+ */
+ return ok || GetLastError() == ERROR_INVALID_HANDLE;
#elif defined(_unix_)
int ret = ::fsync(Fd_);
- /*
- * Ignore EROFS, EINVAL - fd is bound to a special file
- * (PIPE, FIFO, or socket) which does not support synchronization.
- * Fail in case of EIO, ENOSPC, EDQUOT - data might be lost.
- */
+ /*
+ * Ignore EROFS, EINVAL - fd is bound to a special file
+ * (PIPE, FIFO, or socket) which does not support synchronization.
+ * Fail in case of EIO, ENOSPC, EDQUOT - data might be lost.
+ */
return ret == 0 || errno == EROFS || errno == EINVAL
#if defined(_darwin_)
- // ENOTSUP fd does not refer to a vnode
- || errno == ENOTSUP
+ // ENOTSUP fd does not refer to a vnode
+ || errno == ENOTSUP
#endif
;
#else
@@ -451,7 +451,7 @@ bool TFileHandle::FlushData() noexcept {
int ret = ::fdatasync(Fd_);
- // Same loginc in error handling as for fsync above.
+ // Same loginc in error handling as for fsync above.
return ret == 0 || errno == EROFS || errno == EINVAL;
#else
return Flush();
@@ -459,21 +459,21 @@ bool TFileHandle::FlushData() noexcept {
}
i32 TFileHandle::Read(void* buffer, ui32 byteCount) noexcept {
- // FIXME size and return must be 64-bit
- if (!IsOpen()) {
+ // FIXME size and return must be 64-bit
+ if (!IsOpen()) {
return -1;
- }
+ }
#if defined(_win_)
DWORD bytesRead = 0;
- if (::ReadFile(Fd_, buffer, byteCount, &bytesRead, nullptr)) {
+ if (::ReadFile(Fd_, buffer, byteCount, &bytesRead, nullptr)) {
return bytesRead;
- }
+ }
return -1;
#elif defined(_unix_)
i32 ret;
- do {
- ret = ::read(Fd_, buffer, byteCount);
- } while (ret == -1 && errno == EINTR);
+ do {
+ ret = ::read(Fd_, buffer, byteCount);
+ } while (ret == -1 && errno == EINTR);
return ret;
#else
#error unsupported platform
@@ -481,20 +481,20 @@ i32 TFileHandle::Read(void* buffer, ui32 byteCount) noexcept {
}
i32 TFileHandle::Write(const void* buffer, ui32 byteCount) noexcept {
- if (!IsOpen()) {
+ if (!IsOpen()) {
return -1;
- }
+ }
#if defined(_win_)
DWORD bytesWritten = 0;
- if (::WriteFile(Fd_, buffer, byteCount, &bytesWritten, nullptr)) {
+ if (::WriteFile(Fd_, buffer, byteCount, &bytesWritten, nullptr)) {
return bytesWritten;
- }
+ }
return -1;
#elif defined(_unix_)
i32 ret;
- do {
- ret = ::write(Fd_, buffer, byteCount);
- } while (ret == -1 && errno == EINTR);
+ do {
+ ret = ::write(Fd_, buffer, byteCount);
+ } while (ret == -1 && errno == EINTR);
return ret;
#else
#error unsupported platform
@@ -508,18 +508,18 @@ i32 TFileHandle::Pread(void* buffer, ui32 byteCount, i64 offset) const noexcept
DWORD bytesRead = 0;
io.Offset = (ui32)offset;
io.OffsetHigh = (ui32)(offset >> 32);
- if (::ReadFile(Fd_, buffer, byteCount, &bytesRead, &io)) {
+ if (::ReadFile(Fd_, buffer, byteCount, &bytesRead, &io)) {
return bytesRead;
- }
- if (::GetLastError() == ERROR_HANDLE_EOF) {
+ }
+ if (::GetLastError() == ERROR_HANDLE_EOF) {
return 0;
- }
+ }
return -1;
#elif defined(_unix_)
i32 ret;
- do {
- ret = ::pread(Fd_, buffer, byteCount, offset);
- } while (ret == -1 && errno == EINTR);
+ do {
+ ret = ::pread(Fd_, buffer, byteCount, offset);
+ } while (ret == -1 && errno == EINTR);
return ret;
#else
#error unsupported platform
@@ -533,15 +533,15 @@ i32 TFileHandle::Pwrite(const void* buffer, ui32 byteCount, i64 offset) const no
DWORD bytesWritten = 0;
io.Offset = (ui32)offset;
io.OffsetHigh = (ui32)(offset >> 32);
- if (::WriteFile(Fd_, buffer, byteCount, &bytesWritten, &io)) {
+ if (::WriteFile(Fd_, buffer, byteCount, &bytesWritten, &io)) {
return bytesWritten;
- }
+ }
return -1;
#elif defined(_unix_)
i32 ret;
- do {
- ret = ::pwrite(Fd_, buffer, byteCount, offset);
- } while (ret == -1 && errno == EINTR);
+ do {
+ ret = ::pwrite(Fd_, buffer, byteCount, offset);
+ } while (ret == -1 && errno == EINTR);
return ret;
#else
#error unsupported platform
@@ -549,14 +549,14 @@ i32 TFileHandle::Pwrite(const void* buffer, ui32 byteCount, i64 offset) const no
}
FHANDLE TFileHandle::Duplicate() const noexcept {
- if (!IsOpen()) {
+ if (!IsOpen()) {
return INVALID_FHANDLE;
- }
+ }
#if defined(_win_)
FHANDLE dupHandle;
- if (!::DuplicateHandle(GetCurrentProcess(), Fd_, GetCurrentProcess(), &dupHandle, 0, TRUE, DUPLICATE_SAME_ACCESS)) {
+ if (!::DuplicateHandle(GetCurrentProcess(), Fd_, GetCurrentProcess(), &dupHandle, 0, TRUE, DUPLICATE_SAME_ACCESS)) {
return INVALID_FHANDLE;
- }
+ }
return dupHandle;
#elif defined(_unix_)
return ::dup(Fd_);
@@ -643,138 +643,138 @@ void TFileHandle::ResetDirect() {
#endif
}
-i64 TFileHandle::CountCache(i64 offset, i64 length) const noexcept {
-#ifdef _linux_
- const i64 pageSize = NSystemInfo::GetPageSize();
+i64 TFileHandle::CountCache(i64 offset, i64 length) const noexcept {
+#ifdef _linux_
+ const i64 pageSize = NSystemInfo::GetPageSize();
constexpr size_t vecSize = 512; // Fetch up to 2MiB at once
- const i64 batchSize = vecSize * pageSize;
- std::array<ui8, vecSize> vec;
- void* ptr = nullptr;
- i64 res = 0;
-
- if (!IsOpen()) {
- return -1;
- }
-
- if (!length) {
- length = GetLength();
- length -= Min(length, offset);
- }
-
- if (!length) {
- return 0;
- }
-
- const i64 begin = AlignDown(offset, pageSize);
- const i64 end = AlignUp(offset + length, pageSize);
- const i64 size = end - begin;
-
- /*
- * Since fincode is not implemented yet use mmap and mincore.
- * This is not so effective and scalable for frequent usage.
- */
- ptr = ::mmap(
- (caddr_t) nullptr,
- size,
- PROT_READ,
- MAP_SHARED | MAP_NORESERVE,
- Fd_,
- begin);
- if (MAP_FAILED == ptr) {
- return -1;
- }
-
- for (i64 base = begin; base < end; base += batchSize) {
- const size_t batch = Min(vecSize, size_t((end - base) / pageSize));
- void* batchPtr = static_cast<caddr_t>(ptr) + (base - begin);
-
- if (::mincore(batchPtr, batch * pageSize, vec.data())) {
- res = -1;
- break;
- }
-
- for (size_t i = 0; i < batch; i++) {
- // count uptodate complete pages in cache
- if (vec[i] & 1) {
- res += pageSize;
- }
- }
-
- if (base == begin && (vec[0] & 1)) {
- // cut head of first page
- res -= offset - begin;
- }
-
- if ((end - base) <= batchSize && (vec[batch - 1] & 1)) {
- // cut tail of last page
- res -= size - (offset - begin) - length;
- }
- }
-
- ::munmap(ptr, size);
-
- return res;
-#else
- Y_UNUSED(offset);
- Y_UNUSED(length);
- return -1;
-#endif
-}
-
-void TFileHandle::PrefetchCache(i64 offset, i64 length, bool wait) const noexcept {
-#ifdef _linux_
+ const i64 batchSize = vecSize * pageSize;
+ std::array<ui8, vecSize> vec;
+ void* ptr = nullptr;
+ i64 res = 0;
+
+ if (!IsOpen()) {
+ return -1;
+ }
+
+ if (!length) {
+ length = GetLength();
+ length -= Min(length, offset);
+ }
+
+ if (!length) {
+ return 0;
+ }
+
+ const i64 begin = AlignDown(offset, pageSize);
+ const i64 end = AlignUp(offset + length, pageSize);
+ const i64 size = end - begin;
+
+ /*
+ * Since fincode is not implemented yet use mmap and mincore.
+ * This is not so effective and scalable for frequent usage.
+ */
+ ptr = ::mmap(
+ (caddr_t) nullptr,
+ size,
+ PROT_READ,
+ MAP_SHARED | MAP_NORESERVE,
+ Fd_,
+ begin);
+ if (MAP_FAILED == ptr) {
+ return -1;
+ }
+
+ for (i64 base = begin; base < end; base += batchSize) {
+ const size_t batch = Min(vecSize, size_t((end - base) / pageSize));
+ void* batchPtr = static_cast<caddr_t>(ptr) + (base - begin);
+
+ if (::mincore(batchPtr, batch * pageSize, vec.data())) {
+ res = -1;
+ break;
+ }
+
+ for (size_t i = 0; i < batch; i++) {
+ // count uptodate complete pages in cache
+ if (vec[i] & 1) {
+ res += pageSize;
+ }
+ }
+
+ if (base == begin && (vec[0] & 1)) {
+ // cut head of first page
+ res -= offset - begin;
+ }
+
+ if ((end - base) <= batchSize && (vec[batch - 1] & 1)) {
+ // cut tail of last page
+ res -= size - (offset - begin) - length;
+ }
+ }
+
+ ::munmap(ptr, size);
+
+ return res;
+#else
+ Y_UNUSED(offset);
+ Y_UNUSED(length);
+ return -1;
+#endif
+}
+
+void TFileHandle::PrefetchCache(i64 offset, i64 length, bool wait) const noexcept {
+#ifdef _linux_
#if HAVE_POSIX_FADVISE
- // POSIX_FADV_WILLNEED starts reading upto read_ahead_kb in background
- ::posix_fadvise(Fd_, offset, length, POSIX_FADV_WILLNEED);
+ // POSIX_FADV_WILLNEED starts reading upto read_ahead_kb in background
+ ::posix_fadvise(Fd_, offset, length, POSIX_FADV_WILLNEED);
#endif
-
- if (wait) {
- TFileHandle devnull("/dev/null", OpenExisting | WrOnly | CloseOnExec);
- off_t end = length ? (offset + length) : GetLength();
- off_t pos = offset;
- ssize_t ret;
-
- do {
- ret = ::sendfile((FHANDLE)devnull, Fd_, &pos, end - pos);
- } while (pos < end && (ret > 0 || errno == EINTR));
- }
-#else
- Y_UNUSED(offset);
- Y_UNUSED(length);
- Y_UNUSED(wait);
-#endif
-}
-
-void TFileHandle::EvictCache(i64 offset, i64 length) const noexcept {
-#if HAVE_POSIX_FADVISE
- /*
- * This tries to evicts only unmaped, clean, complete pages.
- */
- ::posix_fadvise(Fd_, offset, length, POSIX_FADV_DONTNEED);
-#else
- Y_UNUSED(offset);
- Y_UNUSED(length);
-#endif
-}
-
-bool TFileHandle::FlushCache(i64 offset, i64 length, bool wait) noexcept {
-#if HAVE_SYNC_FILE_RANGE
- int flags = SYNC_FILE_RANGE_WRITE;
- if (wait) {
- flags |= SYNC_FILE_RANGE_WAIT_AFTER;
- }
- int ret = ::sync_file_range(Fd_, offset, length, flags);
- return ret == 0 || errno == EROFS;
-#else
- Y_UNUSED(offset);
- Y_UNUSED(length);
- if (wait) {
- return FlushData();
- }
- return true;
-#endif
-}
-
+
+ if (wait) {
+ TFileHandle devnull("/dev/null", OpenExisting | WrOnly | CloseOnExec);
+ off_t end = length ? (offset + length) : GetLength();
+ off_t pos = offset;
+ ssize_t ret;
+
+ do {
+ ret = ::sendfile((FHANDLE)devnull, Fd_, &pos, end - pos);
+ } while (pos < end && (ret > 0 || errno == EINTR));
+ }
+#else
+ Y_UNUSED(offset);
+ Y_UNUSED(length);
+ Y_UNUSED(wait);
+#endif
+}
+
+void TFileHandle::EvictCache(i64 offset, i64 length) const noexcept {
+#if HAVE_POSIX_FADVISE
+ /*
+ * This tries to evicts only unmaped, clean, complete pages.
+ */
+ ::posix_fadvise(Fd_, offset, length, POSIX_FADV_DONTNEED);
+#else
+ Y_UNUSED(offset);
+ Y_UNUSED(length);
+#endif
+}
+
+bool TFileHandle::FlushCache(i64 offset, i64 length, bool wait) noexcept {
+#if HAVE_SYNC_FILE_RANGE
+ int flags = SYNC_FILE_RANGE_WRITE;
+ if (wait) {
+ flags |= SYNC_FILE_RANGE_WAIT_AFTER;
+ }
+ int ret = ::sync_file_range(Fd_, offset, length, flags);
+ return ret == 0 || errno == EROFS;
+#else
+ Y_UNUSED(offset);
+ Y_UNUSED(length);
+ if (wait) {
+ return FlushData();
+ }
+ return true;
+#endif
+}
+
TString DecodeOpenMode(ui32 mode0) {
ui32 mode = mode0;
@@ -790,25 +790,25 @@ TString DecodeOpenMode(ui32 mode0) {
}
F(RdWr)
- F(RdOnly)
- F(WrOnly)
-
- F(CreateAlways)
+ F(RdOnly)
+ F(WrOnly)
+
+ F(CreateAlways)
F(CreateNew)
- F(OpenAlways)
- F(TruncExisting)
- F(ForAppend)
- F(Transient)
- F(CloseOnExec)
-
- F(Temp)
- F(Sync)
- F(Direct)
- F(DirectAligned)
- F(Seq)
- F(NoReuse)
- F(NoReadAhead)
-
+ F(OpenAlways)
+ F(TruncExisting)
+ F(ForAppend)
+ F(Transient)
+ F(CloseOnExec)
+
+ F(Temp)
+ F(Sync)
+ F(Direct)
+ F(DirectAligned)
+ F(Seq)
+ F(NoReuse)
+ F(NoReadAhead)
+
F(AX)
F(AR)
F(AW)
@@ -861,9 +861,9 @@ public:
inline ~TImpl() = default;
inline void Close() {
- if (!Handle_.Close()) {
+ if (!Handle_.Close()) {
ythrow TFileError() << "can't close " << FileName_.Quote();
- }
+ }
}
const TString& GetName() const noexcept {
@@ -880,22 +880,22 @@ public:
i64 Seek(i64 offset, SeekDir origin) {
i64 pos = Handle_.Seek(offset, origin);
- if (pos == -1L) {
+ if (pos == -1L) {
ythrow TFileError() << "can't seek " << offset << " bytes in " << FileName_.Quote();
- }
+ }
return pos;
}
void Resize(i64 length) {
- if (!Handle_.Resize(length)) {
+ if (!Handle_.Resize(length)) {
ythrow TFileError() << "can't resize " << FileName_.Quote() << " to size " << length;
- }
+ }
}
void Reserve(i64 length) {
- if (!Handle_.Reserve(length)) {
+ if (!Handle_.Reserve(length)) {
ythrow TFileError() << "can't reserve " << length << " for file " << FileName_.Quote();
- }
+ }
}
void FallocateNoResize(i64 length) {
@@ -911,22 +911,22 @@ public:
}
void Flush() {
- if (!Handle_.Flush()) {
+ if (!Handle_.Flush()) {
ythrow TFileError() << "can't flush " << FileName_.Quote();
- }
+ }
}
void FlushData() {
- if (!Handle_.FlushData()) {
+ if (!Handle_.FlushData()) {
ythrow TFileError() << "can't flush data " << FileName_.Quote();
- }
+ }
}
TFile Duplicate() const {
TFileHandle dupH(Handle_.Duplicate());
- if (!dupH.IsOpen()) {
+ if (!dupH.IsOpen()) {
ythrow TFileError() << "can't duplicate the handle of " << FileName_.Quote();
- }
+ }
TFile res(dupH);
dupH.Release();
return res;
@@ -958,10 +958,10 @@ public:
while (numBytes) {
const size_t reallyRead = ReadOrFail(buf, numBytes);
- if (reallyRead == 0) {
- // file exhausted
+ if (reallyRead == 0) {
+ // file exhausted
break;
- }
+ }
buf += reallyRead;
numBytes -= reallyRead;
@@ -971,9 +971,9 @@ public:
}
void Load(void* buf, size_t len) {
- if (Read(buf, len) != len) {
+ if (Read(buf, len) != len) {
ythrow TFileError() << "can't read " << len << " bytes from " << FileName_.Quote();
- }
+ }
}
// Maximum amount of bytes to be written via single system call.
@@ -988,9 +988,9 @@ public:
const i32 toWrite = (i32)Min(MaxWritePortion, numBytes);
const i32 reallyWritten = Handle_.Write(buf, toWrite);
- if (reallyWritten < 0) {
+ if (reallyWritten < 0) {
ythrow TFileError() << "can't write " << toWrite << " bytes to " << FileName_.Quote();
- }
+ }
buf += reallyWritten;
numBytes -= reallyWritten;
@@ -1004,14 +1004,14 @@ public:
const i32 toRead = (i32)Min(MaxReadPortion, numBytes);
const i32 reallyRead = RawPread(buf, toRead, offset);
- if (reallyRead < 0) {
+ if (reallyRead < 0) {
ythrow TFileError() << "can not read data from " << FileName_.Quote();
- }
+ }
- if (reallyRead == 0) {
- // file exausted
+ if (reallyRead == 0) {
+ // file exausted
break;
- }
+ }
buf += reallyRead;
offset += reallyRead;
@@ -1026,9 +1026,9 @@ public:
}
void Pload(void* buf, size_t len, i64 offset) const {
- if (Pread(buf, len, offset) != len) {
+ if (Pread(buf, len, offset) != len) {
ythrow TFileError() << "can't read " << len << " bytes at offset " << offset << " from " << FileName_.Quote();
- }
+ }
}
void Pwrite(const void* buffer, size_t numBytes, i64 offset) const {
@@ -1038,9 +1038,9 @@ public:
const i32 toWrite = (i32)Min(MaxWritePortion, numBytes);
const i32 reallyWritten = Handle_.Pwrite(buf, toWrite, offset);
- if (reallyWritten < 0) {
+ if (reallyWritten < 0) {
ythrow TFileError() << "can't write " << toWrite << " bytes to " << FileName_.Quote();
- }
+ }
buf += reallyWritten;
offset += reallyWritten;
@@ -1064,24 +1064,24 @@ public:
Handle_.ResetDirect();
}
- i64 CountCache(i64 offset, i64 length) const noexcept {
- return Handle_.CountCache(offset, length);
- }
-
- void PrefetchCache(i64 offset, i64 length, bool wait) const noexcept {
- Handle_.PrefetchCache(offset, length, wait);
- }
-
- void EvictCache(i64 offset, i64 length) const noexcept {
- Handle_.EvictCache(offset, length);
- }
-
- void FlushCache(i64 offset, i64 length, bool wait) {
- if (!Handle_.FlushCache(offset, length, wait)) {
- ythrow TFileError() << "can't flush data " << FileName_.Quote();
- }
- }
-
+ i64 CountCache(i64 offset, i64 length) const noexcept {
+ return Handle_.CountCache(offset, length);
+ }
+
+ void PrefetchCache(i64 offset, i64 length, bool wait) const noexcept {
+ Handle_.PrefetchCache(offset, length, wait);
+ }
+
+ void EvictCache(i64 offset, i64 length) const noexcept {
+ Handle_.EvictCache(offset, length);
+ }
+
+ void FlushCache(i64 offset, i64 length, bool wait) {
+ if (!Handle_.FlushCache(offset, length, wait)) {
+ ythrow TFileError() << "can't flush data " << FileName_.Quote();
+ }
+ }
+
private:
TFileHandle Handle_;
TString FileName_;
@@ -1215,22 +1215,22 @@ void TFile::ResetDirect() {
Impl_->ResetDirect();
}
-i64 TFile::CountCache(i64 offset, i64 length) const noexcept {
- return Impl_->CountCache(offset, length);
-}
-
-void TFile::PrefetchCache(i64 offset, i64 length, bool wait) const noexcept {
- Impl_->PrefetchCache(offset, length, wait);
-}
-
-void TFile::EvictCache(i64 offset, i64 length) const noexcept {
- Impl_->EvictCache(offset, length);
-}
-
-void TFile::FlushCache(i64 offset, i64 length, bool wait) {
- Impl_->FlushCache(offset, length, wait);
-}
-
+i64 TFile::CountCache(i64 offset, i64 length) const noexcept {
+ return Impl_->CountCache(offset, length);
+}
+
+void TFile::PrefetchCache(i64 offset, i64 length, bool wait) const noexcept {
+ Impl_->PrefetchCache(offset, length, wait);
+}
+
+void TFile::EvictCache(i64 offset, i64 length) const noexcept {
+ Impl_->EvictCache(offset, length);
+}
+
+void TFile::FlushCache(i64 offset, i64 length, bool wait) {
+ Impl_->FlushCache(offset, length, wait);
+}
+
void TFile::LinkTo(const TFile& f) const {
if (!Impl_->GetHandle().LinkTo(f.Impl_->GetHandle())) {
ythrow TFileError() << "can not link fd(" << GetName() << " -> " << f.GetName() << ")";
@@ -1271,9 +1271,9 @@ TFile Duplicate(int fd) {
FHANDLE handle = reinterpret_cast<FHANDLE>(::_get_osfhandle(fd));
FHANDLE dupHandle;
- if (!::DuplicateHandle(GetCurrentProcess(), handle, GetCurrentProcess(), &dupHandle, 0, TRUE, DUPLICATE_SAME_ACCESS)) {
+ if (!::DuplicateHandle(GetCurrentProcess(), handle, GetCurrentProcess(), &dupHandle, 0, TRUE, DUPLICATE_SAME_ACCESS)) {
ythrow TFileError() << "can not duplicate file descriptor " << LastSystemError() << Endl;
- }
+ }
return TFile(dupHandle);
#elif defined(_unix_)
@@ -1292,7 +1292,7 @@ bool PosixDisableReadAhead(FHANDLE fileHandle, void* addr) noexcept {
ret = madvise(addr, 0, MADV_RANDOM); // according to klamm@ posix_fadvise does not work under linux, madvise does work
#else
Y_UNUSED(addr);
- ret = ::posix_fadvise(fileHandle, 0, 0, POSIX_FADV_RANDOM);
+ ret = ::posix_fadvise(fileHandle, 0, 0, POSIX_FADV_RANDOM);
#endif
#else
Y_UNUSED(fileHandle);