|
|
@ -155,10 +155,12 @@ size_t GetUniqueIdFromFile(HANDLE hFile, char* id, size_t max_size) { |
|
|
|
return static_cast<size_t>(rid - id); |
|
|
|
return static_cast<size_t>(rid - id); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
|
|
|
|
|
|
// WinMmapReadableFile
|
|
|
|
|
|
|
|
|
|
|
|
WinMmapReadableFile::WinMmapReadableFile(const std::string& fileName, HANDLE hFile, HANDLE hMap, |
|
|
|
WinMmapReadableFile::WinMmapReadableFile(const std::string& fileName, HANDLE hFile, HANDLE hMap, |
|
|
|
const void* mapped_region, size_t length) |
|
|
|
const void* mapped_region, size_t length) |
|
|
|
: fileName_(fileName), |
|
|
|
: WinFileData(fileName, hFile, false), |
|
|
|
hFile_(hFile), |
|
|
|
|
|
|
|
hMap_(hMap), |
|
|
|
hMap_(hMap), |
|
|
|
mapped_region_(mapped_region), |
|
|
|
mapped_region_(mapped_region), |
|
|
|
length_(length) {} |
|
|
|
length_(length) {} |
|
|
@ -169,9 +171,6 @@ WinMmapReadableFile::~WinMmapReadableFile() { |
|
|
|
|
|
|
|
|
|
|
|
ret = ::CloseHandle(hMap_); |
|
|
|
ret = ::CloseHandle(hMap_); |
|
|
|
assert(ret); |
|
|
|
assert(ret); |
|
|
|
|
|
|
|
|
|
|
|
ret = ::CloseHandle(hFile_); |
|
|
|
|
|
|
|
assert(ret); |
|
|
|
|
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
Status WinMmapReadableFile::Read(uint64_t offset, size_t n, Slice* result, |
|
|
|
Status WinMmapReadableFile::Read(uint64_t offset, size_t n, Slice* result, |
|
|
@ -180,7 +179,7 @@ Status WinMmapReadableFile::Read(uint64_t offset, size_t n, Slice* result, |
|
|
|
|
|
|
|
|
|
|
|
if (offset > length_) { |
|
|
|
if (offset > length_) { |
|
|
|
*result = Slice(); |
|
|
|
*result = Slice(); |
|
|
|
return IOError(fileName_, EINVAL); |
|
|
|
return IOError(filename_, EINVAL); |
|
|
|
} else if (offset + n > length_) { |
|
|
|
} else if (offset + n > length_) { |
|
|
|
n = length_ - offset; |
|
|
|
n = length_ - offset; |
|
|
|
} |
|
|
|
} |
|
|
@ -197,6 +196,10 @@ size_t WinMmapReadableFile::GetUniqueId(char* id, size_t max_size) const { |
|
|
|
return GetUniqueIdFromFile(hFile_, id, max_size); |
|
|
|
return GetUniqueIdFromFile(hFile_, id, max_size); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
|
|
|
|
|
|
/// WinMmapFile
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// Can only truncate or reserve to a sector size aligned if
|
|
|
|
// Can only truncate or reserve to a sector size aligned if
|
|
|
|
// used on files that are opened with Unbuffered I/O
|
|
|
|
// used on files that are opened with Unbuffered I/O
|
|
|
|
Status WinMmapFile::TruncateFile(uint64_t toSize) { |
|
|
|
Status WinMmapFile::TruncateFile(uint64_t toSize) { |
|
|
@ -302,8 +305,7 @@ Status WinMmapFile::PreallocateInternal(uint64_t spaceToReserve) { |
|
|
|
|
|
|
|
|
|
|
|
WinMmapFile::WinMmapFile(const std::string& fname, HANDLE hFile, size_t page_size, |
|
|
|
WinMmapFile::WinMmapFile(const std::string& fname, HANDLE hFile, size_t page_size, |
|
|
|
size_t allocation_granularity, const EnvOptions& options) |
|
|
|
size_t allocation_granularity, const EnvOptions& options) |
|
|
|
: filename_(fname), |
|
|
|
: WinFileData(fname, hFile, false), |
|
|
|
hFile_(hFile), |
|
|
|
|
|
|
|
hMap_(NULL), |
|
|
|
hMap_(NULL), |
|
|
|
page_size_(page_size), |
|
|
|
page_size_(page_size), |
|
|
|
allocation_granularity_(allocation_granularity), |
|
|
|
allocation_granularity_(allocation_granularity), |
|
|
@ -515,16 +517,16 @@ size_t WinMmapFile::GetUniqueId(char* id, size_t max_size) const { |
|
|
|
return GetUniqueIdFromFile(hFile_, id, max_size); |
|
|
|
return GetUniqueIdFromFile(hFile_, id, max_size); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
//////////////////////////////////////////////////////////////////////////////////
|
|
|
|
|
|
|
|
// WinSequentialFile
|
|
|
|
|
|
|
|
|
|
|
|
WinSequentialFile::WinSequentialFile(const std::string& fname, HANDLE f, |
|
|
|
WinSequentialFile::WinSequentialFile(const std::string& fname, HANDLE f, |
|
|
|
const EnvOptions& options) |
|
|
|
const EnvOptions& options) |
|
|
|
: filename_(fname), |
|
|
|
: WinFileData(fname, f, options.use_os_buffer) |
|
|
|
file_(f), |
|
|
|
|
|
|
|
use_os_buffer_(options.use_os_buffer) |
|
|
|
|
|
|
|
{} |
|
|
|
{} |
|
|
|
|
|
|
|
|
|
|
|
WinSequentialFile::~WinSequentialFile() { |
|
|
|
WinSequentialFile::~WinSequentialFile() { |
|
|
|
assert(file_ != INVALID_HANDLE_VALUE); |
|
|
|
assert(hFile_ != INVALID_HANDLE_VALUE); |
|
|
|
CloseHandle(file_); |
|
|
|
|
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
Status WinSequentialFile::Read(size_t n, Slice* result, char* scratch) { |
|
|
|
Status WinSequentialFile::Read(size_t n, Slice* result, char* scratch) { |
|
|
@ -540,7 +542,7 @@ Status WinSequentialFile::Read(size_t n, Slice* result, char* scratch) { |
|
|
|
|
|
|
|
|
|
|
|
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; |
|
|
|
DWORD bytesRead = 0; |
|
|
|
BOOL ret = ReadFile(file_, scratch, bytesToRead, &bytesRead, NULL); |
|
|
|
BOOL ret = ReadFile(hFile_, scratch, bytesToRead, &bytesRead, NULL); |
|
|
|
if (ret == TRUE) { |
|
|
|
if (ret == TRUE) { |
|
|
|
r = bytesRead; |
|
|
|
r = bytesRead; |
|
|
|
} else { |
|
|
|
} else { |
|
|
@ -561,7 +563,7 @@ Status WinSequentialFile::Skip(uint64_t n) { |
|
|
|
|
|
|
|
|
|
|
|
LARGE_INTEGER li; |
|
|
|
LARGE_INTEGER li; |
|
|
|
li.QuadPart = static_cast<int64_t>(n); //cast is safe due to the check above
|
|
|
|
li.QuadPart = static_cast<int64_t>(n); //cast is safe due to the check above
|
|
|
|
BOOL ret = SetFilePointerEx(file_, li, NULL, FILE_CURRENT); |
|
|
|
BOOL ret = SetFilePointerEx(hFile_, li, NULL, FILE_CURRENT); |
|
|
|
if (ret == FALSE) { |
|
|
|
if (ret == FALSE) { |
|
|
|
return IOErrorFromWindowsError(filename_, GetLastError()); |
|
|
|
return IOErrorFromWindowsError(filename_, GetLastError()); |
|
|
|
} |
|
|
|
} |
|
|
@ -572,14 +574,31 @@ Status WinSequentialFile::InvalidateCache(size_t offset, size_t length) { |
|
|
|
return Status::OK(); |
|
|
|
return Status::OK(); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
SSIZE_T WinRandomAccessFile::ReadIntoBuffer(uint64_t user_offset, uint64_t first_page_start, |
|
|
|
//////////////////////////////////////////////////////////////////////////////////////////////////
|
|
|
|
|
|
|
|
/// WinRandomAccessBase
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// Helper
|
|
|
|
|
|
|
|
void CalculateReadParameters(size_t alignment, uint64_t offset, |
|
|
|
|
|
|
|
size_t bytes_requested, |
|
|
|
|
|
|
|
size_t& actual_bytes_toread, |
|
|
|
|
|
|
|
uint64_t& first_page_start) { |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
first_page_start = TruncateToPageBoundary(alignment, offset); |
|
|
|
|
|
|
|
const uint64_t last_page_start = |
|
|
|
|
|
|
|
TruncateToPageBoundary(alignment, offset + bytes_requested - 1); |
|
|
|
|
|
|
|
actual_bytes_toread = (last_page_start - first_page_start) + alignment; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
SSIZE_T WinRandomAccessImpl::ReadIntoBuffer(uint64_t user_offset, |
|
|
|
|
|
|
|
uint64_t first_page_start, |
|
|
|
size_t bytes_to_read, size_t& left, |
|
|
|
size_t bytes_to_read, size_t& left, |
|
|
|
AlignedBuffer& buffer, char* dest) const { |
|
|
|
AlignedBuffer& buffer, char* dest) const { |
|
|
|
assert(buffer.CurrentSize() == 0); |
|
|
|
assert(buffer.CurrentSize() == 0); |
|
|
|
assert(buffer.Capacity() >= bytes_to_read); |
|
|
|
assert(buffer.Capacity() >= bytes_to_read); |
|
|
|
|
|
|
|
|
|
|
|
SSIZE_T read = |
|
|
|
SSIZE_T read = |
|
|
|
PositionedReadInternal(buffer.Destination(), bytes_to_read, first_page_start); |
|
|
|
PositionedReadInternal(buffer.Destination(), bytes_to_read, |
|
|
|
|
|
|
|
first_page_start); |
|
|
|
|
|
|
|
|
|
|
|
if (read > 0) { |
|
|
|
if (read > 0) { |
|
|
|
buffer.Size(read); |
|
|
|
buffer.Size(read); |
|
|
@ -597,7 +616,8 @@ SSIZE_T WinRandomAccessFile::ReadIntoBuffer(uint64_t user_offset, uint64_t first |
|
|
|
return read; |
|
|
|
return read; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
SSIZE_T WinRandomAccessFile::ReadIntoOneShotBuffer(uint64_t user_offset, uint64_t first_page_start, |
|
|
|
SSIZE_T WinRandomAccessImpl::ReadIntoOneShotBuffer(uint64_t user_offset, |
|
|
|
|
|
|
|
uint64_t first_page_start, |
|
|
|
size_t bytes_to_read, size_t& left, |
|
|
|
size_t bytes_to_read, size_t& left, |
|
|
|
char* dest) const { |
|
|
|
char* dest) const { |
|
|
|
AlignedBuffer bigBuffer; |
|
|
|
AlignedBuffer bigBuffer; |
|
|
@ -608,7 +628,7 @@ SSIZE_T WinRandomAccessFile::ReadIntoOneShotBuffer(uint64_t user_offset, uint64_ |
|
|
|
bigBuffer, dest); |
|
|
|
bigBuffer, dest); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
SSIZE_T WinRandomAccessFile::ReadIntoInstanceBuffer(uint64_t user_offset, |
|
|
|
SSIZE_T WinRandomAccessImpl::ReadIntoInstanceBuffer(uint64_t user_offset, |
|
|
|
uint64_t first_page_start, |
|
|
|
uint64_t first_page_start, |
|
|
|
size_t bytes_to_read, size_t& left, |
|
|
|
size_t bytes_to_read, size_t& left, |
|
|
|
char* dest) const { |
|
|
|
char* dest) const { |
|
|
@ -622,52 +642,35 @@ SSIZE_T WinRandomAccessFile::ReadIntoInstanceBuffer(uint64_t user_offset, |
|
|
|
return read; |
|
|
|
return read; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
void WinRandomAccessFile::CalculateReadParameters(uint64_t offset, size_t bytes_requested, |
|
|
|
SSIZE_T WinRandomAccessImpl::PositionedReadInternal(char* src, |
|
|
|
size_t& actual_bytes_toread, |
|
|
|
size_t numBytes, |
|
|
|
uint64_t& first_page_start) const { |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
const size_t alignment = buffer_.Alignment(); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
first_page_start = TruncateToPageBoundary(alignment, offset); |
|
|
|
|
|
|
|
const uint64_t last_page_start = |
|
|
|
|
|
|
|
TruncateToPageBoundary(alignment, offset + bytes_requested - 1); |
|
|
|
|
|
|
|
actual_bytes_toread = (last_page_start - first_page_start) + alignment; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
SSIZE_T WinRandomAccessFile::PositionedReadInternal(char* src, size_t numBytes, |
|
|
|
|
|
|
|
uint64_t offset) const { |
|
|
|
uint64_t offset) const { |
|
|
|
return pread(hFile_, src, numBytes, offset); |
|
|
|
return pread(file_base_->GetFileHandle(), src, numBytes, offset); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
WinRandomAccessFile::WinRandomAccessFile(const std::string& fname, HANDLE hFile, size_t alignment, |
|
|
|
inline |
|
|
|
const EnvOptions& options) |
|
|
|
WinRandomAccessImpl::WinRandomAccessImpl(WinFileData* file_base, |
|
|
|
: filename_(fname), |
|
|
|
size_t alignment, |
|
|
|
hFile_(hFile), |
|
|
|
const EnvOptions& options) : |
|
|
|
use_os_buffer_(options.use_os_buffer), |
|
|
|
file_base_(file_base), |
|
|
|
read_ahead_(false), |
|
|
|
read_ahead_(false), |
|
|
|
compaction_readahead_size_(options.compaction_readahead_size), |
|
|
|
compaction_readahead_size_(options.compaction_readahead_size), |
|
|
|
random_access_max_buffer_size_(options.random_access_max_buffer_size), |
|
|
|
random_access_max_buffer_size_(options.random_access_max_buffer_size), |
|
|
|
buffer_(), |
|
|
|
buffer_(), |
|
|
|
buffered_start_(0) { |
|
|
|
buffered_start_(0) { |
|
|
|
|
|
|
|
|
|
|
|
assert(!options.use_mmap_reads); |
|
|
|
assert(!options.use_mmap_reads); |
|
|
|
|
|
|
|
|
|
|
|
// Unbuffered access, use internal buffer for reads
|
|
|
|
// Unbuffered access, use internal buffer for reads
|
|
|
|
if (!use_os_buffer_) { |
|
|
|
if (!file_base_->UseOSBuffer()) { |
|
|
|
// Do not allocate the buffer either until the first request or
|
|
|
|
// Do not allocate the buffer either until the first request or
|
|
|
|
// until there is a call to allocate a read-ahead buffer
|
|
|
|
// until there is a call to allocate a read-ahead buffer
|
|
|
|
buffer_.Alignment(alignment); |
|
|
|
buffer_.Alignment(alignment); |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
WinRandomAccessFile::~WinRandomAccessFile() { |
|
|
|
inline |
|
|
|
if (hFile_ != NULL && hFile_ != INVALID_HANDLE_VALUE) { |
|
|
|
Status WinRandomAccessImpl::ReadImpl(uint64_t offset, size_t n, Slice* result, |
|
|
|
::CloseHandle(hFile_); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
void WinRandomAccessFile::EnableReadAhead() { this->Hint(SEQUENTIAL); } |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Status WinRandomAccessFile::Read(uint64_t offset, size_t n, Slice* result, |
|
|
|
|
|
|
|
char* scratch) const { |
|
|
|
char* scratch) const { |
|
|
|
|
|
|
|
|
|
|
|
Status s; |
|
|
|
Status s; |
|
|
@ -683,14 +686,15 @@ Status WinRandomAccessFile::Read(uint64_t offset, size_t n, Slice* result, |
|
|
|
// When in unbuffered mode we need to do the following changes:
|
|
|
|
// When in unbuffered mode we need to do the following changes:
|
|
|
|
// - use our own aligned buffer
|
|
|
|
// - use our own aligned buffer
|
|
|
|
// - always read at the offset of that is a multiple of alignment
|
|
|
|
// - always read at the offset of that is a multiple of alignment
|
|
|
|
if (!use_os_buffer_) { |
|
|
|
if (!file_base_->UseOSBuffer()) { |
|
|
|
|
|
|
|
|
|
|
|
uint64_t first_page_start = 0; |
|
|
|
uint64_t first_page_start = 0; |
|
|
|
size_t actual_bytes_toread = 0; |
|
|
|
size_t actual_bytes_toread = 0; |
|
|
|
size_t bytes_requested = left; |
|
|
|
size_t bytes_requested = left; |
|
|
|
|
|
|
|
|
|
|
|
if (!read_ahead_ && random_access_max_buffer_size_ == 0) { |
|
|
|
if (!read_ahead_ && random_access_max_buffer_size_ == 0) { |
|
|
|
CalculateReadParameters(offset, bytes_requested, actual_bytes_toread, |
|
|
|
CalculateReadParameters(buffer_.Alignment(), offset, bytes_requested, |
|
|
|
|
|
|
|
actual_bytes_toread, |
|
|
|
first_page_start); |
|
|
|
first_page_start); |
|
|
|
|
|
|
|
|
|
|
|
assert(actual_bytes_toread > 0); |
|
|
|
assert(actual_bytes_toread > 0); |
|
|
@ -723,7 +727,8 @@ Status WinRandomAccessFile::Read(uint64_t offset, size_t n, Slice* result, |
|
|
|
bytes_requested = compaction_readahead_size_; |
|
|
|
bytes_requested = compaction_readahead_size_; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
CalculateReadParameters(offset, bytes_requested, actual_bytes_toread, |
|
|
|
CalculateReadParameters(buffer_.Alignment(), offset, bytes_requested, |
|
|
|
|
|
|
|
actual_bytes_toread, |
|
|
|
first_page_start); |
|
|
|
first_page_start); |
|
|
|
|
|
|
|
|
|
|
|
assert(actual_bytes_toread > 0); |
|
|
|
assert(actual_bytes_toread > 0); |
|
|
@ -757,20 +762,25 @@ Status WinRandomAccessFile::Read(uint64_t offset, size_t n, Slice* result, |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
*result = Slice(scratch, (r < 0) ? 0 : n - left); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (r < 0) { |
|
|
|
if (r < 0) { |
|
|
|
s = IOErrorFromLastWindowsError(filename_); |
|
|
|
auto lastError = GetLastError(); |
|
|
|
|
|
|
|
// Posix impl wants to treat reads from beyond
|
|
|
|
|
|
|
|
// of the file as OK.
|
|
|
|
|
|
|
|
if(lastError != ERROR_HANDLE_EOF) { |
|
|
|
|
|
|
|
s = IOErrorFromWindowsError(file_base_->GetName(), lastError); |
|
|
|
|
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
*result = Slice(scratch, (r < 0) ? 0 : n - left); |
|
|
|
|
|
|
|
|
|
|
|
return s; |
|
|
|
return s; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
bool WinRandomAccessFile::ShouldForwardRawRequest() const { |
|
|
|
inline |
|
|
|
return true; |
|
|
|
void WinRandomAccessImpl::HintImpl(RandomAccessFile::AccessPattern pattern) { |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
void WinRandomAccessFile::Hint(AccessPattern pattern) { |
|
|
|
if (pattern == RandomAccessFile::SEQUENTIAL && |
|
|
|
if (pattern == SEQUENTIAL && !use_os_buffer_ && |
|
|
|
!file_base_->UseOSBuffer() && |
|
|
|
compaction_readahead_size_ > 0) { |
|
|
|
compaction_readahead_size_ > 0) { |
|
|
|
std::lock_guard<std::mutex> lg(buffer_mut_); |
|
|
|
std::lock_guard<std::mutex> lg(buffer_mut_); |
|
|
|
if (!read_ahead_) { |
|
|
|
if (!read_ahead_) { |
|
|
@ -785,60 +795,76 @@ void WinRandomAccessFile::Hint(AccessPattern pattern) { |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
Status WinRandomAccessFile::InvalidateCache(size_t offset, size_t length) { |
|
|
|
///////////////////////////////////////////////////////////////////////////////////////////////////
|
|
|
|
return Status::OK(); |
|
|
|
/// WinRandomAccessFile
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
WinRandomAccessFile::WinRandomAccessFile(const std::string& fname, HANDLE hFile, size_t alignment, |
|
|
|
|
|
|
|
const EnvOptions& options) : |
|
|
|
|
|
|
|
WinFileData(fname, hFile, options.use_os_buffer), |
|
|
|
|
|
|
|
WinRandomAccessImpl(this, alignment, options) { |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
size_t WinRandomAccessFile::GetUniqueId(char* id, size_t max_size) const { |
|
|
|
WinRandomAccessFile::~WinRandomAccessFile() { |
|
|
|
return GetUniqueIdFromFile(hFile_, id, max_size); |
|
|
|
|
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
Status WinWritableFile::PreallocateInternal(uint64_t spaceToReserve) { |
|
|
|
Status WinRandomAccessFile::Read(uint64_t offset, size_t n, Slice* result, |
|
|
|
return fallocate(filename_, hFile_, spaceToReserve); |
|
|
|
char* scratch) const { |
|
|
|
|
|
|
|
return ReadImpl(offset, n, result, scratch); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
WinWritableFile::WinWritableFile(const std::string& fname, HANDLE hFile, size_t alignment, |
|
|
|
void WinRandomAccessFile::EnableReadAhead() { |
|
|
|
size_t capacity, const EnvOptions& options) |
|
|
|
HintImpl(SEQUENTIAL); |
|
|
|
: filename_(fname), |
|
|
|
|
|
|
|
hFile_(hFile), |
|
|
|
|
|
|
|
use_os_buffer_(options.use_os_buffer), |
|
|
|
|
|
|
|
alignment_(alignment), |
|
|
|
|
|
|
|
filesize_(0), |
|
|
|
|
|
|
|
reservedsize_(0) { |
|
|
|
|
|
|
|
assert(!options.use_mmap_writes); |
|
|
|
|
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
WinWritableFile::~WinWritableFile() { |
|
|
|
bool WinRandomAccessFile::ShouldForwardRawRequest() const { |
|
|
|
if (NULL != hFile_ && INVALID_HANDLE_VALUE != hFile_) { |
|
|
|
return true; |
|
|
|
WinWritableFile::Close(); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
// Indicates if the class makes use of unbuffered I/O
|
|
|
|
void WinRandomAccessFile::Hint(AccessPattern pattern) { |
|
|
|
bool WinWritableFile::UseOSBuffer() const { |
|
|
|
HintImpl(pattern); |
|
|
|
return use_os_buffer_; |
|
|
|
|
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
size_t WinWritableFile::GetRequiredBufferAlignment() const { |
|
|
|
Status WinRandomAccessFile::InvalidateCache(size_t offset, size_t length) { |
|
|
|
return alignment_; |
|
|
|
return Status::OK(); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
Status WinWritableFile::Append(const Slice& data) { |
|
|
|
size_t WinRandomAccessFile::GetUniqueId(char* id, size_t max_size) const { |
|
|
|
|
|
|
|
return GetUniqueIdFromFile(GetFileHandle(), id, max_size); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
|
|
|
|
|
|
// WinWritableImpl
|
|
|
|
|
|
|
|
//
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
inline |
|
|
|
|
|
|
|
Status WinWritableImpl::PreallocateInternal(uint64_t spaceToReserve) { |
|
|
|
|
|
|
|
return fallocate(file_data_->GetName(), file_data_->GetFileHandle(), spaceToReserve); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
WinWritableImpl::WinWritableImpl(WinFileData* file_data, size_t alignment) |
|
|
|
|
|
|
|
: file_data_(file_data), |
|
|
|
|
|
|
|
alignment_(alignment), |
|
|
|
|
|
|
|
filesize_(0), |
|
|
|
|
|
|
|
reservedsize_(0) { |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Status WinWritableImpl::AppendImpl(const Slice& data) { |
|
|
|
|
|
|
|
|
|
|
|
// Used for buffered access ONLY
|
|
|
|
// Used for buffered access ONLY
|
|
|
|
assert(use_os_buffer_); |
|
|
|
assert(file_data_->UseOSBuffer()); |
|
|
|
assert(data.size() < std::numeric_limits<DWORD>::max()); |
|
|
|
assert(data.size() < std::numeric_limits<DWORD>::max()); |
|
|
|
|
|
|
|
|
|
|
|
Status s; |
|
|
|
Status s; |
|
|
|
|
|
|
|
|
|
|
|
DWORD bytesWritten = 0; |
|
|
|
DWORD bytesWritten = 0; |
|
|
|
if (!WriteFile(hFile_, data.data(), |
|
|
|
if (!WriteFile(file_data_->GetFileHandle(), data.data(), |
|
|
|
static_cast<DWORD>(data.size()), &bytesWritten, NULL)) { |
|
|
|
static_cast<DWORD>(data.size()), &bytesWritten, NULL)) { |
|
|
|
auto lastError = GetLastError(); |
|
|
|
auto lastError = GetLastError(); |
|
|
|
s = IOErrorFromWindowsError( |
|
|
|
s = IOErrorFromWindowsError( |
|
|
|
"Failed to WriteFile: " + filename_, |
|
|
|
"Failed to WriteFile: " + file_data_->GetName(), |
|
|
|
lastError); |
|
|
|
lastError); |
|
|
|
} else { |
|
|
|
} |
|
|
|
|
|
|
|
else { |
|
|
|
assert(size_t(bytesWritten) == data.size()); |
|
|
|
assert(size_t(bytesWritten) == data.size()); |
|
|
|
filesize_ += data.size(); |
|
|
|
filesize_ += data.size(); |
|
|
|
} |
|
|
|
} |
|
|
@ -846,86 +872,77 @@ Status WinWritableFile::Append(const Slice& data) { |
|
|
|
return s; |
|
|
|
return s; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
Status WinWritableFile::PositionedAppend(const Slice& data, uint64_t offset) { |
|
|
|
Status WinWritableImpl::PositionedAppendImpl(const Slice& data, uint64_t offset) { |
|
|
|
Status s; |
|
|
|
Status s; |
|
|
|
|
|
|
|
|
|
|
|
SSIZE_T ret = pwrite(hFile_, data.data(), data.size(), offset); |
|
|
|
SSIZE_T ret = pwrite(file_data_->GetFileHandle(), data.data(), data.size(), offset); |
|
|
|
|
|
|
|
|
|
|
|
// Error break
|
|
|
|
// Error break
|
|
|
|
if (ret < 0) { |
|
|
|
if (ret < 0) { |
|
|
|
auto lastError = GetLastError(); |
|
|
|
auto lastError = GetLastError(); |
|
|
|
s = IOErrorFromWindowsError( |
|
|
|
s = IOErrorFromWindowsError( |
|
|
|
"Failed to pwrite for: " + filename_, lastError); |
|
|
|
"Failed to pwrite for: " + file_data_->GetName(), lastError); |
|
|
|
} else { |
|
|
|
} |
|
|
|
// With positional write it is not clear at all
|
|
|
|
else { |
|
|
|
// if this actually extends the filesize
|
|
|
|
|
|
|
|
assert(size_t(ret) == data.size()); |
|
|
|
assert(size_t(ret) == data.size()); |
|
|
|
filesize_ += data.size(); |
|
|
|
// For sequential write this would be simple
|
|
|
|
|
|
|
|
// size extension by data.size()
|
|
|
|
|
|
|
|
uint64_t write_end = offset + data.size(); |
|
|
|
|
|
|
|
if (write_end >= filesize_) { |
|
|
|
|
|
|
|
filesize_ = write_end; |
|
|
|
|
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
return s; |
|
|
|
return s; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
// Need to implement this so the file is truncated correctly
|
|
|
|
// Need to implement this so the file is truncated correctly
|
|
|
|
// when buffered and unbuffered mode
|
|
|
|
// when buffered and unbuffered mode
|
|
|
|
Status WinWritableFile::Truncate(uint64_t size) { |
|
|
|
inline |
|
|
|
Status s = ftruncate(filename_, hFile_, size); |
|
|
|
Status WinWritableImpl::TruncateImpl(uint64_t size) { |
|
|
|
|
|
|
|
Status s = ftruncate(file_data_->GetName(), file_data_->GetFileHandle(), |
|
|
|
|
|
|
|
size); |
|
|
|
if (s.ok()) { |
|
|
|
if (s.ok()) { |
|
|
|
filesize_ = size; |
|
|
|
filesize_ = size; |
|
|
|
} |
|
|
|
} |
|
|
|
return s; |
|
|
|
return s; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
Status WinWritableFile::Close() { |
|
|
|
Status WinWritableImpl::CloseImpl() { |
|
|
|
|
|
|
|
|
|
|
|
Status s; |
|
|
|
Status s; |
|
|
|
|
|
|
|
|
|
|
|
assert(INVALID_HANDLE_VALUE != hFile_); |
|
|
|
auto hFile = file_data_->GetFileHandle(); |
|
|
|
|
|
|
|
assert(INVALID_HANDLE_VALUE != hFile); |
|
|
|
|
|
|
|
|
|
|
|
if (fsync(hFile_) < 0) { |
|
|
|
if (fsync(hFile) < 0) { |
|
|
|
auto lastError = GetLastError(); |
|
|
|
auto lastError = GetLastError(); |
|
|
|
s = IOErrorFromWindowsError("fsync failed at Close() for: " + filename_, |
|
|
|
s = IOErrorFromWindowsError("fsync failed at Close() for: " + |
|
|
|
|
|
|
|
file_data_->GetName(), |
|
|
|
lastError); |
|
|
|
lastError); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
if (FALSE == ::CloseHandle(hFile_)) { |
|
|
|
if(!file_data_->CloseFile()) { |
|
|
|
auto lastError = GetLastError(); |
|
|
|
auto lastError = GetLastError(); |
|
|
|
s = IOErrorFromWindowsError("CloseHandle failed for: " + filename_, |
|
|
|
s = IOErrorFromWindowsError("CloseHandle failed for: " + file_data_->GetName(), |
|
|
|
lastError); |
|
|
|
lastError); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
hFile_ = INVALID_HANDLE_VALUE; |
|
|
|
|
|
|
|
return s; |
|
|
|
return s; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
// write out the cached data to the OS cache
|
|
|
|
Status WinWritableImpl::SyncImpl() { |
|
|
|
// This is now taken care of the WritableFileWriter
|
|
|
|
|
|
|
|
Status WinWritableFile::Flush() { |
|
|
|
|
|
|
|
return Status::OK(); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Status WinWritableFile::Sync() { |
|
|
|
|
|
|
|
Status s; |
|
|
|
Status s; |
|
|
|
// Calls flush buffers
|
|
|
|
// Calls flush buffers
|
|
|
|
if (fsync(hFile_) < 0) { |
|
|
|
if (fsync(file_data_->GetFileHandle()) < 0) { |
|
|
|
auto lastError = GetLastError(); |
|
|
|
auto lastError = GetLastError(); |
|
|
|
s = IOErrorFromWindowsError("fsync failed at Sync() for: " + filename_, |
|
|
|
s = IOErrorFromWindowsError("fsync failed at Sync() for: " +
|
|
|
|
|
|
|
|
file_data_->GetName(), |
|
|
|
lastError); |
|
|
|
lastError); |
|
|
|
} |
|
|
|
} |
|
|
|
return s; |
|
|
|
return s; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
Status WinWritableFile::Fsync() { return Sync(); } |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
uint64_t WinWritableFile::GetFileSize() { |
|
|
|
|
|
|
|
// Double accounting now here with WritableFileWriter
|
|
|
|
|
|
|
|
// and this size will be wrong when unbuffered access is used
|
|
|
|
|
|
|
|
// but tests implement their own writable files and do not use WritableFileWrapper
|
|
|
|
|
|
|
|
// so we need to squeeze a square peg through
|
|
|
|
|
|
|
|
// a round hole here.
|
|
|
|
|
|
|
|
return filesize_; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Status WinWritableFile::Allocate(uint64_t offset, uint64_t len) { |
|
|
|
Status WinWritableImpl::AllocateImpl(uint64_t offset, uint64_t len) { |
|
|
|
Status status; |
|
|
|
Status status; |
|
|
|
TEST_KILL_RANDOM("WinWritableFile::Allocate", rocksdb_kill_odds); |
|
|
|
TEST_KILL_RANDOM("WinWritableFile::Allocate", rocksdb_kill_odds); |
|
|
|
|
|
|
|
|
|
|
@ -946,18 +963,135 @@ Status WinWritableFile::Allocate(uint64_t offset, uint64_t len) { |
|
|
|
return status; |
|
|
|
return status; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
|
|
|
|
|
|
/// WinWritableFile
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
WinWritableFile::WinWritableFile(const std::string& fname, HANDLE hFile, size_t alignment, |
|
|
|
|
|
|
|
size_t /* capacity */, const EnvOptions& options) |
|
|
|
|
|
|
|
: WinFileData(fname, hFile, options.use_os_buffer), |
|
|
|
|
|
|
|
WinWritableImpl(this, alignment) { |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
assert(!options.use_mmap_writes); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
WinWritableFile::~WinWritableFile() { |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// Indicates if the class makes use of unbuffered I/O
|
|
|
|
|
|
|
|
bool WinWritableFile::UseOSBuffer() const { |
|
|
|
|
|
|
|
return WinFileData::UseOSBuffer(); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
size_t WinWritableFile::GetRequiredBufferAlignment() const { |
|
|
|
|
|
|
|
return GetAlignement(); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Status WinWritableFile::Append(const Slice& data) { |
|
|
|
|
|
|
|
return AppendImpl(data); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Status WinWritableFile::PositionedAppend(const Slice& data, uint64_t offset) { |
|
|
|
|
|
|
|
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) { |
|
|
|
|
|
|
|
return TruncateImpl(size); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Status WinWritableFile::Close() { |
|
|
|
|
|
|
|
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(); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Status WinWritableFile::Sync() { |
|
|
|
|
|
|
|
return SyncImpl(); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Status WinWritableFile::Fsync() {
|
|
|
|
|
|
|
|
return SyncImpl(); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
uint64_t WinWritableFile::GetFileSize() { |
|
|
|
|
|
|
|
return GetFileSizeImpl(); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Status WinWritableFile::Allocate(uint64_t offset, uint64_t len) { |
|
|
|
|
|
|
|
return AllocateImpl(offset, len); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
size_t WinWritableFile::GetUniqueId(char* id, size_t max_size) const { |
|
|
|
size_t WinWritableFile::GetUniqueId(char* id, size_t max_size) const { |
|
|
|
return GetUniqueIdFromFile(hFile_, id, max_size); |
|
|
|
return GetUniqueIdFromFile(GetFileHandle(), id, max_size); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/////////////////////////////////////////////////////////////////////////
|
|
|
|
|
|
|
|
/// WinRandomRWFile
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
WinRandomRWFile::WinRandomRWFile(const std::string& fname, HANDLE hFile, size_t alignment, |
|
|
|
|
|
|
|
const EnvOptions& options) : |
|
|
|
|
|
|
|
WinFileData(fname, hFile, options.use_os_buffer), |
|
|
|
|
|
|
|
WinRandomAccessImpl(this, alignment, options), |
|
|
|
|
|
|
|
WinWritableImpl(this, alignment) { |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
bool WinRandomRWFile::UseOSBuffer() const { |
|
|
|
|
|
|
|
return WinFileData::UseOSBuffer(); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
size_t WinRandomRWFile::GetRequiredBufferAlignment() const { |
|
|
|
|
|
|
|
return GetAlignement(); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
bool WinRandomRWFile::ShouldForwardRawRequest() const { |
|
|
|
|
|
|
|
return true; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
void WinRandomRWFile::EnableReadAhead() { |
|
|
|
|
|
|
|
HintImpl(RandomAccessFile::SEQUENTIAL); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Status WinRandomRWFile::Write(uint64_t offset, const Slice & data) { |
|
|
|
|
|
|
|
return PositionedAppendImpl(data, offset); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Status WinRandomRWFile::Read(uint64_t offset, size_t n, Slice * result,
|
|
|
|
|
|
|
|
char * scratch) const { |
|
|
|
|
|
|
|
return ReadImpl(offset, n, result, scratch); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Status WinRandomRWFile::Flush() { |
|
|
|
|
|
|
|
return Status::OK(); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Status WinRandomRWFile::Sync() { |
|
|
|
|
|
|
|
return SyncImpl(); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Status WinRandomRWFile::Close() { |
|
|
|
|
|
|
|
return CloseImpl(); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
|
|
|
|
|
|
/// WinDirectory
|
|
|
|
|
|
|
|
|
|
|
|
Status WinDirectory::Fsync() { return Status::OK(); } |
|
|
|
Status WinDirectory::Fsync() { return Status::OK(); } |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
|
|
|
|
|
|
/// WinFileLock
|
|
|
|
|
|
|
|
|
|
|
|
WinFileLock::~WinFileLock() { |
|
|
|
WinFileLock::~WinFileLock() { |
|
|
|
BOOL ret = ::CloseHandle(hFile_); |
|
|
|
BOOL ret = ::CloseHandle(hFile_); |
|
|
|
assert(ret); |
|
|
|
assert(ret); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|