#include "port/win/io_win.h"
+#include "env_win.h"
#include "monitoring/iostats_context_imp.h"
#include "test_util/sync_point.h"
#include "util/aligned_buffer.h"
namespace port {
/*
-* DirectIOHelper
-*/
+ * DirectIOHelper
+ */
namespace {
const size_t kSectorSize = 512;
-inline
-bool IsPowerOfTwo(const size_t alignment) {
+inline bool IsPowerOfTwo(const size_t alignment) {
return ((alignment) & (alignment - 1)) == 0;
}
-inline
-bool IsSectorAligned(const size_t off) {
- return (off & (kSectorSize - 1)) == 0;
-}
-
-inline
-bool IsAligned(size_t alignment, const void* ptr) {
+inline bool IsAligned(size_t alignment, const void* ptr) {
return ((uintptr_t(ptr)) & (alignment - 1)) == 0;
}
-}
-
+} // namespace
std::string GetWindowsErrSz(DWORD err) {
- LPSTR lpMsgBuf;
+ std::string Err;
+ LPSTR lpMsgBuf = nullptr;
FormatMessageA(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM |
- FORMAT_MESSAGE_IGNORE_INSERTS,
- NULL, err,
- 0, // Default language
- reinterpret_cast<LPSTR>(&lpMsgBuf), 0, NULL);
-
- std::string Err = lpMsgBuf;
- LocalFree(lpMsgBuf);
+ FORMAT_MESSAGE_IGNORE_INSERTS,
+ NULL, err,
+ 0, // Default language
+ reinterpret_cast<LPSTR>(&lpMsgBuf), 0, NULL);
+
+ if (lpMsgBuf) {
+ Err = lpMsgBuf;
+ LocalFree(lpMsgBuf);
+ }
return Err;
}
// Because all the reads/writes happen by the specified offset, the caller in
// theory should not
// rely on the current file offset.
-Status pwrite(const WinFileData* file_data, const Slice& data,
- uint64_t offset, size_t& bytes_written) {
-
- Status s;
+IOStatus pwrite(const WinFileData* file_data, const Slice& data,
+ uint64_t offset, size_t& bytes_written) {
+ IOStatus s;
bytes_written = 0;
size_t num_bytes = data.size();
if (num_bytes > std::numeric_limits<DWORD>::max()) {
// May happen in 64-bit builds where size_t is 64-bits but
// long is still 32-bit, but that's the API here at the moment
- return Status::InvalidArgument("num_bytes is too large for a single write: " +
- file_data->GetName());
+ return IOStatus::InvalidArgument(
+ "num_bytes is too large for a single write: " + file_data->GetName());
}
- OVERLAPPED overlapped = { 0 };
+ OVERLAPPED overlapped = {0};
ULARGE_INTEGER offsetUnion;
offsetUnion.QuadPart = offset;
DWORD bytesWritten = 0;
- if (FALSE == WriteFile(file_data->GetFileHandle(), data.data(), static_cast<DWORD>(num_bytes),
- &bytesWritten, &overlapped)) {
+ if (FALSE == WriteFile(file_data->GetFileHandle(), data.data(),
+ static_cast<DWORD>(num_bytes), &bytesWritten,
+ &overlapped)) {
auto lastError = GetLastError();
s = IOErrorFromWindowsError("WriteFile failed: " + file_data->GetName(),
- lastError);
+ lastError);
} else {
bytes_written = bytesWritten;
}
}
// See comments for pwrite above
-Status pread(const WinFileData* file_data, char* src, size_t num_bytes,
- uint64_t offset, size_t& bytes_read) {
-
- Status s;
+IOStatus pread(const WinFileData* file_data, char* src, size_t num_bytes,
+ uint64_t offset, size_t& bytes_read) {
+ IOStatus s;
bytes_read = 0;
if (num_bytes > std::numeric_limits<DWORD>::max()) {
- return Status::InvalidArgument("num_bytes is too large for a single read: " +
- file_data->GetName());
+ return IOStatus::InvalidArgument(
+ "num_bytes is too large for a single read: " + file_data->GetName());
}
- OVERLAPPED overlapped = { 0 };
+ OVERLAPPED overlapped = {0};
ULARGE_INTEGER offsetUnion;
offsetUnion.QuadPart = offset;
DWORD bytesRead = 0;
- if (FALSE == ReadFile(file_data->GetFileHandle(), src, static_cast<DWORD>(num_bytes),
- &bytesRead, &overlapped)) {
+ if (FALSE == ReadFile(file_data->GetFileHandle(), src,
+ static_cast<DWORD>(num_bytes), &bytesRead,
+ &overlapped)) {
auto lastError = GetLastError();
// EOF is OK with zero bytes read
if (lastError != ERROR_HANDLE_EOF) {
s = IOErrorFromWindowsError("ReadFile failed: " + file_data->GetName(),
- lastError);
+ lastError);
}
} else {
bytes_read = bytesRead;
// SetFileInformationByHandle() is capable of fast pre-allocates.
// However, this does not change the file end position unless the file is
// truncated and the pre-allocated space is not considered filled with zeros.
-Status fallocate(const std::string& filename, HANDLE hFile,
- uint64_t to_size) {
- Status status;
+IOStatus fallocate(const std::string& filename, HANDLE hFile,
+ uint64_t to_size) {
+ IOStatus status;
FILE_ALLOCATION_INFO alloc_info;
alloc_info.AllocationSize.QuadPart = to_size;
if (!SetFileInformationByHandle(hFile, FileAllocationInfo, &alloc_info,
- sizeof(FILE_ALLOCATION_INFO))) {
+ sizeof(FILE_ALLOCATION_INFO))) {
auto lastError = GetLastError();
status = IOErrorFromWindowsError(
- "Failed to pre-allocate space: " + filename, lastError);
+ "Failed to pre-allocate space: " + filename, lastError);
}
return status;
}
-Status ftruncate(const std::string& filename, HANDLE hFile,
- uint64_t toSize) {
- Status status;
+IOStatus ftruncate(const std::string& filename, HANDLE hFile, uint64_t toSize) {
+ IOStatus status;
FILE_END_OF_FILE_INFO end_of_file;
end_of_file.EndOfFile.QuadPart = toSize;
if (!SetFileInformationByHandle(hFile, FileEndOfFileInfo, &end_of_file,
- sizeof(FILE_END_OF_FILE_INFO))) {
+ sizeof(FILE_END_OF_FILE_INFO))) {
auto lastError = GetLastError();
status = IOErrorFromWindowsError("Failed to Set end of file: " + filename,
- lastError);
+ lastError);
}
return status;
return 0;
}
+WinFileData::WinFileData(const std::string& filename, HANDLE hFile,
+ bool direct_io)
+ : filename_(filename),
+ hFile_(hFile),
+ use_direct_io_(direct_io),
+ sector_size_(WinFileSystem::GetSectorSize(filename)) {}
+
+bool WinFileData::IsSectorAligned(const size_t off) const {
+ return (off & (sector_size_ - 1)) == 0;
+}
+
////////////////////////////////////////////////////////////////////////////////////////////////////
// WinMmapReadableFile
assert(ret);
}
-Status WinMmapReadableFile::Read(uint64_t offset, size_t n, Slice* result,
- char* scratch) const {
- Status s;
+IOStatus WinMmapReadableFile::Read(uint64_t offset, size_t n,
+ const IOOptions& /*options*/, Slice* result,
+ char* scratch,
+ IODebugContext* /*dbg*/) const {
+ IOStatus s;
if (offset > length_) {
*result = Slice();
} else if (offset + n > length_) {
n = length_ - static_cast<size_t>(offset);
}
- *result =
- Slice(reinterpret_cast<const char*>(mapped_region_)+offset, n);
+ *result = Slice(reinterpret_cast<const char*>(mapped_region_) + offset, n);
return s;
}
-Status WinMmapReadableFile::InvalidateCache(size_t offset, size_t length) {
- return Status::OK();
+IOStatus WinMmapReadableFile::InvalidateCache(size_t offset, size_t length) {
+ return IOStatus::OK();
}
size_t WinMmapReadableFile::GetUniqueId(char* id, size_t max_size) const {
///////////////////////////////////////////////////////////////////////////////
/// WinMmapFile
-
// Can only truncate or reserve to a sector size aligned if
// used on files that are opened with Unbuffered I/O
-Status WinMmapFile::TruncateFile(uint64_t toSize) {
+IOStatus WinMmapFile::TruncateFile(uint64_t toSize) {
return ftruncate(filename_, hFile_, toSize);
}
-Status WinMmapFile::UnmapCurrentRegion() {
- Status status;
+IOStatus WinMmapFile::UnmapCurrentRegion() {
+ IOStatus status;
if (mapped_begin_ != nullptr) {
if (!::UnmapViewOfFile(mapped_begin_)) {
status = IOErrorFromWindowsError(
- "Failed to unmap file view: " + filename_, GetLastError());
+ "Failed to unmap file view: " + filename_, GetLastError());
}
// Move on to the next portion of the file
return status;
}
-Status WinMmapFile::MapNewRegion() {
-
- Status status;
+IOStatus WinMmapFile::MapNewRegion(const IOOptions& options,
+ IODebugContext* dbg) {
+ IOStatus status;
assert(mapped_begin_ == nullptr);
size_t minDiskSize = static_cast<size_t>(file_offset_) + view_size_;
if (minDiskSize > reserved_size_) {
- status = Allocate(file_offset_, view_size_);
+ status = Allocate(file_offset_, view_size_, options, dbg);
if (!status.ok()) {
return status;
}
// Need to remap
if (hMap_ == NULL || reserved_size_ > mapping_size_) {
-
if (hMap_ != NULL) {
// Unmap the previous one
BOOL ret __attribute__((__unused__));
mappingSize.QuadPart = reserved_size_;
hMap_ = CreateFileMappingA(
- hFile_,
- NULL, // Security attributes
- PAGE_READWRITE, // There is not a write only mode for mapping
- mappingSize.HighPart, // Enable mapping the whole file but the actual
- // amount mapped is determined by MapViewOfFile
- mappingSize.LowPart,
- NULL); // Mapping name
+ hFile_,
+ NULL, // Security attributes
+ PAGE_READWRITE, // There is not a write only mode for mapping
+ mappingSize.HighPart, // Enable mapping the whole file but the actual
+ // amount mapped is determined by MapViewOfFile
+ mappingSize.LowPart,
+ NULL); // Mapping name
if (NULL == hMap_) {
return IOErrorFromWindowsError(
- "WindowsMmapFile failed to create file mapping for: " + filename_,
- GetLastError());
+ "WindowsMmapFile failed to create file mapping for: " + filename_,
+ GetLastError());
}
mapping_size_ = reserved_size_;
// View must begin at the granularity aligned offset
mapped_begin_ = reinterpret_cast<char*>(
- MapViewOfFileEx(hMap_, FILE_MAP_WRITE, offset.HighPart, offset.LowPart,
- view_size_, NULL));
+ MapViewOfFileEx(hMap_, FILE_MAP_WRITE, offset.HighPart, offset.LowPart,
+ view_size_, NULL));
if (!mapped_begin_) {
status = IOErrorFromWindowsError(
- "WindowsMmapFile failed to map file view: " + filename_,
- GetLastError());
+ "WindowsMmapFile failed to map file view: " + filename_,
+ GetLastError());
} else {
mapped_end_ = mapped_begin_ + view_size_;
dst_ = mapped_begin_;
return status;
}
-Status WinMmapFile::PreallocateInternal(uint64_t spaceToReserve) {
+IOStatus WinMmapFile::PreallocateInternal(uint64_t spaceToReserve) {
return fallocate(filename_, hFile_, spaceToReserve);
}
WinMmapFile::WinMmapFile(const std::string& fname, HANDLE hFile,
size_t page_size, size_t allocation_granularity,
- const EnvOptions& options)
+ const FileOptions& options)
: WinFileData(fname, hFile, false),
- WritableFile(options),
+ FSWritableFile(options),
hMap_(NULL),
page_size_(page_size),
allocation_granularity_(allocation_granularity),
// View size must be both the multiple of allocation_granularity AND the
// page size and the granularity is usually a multiple of a page size.
- const size_t viewSize = 32 * 1024; // 32Kb similar to the Windows File Cache in buffered mode
+ const size_t viewSize =
+ 32 * 1024; // 32Kb similar to the Windows File Cache in buffered mode
view_size_ = Roundup(viewSize, allocation_granularity_);
}
WinMmapFile::~WinMmapFile() {
if (hFile_) {
- this->Close();
+ this->Close(IOOptions(), nullptr);
}
}
-Status WinMmapFile::Append(const Slice& data) {
+IOStatus WinMmapFile::Append(const Slice& data, const IOOptions& options,
+ IODebugContext* dbg) {
const char* src = data.data();
size_t left = data.size();
size_t avail = mapped_end_ - dst_;
if (avail == 0) {
- Status s = UnmapCurrentRegion();
+ IOStatus s = UnmapCurrentRegion();
if (s.ok()) {
- s = MapNewRegion();
+ s = MapNewRegion(options, dbg);
}
if (!s.ok()) {
memset(dst_, 0, bytesToPad);
}
- return Status::OK();
+ return IOStatus::OK();
}
// Means Close() will properly take care of truncate
// and it does not need any additional information
-Status WinMmapFile::Truncate(uint64_t size) {
- return Status::OK();
+IOStatus WinMmapFile::Truncate(uint64_t size, const IOOptions& /*options*/,
+ IODebugContext* /*dbg*/) {
+ return IOStatus::OK();
}
-Status WinMmapFile::Close() {
- Status s;
+IOStatus WinMmapFile::Close(const IOOptions& options, IODebugContext* dbg) {
+ IOStatus s;
assert(NULL != hFile_);
// We truncate to the precise size so no
// uninitialized data at the end. SetEndOfFile
// which we use does not write zeros and it is good.
- uint64_t targetSize = GetFileSize();
+ uint64_t targetSize = GetFileSize(options, dbg);
if (mapped_begin_ != nullptr) {
// Sync before unmapping to make sure everything
// is on disk and there is not a lazy writing
// so we are deterministic with the tests
- Sync();
+ Sync(options, dbg);
s = UnmapCurrentRegion();
}
if (!ret && s.ok()) {
auto lastError = GetLastError();
s = IOErrorFromWindowsError(
- "Failed to Close mapping for file: " + filename_, lastError);
+ "Failed to Close mapping for file: " + filename_, lastError);
}
hMap_ = NULL;
}
if (hFile_ != NULL) {
-
TruncateFile(targetSize);
BOOL ret = ::CloseHandle(hFile_);
if (!ret && s.ok()) {
auto lastError = GetLastError();
s = IOErrorFromWindowsError(
- "Failed to close file map handle: " + filename_, lastError);
+ "Failed to close file map handle: " + filename_, lastError);
}
}
return s;
}
-Status WinMmapFile::Flush() { return Status::OK(); }
+IOStatus WinMmapFile::Flush(const IOOptions& /*options*/,
+ IODebugContext* /*dbg*/) {
+ return IOStatus::OK();
+}
// Flush only data
-Status WinMmapFile::Sync() {
- Status s;
+IOStatus WinMmapFile::Sync(const IOOptions& /*options*/,
+ IODebugContext* /*dbg*/) {
+ IOStatus s;
// Some writes occurred since last sync
if (dst_ > last_sync_) {
assert(dst_ < mapped_end_);
size_t page_begin =
- TruncateToPageBoundary(page_size_, last_sync_ - mapped_begin_);
+ TruncateToPageBoundary(page_size_, last_sync_ - mapped_begin_);
size_t page_end =
- TruncateToPageBoundary(page_size_, dst_ - mapped_begin_ - 1);
+ TruncateToPageBoundary(page_size_, dst_ - mapped_begin_ - 1);
// Flush only the amount of that is a multiple of pages
if (!::FlushViewOfFile(mapped_begin_ + page_begin,
- (page_end - page_begin) + page_size_)) {
+ (page_end - page_begin) + page_size_)) {
s = IOErrorFromWindowsError("Failed to FlushViewOfFile: " + filename_,
- GetLastError());
+ GetLastError());
} else {
last_sync_ = dst_;
}
}
/**
-* Flush data as well as metadata to stable storage.
-*/
-Status WinMmapFile::Fsync() {
- Status s = Sync();
+ * Flush data as well as metadata to stable storage.
+ */
+IOStatus WinMmapFile::Fsync(const IOOptions& options, IODebugContext* dbg) {
+ IOStatus s = Sync(options, dbg);
// Flush metadata
if (s.ok() && pending_sync_) {
if (!::FlushFileBuffers(hFile_)) {
s = IOErrorFromWindowsError("Failed to FlushFileBuffers: " + filename_,
- GetLastError());
+ GetLastError());
}
pending_sync_ = false;
}
}
/**
-* Get the size of valid data in the file. This will not match the
-* size that is returned from the filesystem because we use mmap
-* to extend file by map_size every time.
-*/
-uint64_t WinMmapFile::GetFileSize() {
+ * Get the size of valid data in the file. This will not match the
+ * size that is returned from the filesystem because we use mmap
+ * to extend file by map_size every time.
+ */
+uint64_t WinMmapFile::GetFileSize(const IOOptions& /*options*/,
+ IODebugContext* /*dbg*/) {
size_t used = dst_ - mapped_begin_;
return file_offset_ + used;
}
-Status WinMmapFile::InvalidateCache(size_t offset, size_t length) {
- return Status::OK();
+IOStatus WinMmapFile::InvalidateCache(size_t offset, size_t length) {
+ return IOStatus::OK();
}
-Status WinMmapFile::Allocate(uint64_t offset, uint64_t len) {
- Status status;
- TEST_KILL_RANDOM("WinMmapFile::Allocate", rocksdb_kill_odds);
+IOStatus WinMmapFile::Allocate(uint64_t offset, uint64_t len,
+ const IOOptions& /*options*/,
+ IODebugContext* /*dbg*/) {
+ IOStatus status;
+ TEST_KILL_RANDOM("WinMmapFile::Allocate");
// Make sure that we reserve an aligned amount of space
// since the reservation block size is driven outside so we want
// to check if we are ok with reservation here
- size_t spaceToReserve = Roundup(static_cast<size_t>(offset + len), view_size_);
+ size_t spaceToReserve =
+ Roundup(static_cast<size_t>(offset + len), view_size_);
// Nothing to do
if (spaceToReserve <= reserved_size_) {
return status;
// WinSequentialFile
WinSequentialFile::WinSequentialFile(const std::string& fname, HANDLE f,
- const EnvOptions& options)
+ const FileOptions& options)
: WinFileData(fname, f, options.use_direct_reads) {}
WinSequentialFile::~WinSequentialFile() {
assert(hFile_ != INVALID_HANDLE_VALUE);
}
-Status WinSequentialFile::Read(size_t n, Slice* result, char* scratch) {
- Status s;
+IOStatus WinSequentialFile::Read(size_t n, const IOOptions& /*opts*/,
+ Slice* result, char* scratch,
+ IODebugContext* /*dbg*/) {
+ IOStatus s;
size_t r = 0;
assert(result != nullptr);
if (WinFileData::use_direct_io()) {
- return Status::NotSupported("Read() does not support direct_io");
+ return IOStatus::NotSupported("Read() does not support direct_io");
}
// Windows ReadFile API accepts a DWORD.
// While it is possible to read in a loop if n is too big
// it is an unlikely case.
if (n > std::numeric_limits<DWORD>::max()) {
- return Status::InvalidArgument("n is too big for a single ReadFile: "
- + filename_);
+ return IOStatus::InvalidArgument("n is too big for a single ReadFile: " +
+ filename_);
}
- DWORD bytesToRead = static_cast<DWORD>(n); //cast is safe due to the check above
+ DWORD bytesToRead =
+ static_cast<DWORD>(n); // cast is safe due to the check above
DWORD bytesRead = 0;
BOOL ret = ReadFile(hFile_, scratch, bytesToRead, &bytesRead, NULL);
if (ret != FALSE) {
} else {
auto lastError = GetLastError();
if (lastError != ERROR_HANDLE_EOF) {
- s = IOErrorFromWindowsError("ReadFile failed: " + filename_,
- lastError);
+ s = IOErrorFromWindowsError("ReadFile failed: " + filename_, lastError);
}
}
return s;
}
-Status WinSequentialFile::PositionedReadInternal(char* src, size_t numBytes,
- uint64_t offset, size_t& bytes_read) const {
+IOStatus WinSequentialFile::PositionedReadInternal(char* src, size_t numBytes,
+ uint64_t offset,
+ size_t& bytes_read) const {
return pread(this, src, numBytes, offset, bytes_read);
}
-Status WinSequentialFile::PositionedRead(uint64_t offset, size_t n, Slice* result,
- char* scratch) {
-
- Status s;
-
+IOStatus WinSequentialFile::PositionedRead(uint64_t offset, size_t n,
+ const IOOptions& /*opts*/,
+ Slice* result, char* scratch,
+ IODebugContext* /*dbg*/) {
if (!WinFileData::use_direct_io()) {
- return Status::NotSupported("This function is only used for direct_io");
+ return IOStatus::NotSupported("This function is only used for direct_io");
}
- if (!IsSectorAligned(static_cast<size_t>(offset)) ||
- !IsSectorAligned(n)) {
- return Status::InvalidArgument(
- "WinSequentialFile::PositionedRead: offset is not properly aligned");
- }
+ assert(IsSectorAligned(static_cast<size_t>(offset)));
+ assert(IsSectorAligned(static_cast<size_t>(n)));
- size_t bytes_read = 0; // out param
- s = PositionedReadInternal(scratch, static_cast<size_t>(n), offset, bytes_read);
+ size_t bytes_read = 0; // out param
+ IOStatus s = PositionedReadInternal(scratch, static_cast<size_t>(n), offset,
+ bytes_read);
*result = Slice(scratch, bytes_read);
return s;
}
-
-Status WinSequentialFile::Skip(uint64_t n) {
- // Can't handle more than signed max as SetFilePointerEx accepts a signed 64-bit
- // integer. As such it is a highly unlikley case to have n so large.
+IOStatus WinSequentialFile::Skip(uint64_t n) {
+ // Can't handle more than signed max as SetFilePointerEx accepts a signed
+ // 64-bit integer. As such it is a highly unlikley case to have n so large.
if (n > static_cast<uint64_t>(std::numeric_limits<LONGLONG>::max())) {
- return Status::InvalidArgument("n is too large for a single SetFilePointerEx() call" +
- filename_);
+ return IOStatus::InvalidArgument(
+ "n is too large for a single SetFilePointerEx() call" + filename_);
}
LARGE_INTEGER li;
- li.QuadPart = static_cast<LONGLONG>(n); //cast is safe due to the check above
+ li.QuadPart = static_cast<LONGLONG>(n); // cast is safe due to the check
+ // above
BOOL ret = SetFilePointerEx(hFile_, li, NULL, FILE_CURRENT);
if (ret == FALSE) {
auto lastError = GetLastError();
return IOErrorFromWindowsError("Skip SetFilePointerEx():" + filename_,
lastError);
}
- return Status::OK();
+ return IOStatus::OK();
}
-Status WinSequentialFile::InvalidateCache(size_t offset, size_t length) {
- return Status::OK();
+IOStatus WinSequentialFile::InvalidateCache(size_t offset, size_t length) {
+ return IOStatus::OK();
}
//////////////////////////////////////////////////////////////////////////////////////////////////
/// WinRandomAccessBase
-inline
-Status WinRandomAccessImpl::PositionedReadInternal(char* src,
- size_t numBytes,
- uint64_t offset,
- size_t& bytes_read) const {
+inline IOStatus WinRandomAccessImpl::PositionedReadInternal(
+ char* src, size_t numBytes, uint64_t offset, size_t& bytes_read) const {
return pread(file_base_, src, numBytes, offset, bytes_read);
}
-inline
-WinRandomAccessImpl::WinRandomAccessImpl(WinFileData* file_base,
- size_t alignment,
- const EnvOptions& options) :
- file_base_(file_base),
- alignment_(alignment) {
-
+inline WinRandomAccessImpl::WinRandomAccessImpl(WinFileData* file_base,
+ size_t alignment,
+ const FileOptions& options)
+ : file_base_(file_base),
+ alignment_(std::max(alignment, file_base->GetSectorSize())) {
assert(!options.use_mmap_reads);
}
-inline
-Status WinRandomAccessImpl::ReadImpl(uint64_t offset, size_t n, Slice* result,
- char* scratch) const {
-
- Status s;
-
+inline IOStatus WinRandomAccessImpl::ReadImpl(uint64_t offset, size_t n,
+ Slice* result,
+ char* scratch) const {
// Check buffer alignment
if (file_base_->use_direct_io()) {
- if (!IsSectorAligned(static_cast<size_t>(offset)) ||
- !IsAligned(alignment_, scratch)) {
- return Status::InvalidArgument(
- "WinRandomAccessImpl::ReadImpl: offset or scratch is not properly aligned");
- }
+ assert(file_base_->IsSectorAligned(static_cast<size_t>(offset)));
+ assert(IsAligned(alignment_, scratch));
}
if (n == 0) {
*result = Slice(scratch, 0);
- return s;
+ return IOStatus::OK();
}
size_t bytes_read = 0;
- s = PositionedReadInternal(scratch, n, offset, bytes_read);
+ IOStatus s = PositionedReadInternal(scratch, n, offset, bytes_read);
*result = Slice(scratch, bytes_read);
return s;
}
WinRandomAccessFile::WinRandomAccessFile(const std::string& fname, HANDLE hFile,
size_t alignment,
- const EnvOptions& options)
+ const FileOptions& options)
: WinFileData(fname, hFile, options.use_direct_reads),
WinRandomAccessImpl(this, alignment, options) {}
-WinRandomAccessFile::~WinRandomAccessFile() {
-}
+WinRandomAccessFile::~WinRandomAccessFile() {}
-Status WinRandomAccessFile::Read(uint64_t offset, size_t n, Slice* result,
- char* scratch) const {
+IOStatus WinRandomAccessFile::Read(uint64_t offset, size_t n,
+ const IOOptions& /*options*/, Slice* result,
+ char* scratch,
+ IODebugContext* /*dbg*/) const {
return ReadImpl(offset, n, result, scratch);
}
-Status WinRandomAccessFile::InvalidateCache(size_t offset, size_t length) {
- return Status::OK();
+IOStatus WinRandomAccessFile::InvalidateCache(size_t offset, size_t length) {
+ return IOStatus::OK();
}
size_t WinRandomAccessFile::GetUniqueId(char* id, size_t max_size) const {
// WinWritableImpl
//
-inline
-Status WinWritableImpl::PreallocateInternal(uint64_t spaceToReserve) {
- return fallocate(file_data_->GetName(), file_data_->GetFileHandle(), spaceToReserve);
+inline IOStatus WinWritableImpl::PreallocateInternal(uint64_t spaceToReserve) {
+ return fallocate(file_data_->GetName(), file_data_->GetFileHandle(),
+ spaceToReserve);
}
-inline
-WinWritableImpl::WinWritableImpl(WinFileData* file_data, size_t alignment)
- : file_data_(file_data),
- alignment_(alignment),
- next_write_offset_(0),
- reservedsize_(0) {
-
+inline WinWritableImpl::WinWritableImpl(WinFileData* file_data,
+ size_t alignment)
+ : file_data_(file_data),
+ alignment_(std::max(alignment, file_data->GetSectorSize())),
+ next_write_offset_(0),
+ reservedsize_(0) {
// Query current position in case ReopenWritableFile is called
// This position is only important for buffered writes
// for unbuffered writes we explicitely specify the position.
LARGE_INTEGER zero_move;
- zero_move.QuadPart = 0; // Do not move
+ zero_move.QuadPart = 0; // Do not move
LARGE_INTEGER pos;
pos.QuadPart = 0;
BOOL ret = SetFilePointerEx(file_data_->GetFileHandle(), zero_move, &pos,
- FILE_CURRENT);
+ FILE_CURRENT);
// Querying no supped to fail
if (ret != 0) {
next_write_offset_ = pos.QuadPart;
}
}
-inline
-Status WinWritableImpl::AppendImpl(const Slice& data) {
-
- Status s;
+inline IOStatus WinWritableImpl::AppendImpl(const Slice& data) {
+ IOStatus s;
if (data.size() > std::numeric_limits<DWORD>::max()) {
- return Status::InvalidArgument("data is too long for a single write" +
- file_data_->GetName());
+ return IOStatus::InvalidArgument("data is too long for a single write" +
+ file_data_->GetName());
}
- size_t bytes_written = 0; // out param
+ size_t bytes_written = 0; // out param
if (file_data_->use_direct_io()) {
// With no offset specified we are appending
// to the end of the file
- assert(IsSectorAligned(next_write_offset_));
- if (!IsSectorAligned(data.size()) ||
- !IsAligned(static_cast<size_t>(GetAlignement()), data.data())) {
- s = Status::InvalidArgument(
- "WriteData must be page aligned, size must be sector aligned");
- } else {
- s = pwrite(file_data_, data, next_write_offset_, bytes_written);
- }
+ assert(file_data_->IsSectorAligned(next_write_offset_));
+ assert(file_data_->IsSectorAligned(data.size()));
+ assert(IsAligned(static_cast<size_t>(GetAlignment()), data.data()));
+ s = pwrite(file_data_, data, next_write_offset_, bytes_written);
} else {
-
DWORD bytesWritten = 0;
if (!WriteFile(file_data_->GetFileHandle(), data.data(),
- static_cast<DWORD>(data.size()), &bytesWritten, NULL)) {
+ static_cast<DWORD>(data.size()), &bytesWritten, NULL)) {
auto lastError = GetLastError();
s = IOErrorFromWindowsError(
- "Failed to WriteFile: " + file_data_->GetName(),
- lastError);
+ "Failed to WriteFile: " + file_data_->GetName(), lastError);
} else {
bytes_written = bytesWritten;
}
}
- if(s.ok()) {
+ if (s.ok()) {
if (bytes_written == data.size()) {
// This matters for direct_io cases where
// we rely on the fact that next_write_offset_
// is sector aligned
next_write_offset_ += bytes_written;
} else {
- s = Status::IOError("Failed to write all bytes: " +
- file_data_->GetName());
+ s = IOStatus::IOError("Failed to write all bytes: " +
+ file_data_->GetName());
}
}
return s;
}
-inline
-Status WinWritableImpl::PositionedAppendImpl(const Slice& data, uint64_t offset) {
-
- if(file_data_->use_direct_io()) {
- if (!IsSectorAligned(static_cast<size_t>(offset)) ||
- !IsSectorAligned(data.size()) ||
- !IsAligned(static_cast<size_t>(GetAlignement()), data.data())) {
- return Status::InvalidArgument(
- "Data and offset must be page aligned, size must be sector aligned");
- }
+inline IOStatus WinWritableImpl::PositionedAppendImpl(const Slice& data,
+ uint64_t offset) {
+ if (file_data_->use_direct_io()) {
+ assert(file_data_->IsSectorAligned(static_cast<size_t>(offset)));
+ assert(file_data_->IsSectorAligned(data.size()));
+ assert(IsAligned(static_cast<size_t>(GetAlignment()), data.data()));
}
size_t bytes_written = 0;
- Status s = pwrite(file_data_, data, offset, bytes_written);
+ IOStatus s = pwrite(file_data_, data, offset, bytes_written);
- if(s.ok()) {
+ if (s.ok()) {
if (bytes_written == data.size()) {
// For sequential write this would be simple
// size extension by data.size()
next_write_offset_ = write_end;
}
} else {
- s = Status::IOError("Failed to write all of the requested data: " +
- file_data_->GetName());
+ s = IOStatus::IOError("Failed to write all of the requested data: " +
+ file_data_->GetName());
}
}
return s;
}
-inline
-Status WinWritableImpl::TruncateImpl(uint64_t size) {
-
+inline IOStatus WinWritableImpl::TruncateImpl(uint64_t size) {
// It is tempting to check for the size for sector alignment
// but truncation may come at the end and there is not a requirement
// for this to be sector aligned so long as we do not attempt to write
// after that. The interface docs state that the behavior is undefined
// in that case.
- Status s = ftruncate(file_data_->GetName(), file_data_->GetFileHandle(),
- size);
+ IOStatus s =
+ ftruncate(file_data_->GetName(), file_data_->GetFileHandle(), size);
if (s.ok()) {
next_write_offset_ = size;
return s;
}
-inline
-Status WinWritableImpl::CloseImpl() {
-
- Status s;
+inline IOStatus WinWritableImpl::CloseImpl() {
+ IOStatus s;
auto hFile = file_data_->GetFileHandle();
assert(INVALID_HANDLE_VALUE != hFile);
if (!::FlushFileBuffers(hFile)) {
auto lastError = GetLastError();
- s = IOErrorFromWindowsError("FlushFileBuffers failed at Close() for: " +
- file_data_->GetName(),
- lastError);
+ s = IOErrorFromWindowsError(
+ "FlushFileBuffers failed at Close() for: " + file_data_->GetName(),
+ lastError);
}
- if(!file_data_->CloseFile() && s.ok()) {
+ if (!file_data_->CloseFile() && s.ok()) {
auto lastError = GetLastError();
- s = IOErrorFromWindowsError("CloseHandle failed for: " + file_data_->GetName(),
- lastError);
+ s = IOErrorFromWindowsError(
+ "CloseHandle failed for: " + file_data_->GetName(), lastError);
}
return s;
}
-inline
-Status WinWritableImpl::SyncImpl() {
- Status s;
- if (!::FlushFileBuffers (file_data_->GetFileHandle())) {
+inline IOStatus WinWritableImpl::SyncImpl(const IOOptions& /*options*/,
+ IODebugContext* /*dbg*/) {
+ IOStatus s;
+ if (!::FlushFileBuffers(file_data_->GetFileHandle())) {
auto lastError = GetLastError();
s = IOErrorFromWindowsError(
- "FlushFileBuffers failed at Sync() for: " + file_data_->GetName(), lastError);
+ "FlushFileBuffers failed at Sync() for: " + file_data_->GetName(),
+ lastError);
}
return s;
}
-
-inline
-Status WinWritableImpl::AllocateImpl(uint64_t offset, uint64_t len) {
- Status status;
- TEST_KILL_RANDOM("WinWritableFile::Allocate", rocksdb_kill_odds);
+inline IOStatus WinWritableImpl::AllocateImpl(uint64_t offset, uint64_t len) {
+ IOStatus status;
+ TEST_KILL_RANDOM("WinWritableFile::Allocate");
// Make sure that we reserve an aligned amount of space
// since the reservation block size is driven outside so we want
// to check if we are ok with reservation here
- size_t spaceToReserve = Roundup(static_cast<size_t>(offset + len), static_cast<size_t>(alignment_));
+ size_t spaceToReserve = Roundup(static_cast<size_t>(offset + len),
+ static_cast<size_t>(alignment_));
// Nothing to do
if (spaceToReserve <= reservedsize_) {
return status;
return status;
}
-
////////////////////////////////////////////////////////////////////////////////
/// WinWritableFile
WinWritableFile::WinWritableFile(const std::string& fname, HANDLE hFile,
size_t alignment, size_t /* capacity */,
- const EnvOptions& options)
+ const FileOptions& options)
: WinFileData(fname, hFile, options.use_direct_writes),
WinWritableImpl(this, alignment),
- WritableFile(options) {
+ FSWritableFile(options) {
assert(!options.use_mmap_writes);
}
-WinWritableFile::~WinWritableFile() {
-}
+WinWritableFile::~WinWritableFile() {}
// Indicates if the class makes use of direct I/O
-bool WinWritableFile::use_direct_io() const { return WinFileData::use_direct_io(); }
+bool WinWritableFile::use_direct_io() const {
+ return WinFileData::use_direct_io();
+}
size_t WinWritableFile::GetRequiredBufferAlignment() const {
- return static_cast<size_t>(GetAlignement());
+ return static_cast<size_t>(GetAlignment());
}
-Status WinWritableFile::Append(const Slice& data) {
+IOStatus WinWritableFile::Append(const Slice& data,
+ const IOOptions& /*options*/,
+ IODebugContext* /*dbg*/) {
return AppendImpl(data);
}
-Status WinWritableFile::PositionedAppend(const Slice& data, uint64_t offset) {
+IOStatus WinWritableFile::PositionedAppend(const Slice& data, uint64_t offset,
+ const IOOptions& /*options*/,
+ IODebugContext* /*dbg*/) {
return PositionedAppendImpl(data, offset);
}
// Need to implement this so the file is truncated correctly
// when buffered and unbuffered mode
-Status WinWritableFile::Truncate(uint64_t size) {
+IOStatus WinWritableFile::Truncate(uint64_t size, const IOOptions& /*options*/,
+ IODebugContext* /*dbg*/) {
return TruncateImpl(size);
}
-Status WinWritableFile::Close() {
+IOStatus WinWritableFile::Close(const IOOptions& /*options*/,
+ IODebugContext* /*dbg*/) {
return CloseImpl();
}
- // write out the cached data to the OS cache
- // This is now taken care of the WritableFileWriter
-Status WinWritableFile::Flush() {
- return Status::OK();
+// write out the cached data to the OS cache
+// This is now taken care of the WritableFileWriter
+IOStatus WinWritableFile::Flush(const IOOptions& /*options*/,
+ IODebugContext* /*dbg*/) {
+ return IOStatus::OK();
}
-Status WinWritableFile::Sync() {
- return SyncImpl();
+IOStatus WinWritableFile::Sync(const IOOptions& options, IODebugContext* dbg) {
+ return SyncImpl(options, dbg);
}
-Status WinWritableFile::Fsync() { return SyncImpl(); }
+IOStatus WinWritableFile::Fsync(const IOOptions& options, IODebugContext* dbg) {
+ return SyncImpl(options, dbg);
+}
bool WinWritableFile::IsSyncThreadSafe() const { return true; }
-uint64_t WinWritableFile::GetFileSize() {
+uint64_t WinWritableFile::GetFileSize(const IOOptions& /*options*/,
+ IODebugContext* /*dbg*/) {
return GetFileNextWriteOffset();
}
-Status WinWritableFile::Allocate(uint64_t offset, uint64_t len) {
+IOStatus WinWritableFile::Allocate(uint64_t offset, uint64_t len,
+ const IOOptions& /*options*/,
+ IODebugContext* /*dbg*/) {
return AllocateImpl(offset, len);
}
/// WinRandomRWFile
WinRandomRWFile::WinRandomRWFile(const std::string& fname, HANDLE hFile,
- size_t alignment, const EnvOptions& options)
+ size_t alignment, const FileOptions& options)
: WinFileData(fname, hFile,
options.use_direct_reads && options.use_direct_writes),
WinRandomAccessImpl(this, alignment, options),
WinWritableImpl(this, alignment) {}
-bool WinRandomRWFile::use_direct_io() const { return WinFileData::use_direct_io(); }
+bool WinRandomRWFile::use_direct_io() const {
+ return WinFileData::use_direct_io();
+}
size_t WinRandomRWFile::GetRequiredBufferAlignment() const {
- return static_cast<size_t>(GetAlignement());
+ assert(WinRandomAccessImpl::GetAlignment() ==
+ WinWritableImpl::GetAlignment());
+ return static_cast<size_t>(WinRandomAccessImpl::GetAlignment());
}
-Status WinRandomRWFile::Write(uint64_t offset, const Slice & data) {
+IOStatus WinRandomRWFile::Write(uint64_t offset, const Slice& data,
+ const IOOptions& /*options*/,
+ IODebugContext* /*dbg*/) {
return PositionedAppendImpl(data, offset);
}
-Status WinRandomRWFile::Read(uint64_t offset, size_t n, Slice* result,
- char* scratch) const {
+IOStatus WinRandomRWFile::Read(uint64_t offset, size_t n,
+ const IOOptions& /*options*/, Slice* result,
+ char* scratch, IODebugContext* /*dbg*/) const {
return ReadImpl(offset, n, result, scratch);
}
-Status WinRandomRWFile::Flush() {
- return Status::OK();
+IOStatus WinRandomRWFile::Flush(const IOOptions& /*options*/,
+ IODebugContext* /*dbg*/) {
+ return IOStatus::OK();
}
-Status WinRandomRWFile::Sync() {
- return SyncImpl();
+IOStatus WinRandomRWFile::Sync(const IOOptions& options, IODebugContext* dbg) {
+ return SyncImpl(options, dbg);
}
-Status WinRandomRWFile::Close() {
+IOStatus WinRandomRWFile::Close(const IOOptions& /*options*/,
+ IODebugContext* /*dbg*/) {
return CloseImpl();
}
WinMemoryMappedBuffer::~WinMemoryMappedBuffer() {
BOOL ret
#if defined(_MSC_VER)
- = FALSE;
+ = FALSE;
#else
- __attribute__((__unused__));
+ __attribute__((__unused__));
#endif
if (base_ != nullptr) {
ret = ::UnmapViewOfFile(base_);
//////////////////////////////////////////////////////////////////////////
/// WinDirectory
-Status WinDirectory::Fsync() { return Status::OK(); }
+IOStatus WinDirectory::Fsync(const IOOptions& /*options*/,
+ IODebugContext* /*dbg*/) {
+ return IOStatus::OK();
+}
+
+IOStatus WinDirectory::Close(const IOOptions& /*options*/,
+ IODebugContext* /*dbg*/) {
+ IOStatus s = IOStatus::OK();
+ BOOL ret __attribute__((__unused__));
+ if (handle_ != INVALID_HANDLE_VALUE) {
+ ret = ::CloseHandle(handle_);
+ if (!ret) {
+ auto lastError = GetLastError();
+ s = IOErrorFromWindowsError("Directory closes failed for : " + GetName(),
+ lastError);
+ }
+ handle_ = NULL;
+ }
+ return s;
+}
size_t WinDirectory::GetUniqueId(char* id, size_t max_size) const {
return GetUniqueIdFromFile(handle_, id, max_size);
assert(ret);
}
-}
+} // namespace port
} // namespace ROCKSDB_NAMESPACE
#endif