@ -20,28 +20,24 @@ namespace ROCKSDB_NAMESPACE {
namespace port {
namespace port {
/*
/*
* DirectIOHelper
* DirectIOHelper
*/
*/
namespace {
namespace {
const size_t kSectorSize = 512 ;
const size_t kSectorSize = 512 ;
inline
inline bool IsPowerOfTwo ( const size_t alignment ) {
bool IsPowerOfTwo ( const size_t alignment ) {
return ( ( alignment ) & ( alignment - 1 ) ) = = 0 ;
return ( ( alignment ) & ( alignment - 1 ) ) = = 0 ;
}
}
inline
inline bool IsSectorAligned ( const size_t off ) {
bool IsSectorAligned ( const size_t off ) {
return ( off & ( kSectorSize - 1 ) ) = = 0 ;
return ( off & ( kSectorSize - 1 ) ) = = 0 ;
}
}
inline
inline bool IsAligned ( size_t alignment , const void * ptr ) {
bool IsAligned ( size_t alignment , const void * ptr ) {
return ( ( uintptr_t ( ptr ) ) & ( alignment - 1 ) ) = = 0 ;
return ( ( uintptr_t ( ptr ) ) & ( alignment - 1 ) ) = = 0 ;
}
}
}
} // namespace
std : : string GetWindowsErrSz ( DWORD err ) {
std : : string GetWindowsErrSz ( DWORD err ) {
LPSTR lpMsgBuf ;
LPSTR lpMsgBuf ;
@ -69,21 +65,20 @@ std::string GetWindowsErrSz(DWORD err) {
// Because all the reads/writes happen by the specified offset, the caller in
// Because all the reads/writes happen by the specified offset, the caller in
// theory should not
// theory should not
// rely on the current file offset.
// rely on the current file offset.
Status pwrite ( const WinFileData * file_data , const Slice & data ,
IO Status pwrite ( const WinFileData * file_data , const Slice & data ,
uint64_t offset , size_t & bytes_written ) {
uint64_t offset , size_t & bytes_written ) {
IOStatus s ;
Status s ;
bytes_written = 0 ;
bytes_written = 0 ;
size_t num_bytes = data . size ( ) ;
size_t num_bytes = data . size ( ) ;
if ( num_bytes > std : : numeric_limits < DWORD > : : max ( ) ) {
if ( num_bytes > std : : numeric_limits < DWORD > : : max ( ) ) {
// May happen in 64-bit builds where size_t is 64-bits but
// 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
// 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: " +
return IO Status: : InvalidArgument (
file_data - > GetName ( ) ) ;
" num_bytes is too large for a single write: " + file_data - > GetName ( ) ) ;
}
}
OVERLAPPED overlapped = { 0 } ;
OVERLAPPED overlapped = { 0 } ;
ULARGE_INTEGER offsetUnion ;
ULARGE_INTEGER offsetUnion ;
offsetUnion . QuadPart = offset ;
offsetUnion . QuadPart = offset ;
@ -92,8 +87,9 @@ Status pwrite(const WinFileData* file_data, const Slice& data,
DWORD bytesWritten = 0 ;
DWORD bytesWritten = 0 ;
if ( FALSE = = WriteFile ( file_data - > GetFileHandle ( ) , data . data ( ) , static_cast < DWORD > ( num_bytes ) ,
if ( FALSE = = WriteFile ( file_data - > GetFileHandle ( ) , data . data ( ) ,
& bytesWritten , & overlapped ) ) {
static_cast < DWORD > ( num_bytes ) , & bytesWritten ,
& overlapped ) ) {
auto lastError = GetLastError ( ) ;
auto lastError = GetLastError ( ) ;
s = IOErrorFromWindowsError ( " WriteFile failed: " + file_data - > GetName ( ) ,
s = IOErrorFromWindowsError ( " WriteFile failed: " + file_data - > GetName ( ) ,
lastError ) ;
lastError ) ;
@ -105,18 +101,17 @@ Status pwrite(const WinFileData* file_data, const Slice& data,
}
}
// See comments for pwrite above
// See comments for pwrite above
Status pread ( const WinFileData * file_data , char * src , size_t num_bytes ,
IO Status pread ( const WinFileData * file_data , char * src , size_t num_bytes ,
uint64_t offset , size_t & bytes_read ) {
uint64_t offset , size_t & bytes_read ) {
IOStatus s ;
Status s ;
bytes_read = 0 ;
bytes_read = 0 ;
if ( num_bytes > std : : numeric_limits < DWORD > : : max ( ) ) {
if ( num_bytes > std : : numeric_limits < DWORD > : : max ( ) ) {
return Status : : InvalidArgument ( " num_bytes is too large for a single read: " +
return IO Status: : InvalidArgument (
file_data - > GetName ( ) ) ;
" num_bytes is too large for a single read: " + file_data - > GetName ( ) ) ;
}
}
OVERLAPPED overlapped = { 0 } ;
OVERLAPPED overlapped = { 0 } ;
ULARGE_INTEGER offsetUnion ;
ULARGE_INTEGER offsetUnion ;
offsetUnion . QuadPart = offset ;
offsetUnion . QuadPart = offset ;
@ -125,8 +120,9 @@ Status pread(const WinFileData* file_data, char* src, size_t num_bytes,
DWORD bytesRead = 0 ;
DWORD bytesRead = 0 ;
if ( FALSE = = ReadFile ( file_data - > GetFileHandle ( ) , src , static_cast < DWORD > ( num_bytes ) ,
if ( FALSE = = ReadFile ( file_data - > GetFileHandle ( ) , src ,
& bytesRead , & overlapped ) ) {
static_cast < DWORD > ( num_bytes ) , & bytesRead ,
& overlapped ) ) {
auto lastError = GetLastError ( ) ;
auto lastError = GetLastError ( ) ;
// EOF is OK with zero bytes read
// EOF is OK with zero bytes read
if ( lastError ! = ERROR_HANDLE_EOF ) {
if ( lastError ! = ERROR_HANDLE_EOF ) {
@ -143,9 +139,9 @@ Status pread(const WinFileData* file_data, char* src, size_t num_bytes,
// SetFileInformationByHandle() is capable of fast pre-allocates.
// SetFileInformationByHandle() is capable of fast pre-allocates.
// However, this does not change the file end position unless the file is
// 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.
// truncated and the pre-allocated space is not considered filled with zeros.
Status fallocate ( const std : : string & filename , HANDLE hFile ,
IO Status fallocate ( const std : : string & filename , HANDLE hFile ,
uint64_t to_size ) {
uint64_t to_size ) {
Status status ;
IO Status status ;
FILE_ALLOCATION_INFO alloc_info ;
FILE_ALLOCATION_INFO alloc_info ;
alloc_info . AllocationSize . QuadPart = to_size ;
alloc_info . AllocationSize . QuadPart = to_size ;
@ -160,9 +156,8 @@ Status fallocate(const std::string& filename, HANDLE hFile,
return status ;
return status ;
}
}
Status ftruncate ( const std : : string & filename , HANDLE hFile ,
IOStatus ftruncate ( const std : : string & filename , HANDLE hFile , uint64_t toSize ) {
uint64_t toSize ) {
IOStatus status ;
Status status ;
FILE_END_OF_FILE_INFO end_of_file ;
FILE_END_OF_FILE_INFO end_of_file ;
end_of_file . EndOfFile . QuadPart = toSize ;
end_of_file . EndOfFile . QuadPart = toSize ;
@ -212,9 +207,11 @@ WinMmapReadableFile::~WinMmapReadableFile() {
assert ( ret ) ;
assert ( ret ) ;
}
}
Status WinMmapReadableFile : : Read ( uint64_t offset , size_t n , Slice * result ,
IOStatus WinMmapReadableFile : : Read ( uint64_t offset , size_t n ,
char * scratch ) const {
const IOOptions & /*options*/ , Slice * result ,
Status s ;
char * scratch ,
IODebugContext * /*dbg*/ ) const {
IOStatus s ;
if ( offset > length_ ) {
if ( offset > length_ ) {
* result = Slice ( ) ;
* result = Slice ( ) ;
@ -222,13 +219,12 @@ Status WinMmapReadableFile::Read(uint64_t offset, size_t n, Slice* result,
} else if ( offset + n > length_ ) {
} else if ( offset + n > length_ ) {
n = length_ - static_cast < size_t > ( offset ) ;
n = length_ - static_cast < size_t > ( offset ) ;
}
}
* result =
* result = Slice ( reinterpret_cast < const char * > ( mapped_region_ ) + offset , n ) ;
Slice ( reinterpret_cast < const char * > ( mapped_region_ ) + offset , n ) ;
return s ;
return s ;
}
}
Status WinMmapReadableFile : : InvalidateCache ( size_t offset , size_t length ) {
IO Status WinMmapReadableFile : : InvalidateCache ( size_t offset , size_t length ) {
return Status : : OK ( ) ;
return IO Status: : OK ( ) ;
}
}
size_t WinMmapReadableFile : : GetUniqueId ( char * id , size_t max_size ) const {
size_t WinMmapReadableFile : : GetUniqueId ( char * id , size_t max_size ) const {
@ -238,15 +234,14 @@ size_t WinMmapReadableFile::GetUniqueId(char* id, size_t max_size) const {
///////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////
/// WinMmapFile
/// 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 ) {
IO Status WinMmapFile : : TruncateFile ( uint64_t toSize ) {
return ftruncate ( filename_ , hFile_ , toSize ) ;
return ftruncate ( filename_ , hFile_ , toSize ) ;
}
}
Status WinMmapFile : : UnmapCurrentRegion ( ) {
IO Status WinMmapFile : : UnmapCurrentRegion ( ) {
Status status ;
IO Status status ;
if ( mapped_begin_ ! = nullptr ) {
if ( mapped_begin_ ! = nullptr ) {
if ( ! : : UnmapViewOfFile ( mapped_begin_ ) ) {
if ( ! : : UnmapViewOfFile ( mapped_begin_ ) ) {
@ -271,16 +266,16 @@ Status WinMmapFile::UnmapCurrentRegion() {
return status ;
return status ;
}
}
Status WinMmapFile : : MapNewRegion ( ) {
IO Status WinMmapFile : : MapNewRegion ( const IOOptions & options ,
IODebugContext * dbg ) {
Status status ;
IO Status status ;
assert ( mapped_begin_ = = nullptr ) ;
assert ( mapped_begin_ = = nullptr ) ;
size_t minDiskSize = static_cast < size_t > ( file_offset_ ) + view_size_ ;
size_t minDiskSize = static_cast < size_t > ( file_offset_ ) + view_size_ ;
if ( minDiskSize > reserved_size_ ) {
if ( minDiskSize > reserved_size_ ) {
status = Allocate ( file_offset_ , view_size_ ) ;
status = Allocate ( file_offset_ , view_size_ , options , dbg ) ;
if ( ! status . ok ( ) ) {
if ( ! status . ok ( ) ) {
return status ;
return status ;
}
}
@ -288,7 +283,6 @@ Status WinMmapFile::MapNewRegion() {
// Need to remap
// Need to remap
if ( hMap_ = = NULL | | reserved_size_ > mapping_size_ ) {
if ( hMap_ = = NULL | | reserved_size_ > mapping_size_ ) {
if ( hMap_ ! = NULL ) {
if ( hMap_ ! = NULL ) {
// Unmap the previous one
// Unmap the previous one
BOOL ret __attribute__ ( ( __unused__ ) ) ;
BOOL ret __attribute__ ( ( __unused__ ) ) ;
@ -339,15 +333,15 @@ Status WinMmapFile::MapNewRegion() {
return status ;
return status ;
}
}
Status WinMmapFile : : PreallocateInternal ( uint64_t spaceToReserve ) {
IO Status WinMmapFile : : PreallocateInternal ( uint64_t spaceToReserve ) {
return fallocate ( filename_ , hFile_ , spaceToReserve ) ;
return fallocate ( filename_ , hFile_ , spaceToReserve ) ;
}
}
WinMmapFile : : WinMmapFile ( const std : : string & fname , HANDLE hFile ,
WinMmapFile : : WinMmapFile ( const std : : string & fname , HANDLE hFile ,
size_t page_size , size_t allocation_granularity ,
size_t page_size , size_t allocation_granularity ,
const Env Options& options )
const File Options& options )
: WinFileData ( fname , hFile , false ) ,
: WinFileData ( fname , hFile , false ) ,
WritableFile ( options ) ,
FS WritableFile( options ) ,
hMap_ ( NULL ) ,
hMap_ ( NULL ) ,
page_size_ ( page_size ) ,
page_size_ ( page_size ) ,
allocation_granularity_ ( allocation_granularity ) ,
allocation_granularity_ ( allocation_granularity ) ,
@ -373,17 +367,19 @@ WinMmapFile::WinMmapFile(const std::string& fname, HANDLE hFile,
// View size must be both the multiple of allocation_granularity AND the
// 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.
// 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_ ) ;
view_size_ = Roundup ( viewSize , allocation_granularity_ ) ;
}
}
WinMmapFile : : ~ WinMmapFile ( ) {
WinMmapFile : : ~ WinMmapFile ( ) {
if ( hFile_ ) {
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 ( ) ;
const char * src = data . data ( ) ;
size_t left = data . size ( ) ;
size_t left = data . size ( ) ;
@ -392,9 +388,9 @@ Status WinMmapFile::Append(const Slice& data) {
size_t avail = mapped_end_ - dst_ ;
size_t avail = mapped_end_ - dst_ ;
if ( avail = = 0 ) {
if ( avail = = 0 ) {
Status s = UnmapCurrentRegion ( ) ;
IO Status s = UnmapCurrentRegion ( ) ;
if ( s . ok ( ) ) {
if ( s . ok ( ) ) {
s = MapNewRegion ( ) ;
s = MapNewRegion ( options , dbg ) ;
}
}
if ( ! s . ok ( ) ) {
if ( ! s . ok ( ) ) {
@ -416,30 +412,31 @@ Status WinMmapFile::Append(const Slice& data) {
memset ( dst_ , 0 , bytesToPad ) ;
memset ( dst_ , 0 , bytesToPad ) ;
}
}
return Status : : OK ( ) ;
return IO Status: : OK ( ) ;
}
}
// Means Close() will properly take care of truncate
// Means Close() will properly take care of truncate
// and it does not need any additional information
// and it does not need any additional information
Status WinMmapFile : : Truncate ( uint64_t size ) {
IOStatus WinMmapFile : : Truncate ( uint64_t size , const IOOptions & /*options*/ ,
return Status : : OK ( ) ;
IODebugContext * /*dbg*/ ) {
return IOStatus : : OK ( ) ;
}
}
Status WinMmapFile : : Close ( ) {
IO Status WinMmapFile : : Close ( const IOOptions & options , IODebugContext * dbg ) {
Status s ;
IO Status s ;
assert ( NULL ! = hFile_ ) ;
assert ( NULL ! = hFile_ ) ;
// We truncate to the precise size so no
// We truncate to the precise size so no
// uninitialized data at the end. SetEndOfFile
// uninitialized data at the end. SetEndOfFile
// which we use does not write zeros and it is good.
// 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 ) {
if ( mapped_begin_ ! = nullptr ) {
// Sync before unmapping to make sure everything
// Sync before unmapping to make sure everything
// is on disk and there is not a lazy writing
// is on disk and there is not a lazy writing
// so we are deterministic with the tests
// so we are deterministic with the tests
Sync ( ) ;
Sync ( options , dbg ) ;
s = UnmapCurrentRegion ( ) ;
s = UnmapCurrentRegion ( ) ;
}
}
@ -455,7 +452,6 @@ Status WinMmapFile::Close() {
}
}
if ( hFile_ ! = NULL ) {
if ( hFile_ ! = NULL ) {
TruncateFile ( targetSize ) ;
TruncateFile ( targetSize ) ;
BOOL ret = : : CloseHandle ( hFile_ ) ;
BOOL ret = : : CloseHandle ( hFile_ ) ;
@ -471,11 +467,15 @@ Status WinMmapFile::Close() {
return s ;
return s ;
}
}
Status WinMmapFile : : Flush ( ) { return Status : : OK ( ) ; }
IOStatus WinMmapFile : : Flush ( const IOOptions & /*options*/ ,
IODebugContext * /*dbg*/ ) {
return IOStatus : : OK ( ) ;
}
// Flush only data
// Flush only data
Status WinMmapFile : : Sync ( ) {
IOStatus WinMmapFile : : Sync ( const IOOptions & /*options*/ ,
Status s ;
IODebugContext * /*dbg*/ ) {
IOStatus s ;
// Some writes occurred since last sync
// Some writes occurred since last sync
if ( dst_ > last_sync_ ) {
if ( dst_ > last_sync_ ) {
@ -503,10 +503,10 @@ Status WinMmapFile::Sync() {
}
}
/**
/**
* Flush data as well as metadata to stable storage .
* Flush data as well as metadata to stable storage .
*/
*/
Status WinMmapFile : : Fsync ( ) {
IO Status WinMmapFile : : Fsync ( const IOOptions & options , IODebugContext * dbg ) {
Status s = Sync ( ) ;
IO Status s = Sync ( options , dbg ) ;
// Flush metadata
// Flush metadata
if ( s . ok ( ) & & pending_sync_ ) {
if ( s . ok ( ) & & pending_sync_ ) {
@ -521,27 +521,31 @@ Status WinMmapFile::Fsync() {
}
}
/**
/**
* Get the size of valid data in the file . This will not match the
* 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
* size that is returned from the filesystem because we use mmap
* to extend file by map_size every time .
* to extend file by map_size every time .
*/
*/
uint64_t WinMmapFile : : GetFileSize ( ) {
uint64_t WinMmapFile : : GetFileSize ( const IOOptions & /*options*/ ,
IODebugContext * /*dbg*/ ) {
size_t used = dst_ - mapped_begin_ ;
size_t used = dst_ - mapped_begin_ ;
return file_offset_ + used ;
return file_offset_ + used ;
}
}
Status WinMmapFile : : InvalidateCache ( size_t offset , size_t length ) {
IO Status WinMmapFile : : InvalidateCache ( size_t offset , size_t length ) {
return Status : : OK ( ) ;
return IO Status: : OK ( ) ;
}
}
Status WinMmapFile : : Allocate ( uint64_t offset , uint64_t len ) {
IOStatus WinMmapFile : : Allocate ( uint64_t offset , uint64_t len ,
Status status ;
const IOOptions & /*options*/ ,
IODebugContext * /*dbg*/ ) {
IOStatus status ;
TEST_KILL_RANDOM ( " WinMmapFile::Allocate " , rocksdb_kill_odds ) ;
TEST_KILL_RANDOM ( " WinMmapFile::Allocate " , rocksdb_kill_odds ) ;
// Make sure that we reserve an aligned amount of space
// Make sure that we reserve an aligned amount of space
// since the reservation block size is driven outside so we want
// since the reservation block size is driven outside so we want
// to check if we are ok with reservation here
// 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
// Nothing to do
if ( spaceToReserve < = reserved_size_ ) {
if ( spaceToReserve < = reserved_size_ ) {
return status ;
return status ;
@ -563,31 +567,34 @@ size_t WinMmapFile::GetUniqueId(char* id, size_t max_size) const {
// WinSequentialFile
// WinSequentialFile
WinSequentialFile : : WinSequentialFile ( const std : : string & fname , HANDLE f ,
WinSequentialFile : : WinSequentialFile ( const std : : string & fname , HANDLE f ,
const Env Options& options )
const File Options& options )
: WinFileData ( fname , f , options . use_direct_reads ) { }
: WinFileData ( fname , f , options . use_direct_reads ) { }
WinSequentialFile : : ~ WinSequentialFile ( ) {
WinSequentialFile : : ~ WinSequentialFile ( ) {
assert ( hFile_ ! = INVALID_HANDLE_VALUE ) ;
assert ( hFile_ ! = INVALID_HANDLE_VALUE ) ;
}
}
Status WinSequentialFile : : Read ( size_t n , Slice * result , char * scratch ) {
IOStatus WinSequentialFile : : Read ( size_t n , const IOOptions & /*opts*/ ,
Status s ;
Slice * result , char * scratch ,
IODebugContext * /*dbg*/ ) {
IOStatus s ;
size_t r = 0 ;
size_t r = 0 ;
assert ( result ! = nullptr ) ;
assert ( result ! = nullptr ) ;
if ( WinFileData : : use_direct_io ( ) ) {
if ( WinFileData : : use_direct_io ( ) ) {
return Status : : NotSupported ( " Read() does not support direct_io " ) ;
return IO Status: : NotSupported ( " Read() does not support direct_io " ) ;
}
}
// Windows ReadFile API accepts a DWORD.
// Windows ReadFile API accepts a DWORD.
// While it is possible to read in a loop if n is too big
// While it is possible to read in a loop if n is too big
// it is an unlikely case.
// it is an unlikely case.
if ( n > std : : numeric_limits < DWORD > : : max ( ) ) {
if ( n > std : : numeric_limits < DWORD > : : max ( ) ) {
return Status : : InvalidArgument ( " n is too big for a single ReadFile: "
return IO Status: : InvalidArgument ( " n is too big for a single ReadFile: " +
+ filename_ ) ;
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 ;
DWORD bytesRead = 0 ;
BOOL ret = ReadFile ( hFile_ , scratch , bytesToRead , & bytesRead , NULL ) ;
BOOL ret = ReadFile ( hFile_ , scratch , bytesToRead , & bytesRead , NULL ) ;
if ( ret ! = FALSE ) {
if ( ret ! = FALSE ) {
@ -595,8 +602,7 @@ Status WinSequentialFile::Read(size_t n, Slice* result, char* scratch) {
} else {
} else {
auto lastError = GetLastError ( ) ;
auto lastError = GetLastError ( ) ;
if ( lastError ! = ERROR_HANDLE_EOF ) {
if ( lastError ! = ERROR_HANDLE_EOF ) {
s = IOErrorFromWindowsError ( " ReadFile failed: " + filename_ ,
s = IOErrorFromWindowsError ( " ReadFile failed: " + filename_ , lastError ) ;
lastError ) ;
}
}
}
}
@ -604,99 +610,91 @@ Status WinSequentialFile::Read(size_t n, Slice* result, char* scratch) {
return s ;
return s ;
}
}
Status WinSequentialFile : : PositionedReadInternal ( char * src , size_t numBytes ,
IOStatus WinSequentialFile : : PositionedReadInternal ( char * src , size_t numBytes ,
uint64_t offset , size_t & bytes_read ) const {
uint64_t offset ,
size_t & bytes_read ) const {
return pread ( this , src , numBytes , offset , bytes_read ) ;
return pread ( this , src , numBytes , offset , bytes_read ) ;
}
}
Status WinSequentialFile : : PositionedRead ( uint64_t offset , size_t n , Slice * result ,
IOStatus WinSequentialFile : : PositionedRead ( uint64_t offset , size_t n ,
char * scratch ) {
const IOOptions & /*opts*/ ,
Slice * result , char * scratch ,
Status s ;
IODebugContext * /*dbg*/ ) {
if ( ! WinFileData : : use_direct_io ( ) ) {
if ( ! WinFileData : : use_direct_io ( ) ) {
return Status : : NotSupported ( " This function is only used for direct_io " ) ;
return IO Status: : NotSupported ( " This function is only used for direct_io " ) ;
}
}
if ( ! IsSectorAligned ( static_cast < size_t > ( offset ) ) | |
if ( ! IsSectorAligned ( static_cast < size_t > ( offset ) ) | | ! IsSectorAligned ( n ) ) {
! IsSectorAligned ( n ) ) {
return IOStatus : : InvalidArgument (
return Status : : InvalidArgument (
" WinSequentialFile::PositionedRead: offset is not properly aligned " ) ;
" WinSequentialFile::PositionedRead: offset is not properly aligned " ) ;
}
}
size_t bytes_read = 0 ; // out param
size_t bytes_read = 0 ; // out param
s = PositionedReadInternal ( scratch , static_cast < size_t > ( n ) , offset , bytes_read ) ;
IOStatus s = PositionedReadInternal ( scratch , static_cast < size_t > ( n ) , offset ,
bytes_read ) ;
* result = Slice ( scratch , bytes_read ) ;
* result = Slice ( scratch , bytes_read ) ;
return s ;
return s ;
}
}
IOStatus WinSequentialFile : : Skip ( uint64_t n ) {
Status WinSequentialFile : : Skip ( uint64_t n ) {
// Can't handle more than signed max as SetFilePointerEx accepts a signed
// Can't handle more than signed max as SetFilePointerEx accepts a signed 64-bit
// 64-bit integer. As such it is a highly unlikley case to have n so large.
// 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 ( ) ) ) {
if ( n > static_cast < uint64_t > ( std : : numeric_limits < LONGLONG > : : max ( ) ) ) {
return Status : : InvalidArgument ( " n is too large for a single SetFilePointerEx() call " +
return IO Status: : InvalidArgument (
filename_ ) ;
" n is too large for a single SetFilePointerEx() call " + filename_ ) ;
}
}
LARGE_INTEGER li ;
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 ) ;
BOOL ret = SetFilePointerEx ( hFile_ , li , NULL , FILE_CURRENT ) ;
if ( ret = = FALSE ) {
if ( ret = = FALSE ) {
auto lastError = GetLastError ( ) ;
auto lastError = GetLastError ( ) ;
return IOErrorFromWindowsError ( " Skip SetFilePointerEx(): " + filename_ ,
return IOErrorFromWindowsError ( " Skip SetFilePointerEx(): " + filename_ ,
lastError ) ;
lastError ) ;
}
}
return Status : : OK ( ) ;
return IO Status: : OK ( ) ;
}
}
Status WinSequentialFile : : InvalidateCache ( size_t offset , size_t length ) {
IO Status WinSequentialFile : : InvalidateCache ( size_t offset , size_t length ) {
return Status : : OK ( ) ;
return IO Status: : OK ( ) ;
}
}
//////////////////////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////////////////////////
/// WinRandomAccessBase
/// WinRandomAccessBase
inline
inline IOStatus WinRandomAccessImpl : : PositionedReadInternal (
Status WinRandomAccessImpl : : PositionedReadInternal ( char * src ,
char * src , size_t numBytes , uint64_t offset , size_t & bytes_read ) const {
size_t numBytes ,
uint64_t offset ,
size_t & bytes_read ) const {
return pread ( file_base_ , src , numBytes , offset , bytes_read ) ;
return pread ( file_base_ , src , numBytes , offset , bytes_read ) ;
}
}
inline
inline WinRandomAccessImpl : : WinRandomAccessImpl ( WinFileData * file_base ,
WinRandomAccessImpl : : WinRandomAccessImpl ( WinFileData * file_base ,
size_t alignment ,
size_t alignment ,
const EnvOptions & options ) :
const FileOptions & options )
file_base_ ( file_base ) ,
: file_base_ ( file_base ) , alignment_ ( alignment ) {
alignment_ ( alignment ) {
assert ( ! options . use_mmap_reads ) ;
assert ( ! options . use_mmap_reads ) ;
}
}
inline
inline IOStatus WinRandomAccessImpl : : ReadImpl ( uint64_t offset , size_t n ,
Status WinRandomAccessImpl : : ReadImpl ( uint64_t offset , size_t n , Slice * result ,
Slice * result ,
char * scratch ) const {
char * scratch ) const {
Status s ;
// Check buffer alignment
// Check buffer alignment
if ( file_base_ - > use_direct_io ( ) ) {
if ( file_base_ - > use_direct_io ( ) ) {
if ( ! IsSectorAligned ( static_cast < size_t > ( offset ) ) | |
if ( ! IsSectorAligned ( static_cast < size_t > ( offset ) ) | |
! IsAligned ( alignment_ , scratch ) ) {
! IsAligned ( alignment_ , scratch ) ) {
return Status : : InvalidArgument (
return IOStatus : : InvalidArgument (
" WinRandomAccessImpl::ReadImpl: offset or scratch is not properly aligned " ) ;
" WinRandomAccessImpl::ReadImpl: offset or scratch is not properly "
" aligned " ) ;
}
}
}
}
if ( n = = 0 ) {
if ( n = = 0 ) {
* result = Slice ( scratch , 0 ) ;
* result = Slice ( scratch , 0 ) ;
return s ;
return IOStatu s: : OK ( ) ;
}
}
size_t bytes_read = 0 ;
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 ) ;
* result = Slice ( scratch , bytes_read ) ;
return s ;
return s ;
}
}
@ -706,20 +704,21 @@ Status WinRandomAccessImpl::ReadImpl(uint64_t offset, size_t n, Slice* result,
WinRandomAccessFile : : WinRandomAccessFile ( const std : : string & fname , HANDLE hFile ,
WinRandomAccessFile : : WinRandomAccessFile ( const std : : string & fname , HANDLE hFile ,
size_t alignment ,
size_t alignment ,
const Env Options& options )
const File Options& options )
: WinFileData ( fname , hFile , options . use_direct_reads ) ,
: WinFileData ( fname , hFile , options . use_direct_reads ) ,
WinRandomAccessImpl ( this , alignment , options ) { }
WinRandomAccessImpl ( this , alignment , options ) { }
WinRandomAccessFile : : ~ WinRandomAccessFile ( ) {
WinRandomAccessFile : : ~ WinRandomAccessFile ( ) { }
}
Status WinRandomAccessFile : : Read ( uint64_t offset , size_t n , Slice * result ,
IOStatus WinRandomAccessFile : : Read ( uint64_t offset , size_t n ,
char * scratch ) const {
const IOOptions & /*options*/ , Slice * result ,
char * scratch ,
IODebugContext * /*dbg*/ ) const {
return ReadImpl ( offset , n , result , scratch ) ;
return ReadImpl ( offset , n , result , scratch ) ;
}
}
Status WinRandomAccessFile : : InvalidateCache ( size_t offset , size_t length ) {
IO Status WinRandomAccessFile : : InvalidateCache ( size_t offset , size_t length ) {
return Status : : OK ( ) ;
return IO Status: : OK ( ) ;
}
}
size_t WinRandomAccessFile : : GetUniqueId ( char * id , size_t max_size ) const {
size_t WinRandomAccessFile : : GetUniqueId ( char * id , size_t max_size ) const {
@ -734,18 +733,17 @@ size_t WinRandomAccessFile::GetRequiredBufferAlignment() const {
// WinWritableImpl
// WinWritableImpl
//
//
inline
inline IOStatus WinWritableImpl : : PreallocateInternal ( uint64_t spaceToReserve ) {
Status WinWritableImpl : : PreallocateInternal ( uint64_t spaceToReserve ) {
return fallocate ( file_data_ - > GetName ( ) , file_data_ - > GetFileHandle ( ) ,
return fallocate ( file_data_ - > GetName ( ) , file_data_ - > GetFileHandle ( ) , spaceToReserve ) ;
spaceToReserve ) ;
}
}
inline
inline WinWritableImpl : : WinWritableImpl ( WinFileData * file_data ,
WinWritableImpl : : WinWritableImpl ( WinFileData * file_data , size_t alignment )
size_t alignment )
: file_data_ ( file_data ) ,
: file_data_ ( file_data ) ,
alignment_ ( alignment ) ,
alignment_ ( alignment ) ,
next_write_offset_ ( 0 ) ,
next_write_offset_ ( 0 ) ,
reservedsize_ ( 0 ) {
reservedsize_ ( 0 ) {
// Query current position in case ReopenWritableFile is called
// Query current position in case ReopenWritableFile is called
// This position is only important for buffered writes
// This position is only important for buffered writes
// for unbuffered writes we explicitely specify the position.
// for unbuffered writes we explicitely specify the position.
@ -763,13 +761,11 @@ WinWritableImpl::WinWritableImpl(WinFileData* file_data, size_t alignment)
}
}
}
}
inline
inline IOStatus WinWritableImpl : : AppendImpl ( const Slice & data ) {
Status WinWritableImpl : : AppendImpl ( const Slice & data ) {
IOStatus s ;
Status s ;
if ( data . size ( ) > std : : numeric_limits < DWORD > : : max ( ) ) {
if ( data . size ( ) > std : : numeric_limits < DWORD > : : max ( ) ) {
return Status : : InvalidArgument ( " data is too long for a single write " +
return IO Status: : InvalidArgument ( " data is too long for a single write " +
file_data_ - > GetName ( ) ) ;
file_data_ - > GetName ( ) ) ;
}
}
@ -781,33 +777,31 @@ Status WinWritableImpl::AppendImpl(const Slice& data) {
assert ( IsSectorAligned ( next_write_offset_ ) ) ;
assert ( IsSectorAligned ( next_write_offset_ ) ) ;
if ( ! IsSectorAligned ( data . size ( ) ) | |
if ( ! IsSectorAligned ( data . size ( ) ) | |
! IsAligned ( static_cast < size_t > ( GetAlignement ( ) ) , data . data ( ) ) ) {
! IsAligned ( static_cast < size_t > ( GetAlignement ( ) ) , data . data ( ) ) ) {
s = Status : : InvalidArgument (
s = IO Status: : InvalidArgument (
" WriteData must be page aligned, size must be sector aligned " ) ;
" WriteData must be page aligned, size must be sector aligned " ) ;
} else {
} else {
s = pwrite ( file_data_ , data , next_write_offset_ , bytes_written ) ;
s = pwrite ( file_data_ , data , next_write_offset_ , bytes_written ) ;
}
}
} else {
} else {
DWORD bytesWritten = 0 ;
DWORD bytesWritten = 0 ;
if ( ! WriteFile ( file_data_ - > GetFileHandle ( ) , 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: " + file_data_ - > GetName ( ) ,
" Failed to WriteFile: " + file_data_ - > GetName ( ) , lastError ) ;
lastError ) ;
} else {
} else {
bytes_written = bytesWritten ;
bytes_written = bytesWritten ;
}
}
}
}
if ( s . ok ( ) ) {
if ( s . ok ( ) ) {
if ( bytes_written = = data . size ( ) ) {
if ( bytes_written = = data . size ( ) ) {
// This matters for direct_io cases where
// This matters for direct_io cases where
// we rely on the fact that next_write_offset_
// we rely on the fact that next_write_offset_
// is sector aligned
// is sector aligned
next_write_offset_ + = bytes_written ;
next_write_offset_ + = bytes_written ;
} else {
} else {
s = Status : : IOError ( " Failed to write all bytes: " +
s = IO Status: : IOError ( " Failed to write all bytes: " +
file_data_ - > GetName ( ) ) ;
file_data_ - > GetName ( ) ) ;
}
}
}
}
@ -815,22 +809,21 @@ Status WinWritableImpl::AppendImpl(const Slice& data) {
return s ;
return s ;
}
}
inline
inline IOStatus WinWritableImpl : : PositionedAppendImpl ( const Slice & data ,
Status WinWritableImpl : : PositionedAppendImpl ( const Slice & data , uint64_t offset ) {
uint64_t offset ) {
if ( file_data_ - > use_direct_io ( ) ) {
if ( file_data_ - > use_direct_io ( ) ) {
if ( ! IsSectorAligned ( static_cast < size_t > ( offset ) ) | |
if ( ! IsSectorAligned ( static_cast < size_t > ( offset ) ) | |
! IsSectorAligned ( data . size ( ) ) | |
! IsSectorAligned ( data . size ( ) ) | |
! IsAligned ( static_cast < size_t > ( GetAlignement ( ) ) , data . data ( ) ) ) {
! IsAligned ( static_cast < size_t > ( GetAlignement ( ) ) , data . data ( ) ) ) {
return Status : : InvalidArgument (
return IO Status: : InvalidArgument (
" Data and offset must be page aligned, size must be sector aligned " ) ;
" Data and offset must be page aligned, size must be sector aligned " ) ;
}
}
}
}
size_t bytes_written = 0 ;
size_t bytes_written = 0 ;
Status s = pwrite ( file_data_ , data , offset , bytes_written ) ;
IO Status s = pwrite ( file_data_ , data , offset , bytes_written ) ;
if ( s . ok ( ) ) {
if ( s . ok ( ) ) {
if ( bytes_written = = data . size ( ) ) {
if ( bytes_written = = data . size ( ) ) {
// For sequential write this would be simple
// For sequential write this would be simple
// size extension by data.size()
// size extension by data.size()
@ -839,23 +832,21 @@ Status WinWritableImpl::PositionedAppendImpl(const Slice& data, uint64_t offset)
next_write_offset_ = write_end ;
next_write_offset_ = write_end ;
}
}
} else {
} else {
s = Status : : IOError ( " Failed to write all of the requested data: " +
s = IO Status: : IOError ( " Failed to write all of the requested data: " +
file_data_ - > GetName ( ) ) ;
file_data_ - > GetName ( ) ) ;
}
}
}
}
return s ;
return s ;
}
}
inline
inline IOStatus WinWritableImpl : : TruncateImpl ( uint64_t size ) {
Status WinWritableImpl : : TruncateImpl ( uint64_t size ) {
// It is tempting to check for the size for sector alignment
// It is tempting to check for the size for sector alignment
// but truncation may come at the end and there is not a requirement
// 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
// 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
// after that. The interface docs state that the behavior is undefined
// in that case.
// in that case.
Status s = ftruncate ( file_data_ - > GetName ( ) , file_data_ - > GetFileHandle ( ) ,
IO Status s =
size ) ;
ftruncate ( file_data_ - > GetName ( ) , file_data_ - > GetFileHandle ( ) , size ) ;
if ( s . ok ( ) ) {
if ( s . ok ( ) ) {
next_write_offset_ = size ;
next_write_offset_ = size ;
@ -863,50 +854,48 @@ Status WinWritableImpl::TruncateImpl(uint64_t size) {
return s ;
return s ;
}
}
inline
inline IOStatus WinWritableImpl : : CloseImpl ( ) {
Status WinWritableImpl : : CloseImpl ( ) {
IOStatus s ;
Status s ;
auto hFile = file_data_ - > GetFileHandle ( ) ;
auto hFile = file_data_ - > GetFileHandle ( ) ;
assert ( INVALID_HANDLE_VALUE ! = hFile ) ;
assert ( INVALID_HANDLE_VALUE ! = hFile ) ;
if ( ! : : FlushFileBuffers ( hFile ) ) {
if ( ! : : FlushFileBuffers ( hFile ) ) {
auto lastError = GetLastError ( ) ;
auto lastError = GetLastError ( ) ;
s = IOErrorFromWindowsError ( " FlushFileBuffers failed at Close() for: " +
s = IOErrorFromWindowsError (
file_data_ - > GetName ( ) ,
" FlushFileBuffers failed at Close() for: " + file_data_ - > GetName ( ) ,
lastError ) ;
lastError ) ;
}
}
if ( ! file_data_ - > CloseFile ( ) & & s . ok ( ) ) {
if ( ! file_data_ - > CloseFile ( ) & & s . ok ( ) ) {
auto lastError = GetLastError ( ) ;
auto lastError = GetLastError ( ) ;
s = IOErrorFromWindowsError ( " CloseHandle failed for: " + file_data_ - > GetName ( ) ,
s = IOErrorFromWindowsError (
lastError ) ;
" CloseHandle failed for: " + file_data_ - > GetName ( ) , lastError ) ;
}
}
return s ;
return s ;
}
}
inline
inline IOStatus WinWritableImpl : : SyncImpl ( const IOOptions & /*options*/ ,
Status WinWritableImpl : : SyncImpl ( ) {
IODebugContext * /*dbg*/ ) {
Status s ;
IO Status s ;
if ( ! : : FlushFileBuffers ( file_data_ - > GetFileHandle ( ) ) ) {
if ( ! : : FlushFileBuffers ( file_data_ - > GetFileHandle ( ) ) ) {
auto lastError = GetLastError ( ) ;
auto lastError = GetLastError ( ) ;
s = IOErrorFromWindowsError (
s = IOErrorFromWindowsError (
" FlushFileBuffers failed at Sync() for: " + file_data_ - > GetName ( ) , lastError ) ;
" FlushFileBuffers failed at Sync() for: " + file_data_ - > GetName ( ) ,
lastError ) ;
}
}
return s ;
return s ;
}
}
inline IOStatus WinWritableImpl : : AllocateImpl ( uint64_t offset , uint64_t len ) {
inline
IOStatus status ;
Status WinWritableImpl : : AllocateImpl ( uint64_t offset , uint64_t len ) {
Status status ;
TEST_KILL_RANDOM ( " WinWritableFile::Allocate " , rocksdb_kill_odds ) ;
TEST_KILL_RANDOM ( " WinWritableFile::Allocate " , rocksdb_kill_odds ) ;
// Make sure that we reserve an aligned amount of space
// Make sure that we reserve an aligned amount of space
// since the reservation block size is driven outside so we want
// since the reservation block size is driven outside so we want
// to check if we are ok with reservation here
// 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
// Nothing to do
if ( spaceToReserve < = reservedsize_ ) {
if ( spaceToReserve < = reservedsize_ ) {
return status ;
return status ;
@ -920,66 +909,78 @@ Status WinWritableImpl::AllocateImpl(uint64_t offset, uint64_t len) {
return status ;
return status ;
}
}
////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
/// WinWritableFile
/// WinWritableFile
WinWritableFile : : WinWritableFile ( const std : : string & fname , HANDLE hFile ,
WinWritableFile : : WinWritableFile ( const std : : string & fname , HANDLE hFile ,
size_t alignment , size_t /* capacity */ ,
size_t alignment , size_t /* capacity */ ,
const Env Options& options )
const File Options& options )
: WinFileData ( fname , hFile , options . use_direct_writes ) ,
: WinFileData ( fname , hFile , options . use_direct_writes ) ,
WinWritableImpl ( this , alignment ) ,
WinWritableImpl ( this , alignment ) ,
WritableFile ( options ) {
FS WritableFile( options ) {
assert ( ! options . use_mmap_writes ) ;
assert ( ! options . use_mmap_writes ) ;
}
}
WinWritableFile : : ~ WinWritableFile ( ) {
WinWritableFile : : ~ WinWritableFile ( ) { }
}
// Indicates if the class makes use of direct I/O
// 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 {
size_t WinWritableFile : : GetRequiredBufferAlignment ( ) const {
return static_cast < size_t > ( GetAlignement ( ) ) ;
return static_cast < size_t > ( GetAlignement ( ) ) ;
}
}
Status WinWritableFile : : Append ( const Slice & data ) {
IOStatus WinWritableFile : : Append ( const Slice & data ,
const IOOptions & /*options*/ ,
IODebugContext * /*dbg*/ ) {
return AppendImpl ( data ) ;
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 ) ;
return PositionedAppendImpl ( data , offset ) ;
}
}
// 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 ) {
IOStatus WinWritableFile : : Truncate ( uint64_t size , const IOOptions & /*options*/ ,
IODebugContext * /*dbg*/ ) {
return TruncateImpl ( size ) ;
return TruncateImpl ( size ) ;
}
}
Status WinWritableFile : : Close ( ) {
IOStatus WinWritableFile : : Close ( const IOOptions & /*options*/ ,
IODebugContext * /*dbg*/ ) {
return CloseImpl ( ) ;
return CloseImpl ( ) ;
}
}
// write out the cached data to the OS cache
// write out the cached data to the OS cache
// This is now taken care of the WritableFileWriter
// This is now taken care of the WritableFileWriter
Status WinWritableFile : : Flush ( ) {
IOStatus WinWritableFile : : Flush ( const IOOptions & /*options*/ ,
return Status : : OK ( ) ;
IODebugContext * /*dbg*/ ) {
return IOStatus : : OK ( ) ;
}
}
Status WinWritableFile : : Sync ( ) {
IO Status WinWritableFile : : Sync ( const IOOptions & options , IODebugContext * dbg ) {
return SyncImpl ( ) ;
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 ; }
bool WinWritableFile : : IsSyncThreadSafe ( ) const { return true ; }
uint64_t WinWritableFile : : GetFileSize ( ) {
uint64_t WinWritableFile : : GetFileSize ( const IOOptions & /*options*/ ,
IODebugContext * /*dbg*/ ) {
return GetFileNextWriteOffset ( ) ;
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 ) ;
return AllocateImpl ( offset , len ) ;
}
}
@ -991,36 +992,43 @@ size_t WinWritableFile::GetUniqueId(char* id, size_t max_size) const {
/// WinRandomRWFile
/// WinRandomRWFile
WinRandomRWFile : : WinRandomRWFile ( const std : : string & fname , HANDLE hFile ,
WinRandomRWFile : : WinRandomRWFile ( const std : : string & fname , HANDLE hFile ,
size_t alignment , const Env Options& options )
size_t alignment , const File Options& options )
: WinFileData ( fname , hFile ,
: WinFileData ( fname , hFile ,
options . use_direct_reads & & options . use_direct_writes ) ,
options . use_direct_reads & & options . use_direct_writes ) ,
WinRandomAccessImpl ( this , alignment , options ) ,
WinRandomAccessImpl ( this , alignment , options ) ,
WinWritableImpl ( this , alignment ) { }
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 {
size_t WinRandomRWFile : : GetRequiredBufferAlignment ( ) const {
return static_cast < size_t > ( GetAlignement ( ) ) ;
return static_cast < size_t > ( GetAlignement ( ) ) ;
}
}
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 ) ;
return PositionedAppendImpl ( data , offset ) ;
}
}
Status WinRandomRWFile : : Read ( uint64_t offset , size_t n , Slice * result ,
IOStatus WinRandomRWFile : : Read ( uint64_t offset , size_t n ,
char * scratch ) const {
const IOOptions & /*options*/ , Slice * result ,
char * scratch , IODebugContext * /*dbg*/ ) const {
return ReadImpl ( offset , n , result , scratch ) ;
return ReadImpl ( offset , n , result , scratch ) ;
}
}
Status WinRandomRWFile : : Flush ( ) {
IOStatus WinRandomRWFile : : Flush ( const IOOptions & /*options*/ ,
return Status : : OK ( ) ;
IODebugContext * /*dbg*/ ) {
return IOStatus : : OK ( ) ;
}
}
Status WinRandomRWFile : : Sync ( ) {
IO Status WinRandomRWFile : : Sync ( const IOOptions & options , IODebugContext * dbg ) {
return SyncImpl ( ) ;
return SyncImpl ( options , dbg ) ;
}
}
Status WinRandomRWFile : : Close ( ) {
IOStatus WinRandomRWFile : : Close ( const IOOptions & /*options*/ ,
IODebugContext * /*dbg*/ ) {
return CloseImpl ( ) ;
return CloseImpl ( ) ;
}
}
@ -1053,7 +1061,10 @@ WinMemoryMappedBuffer::~WinMemoryMappedBuffer() {
//////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////
/// WinDirectory
/// WinDirectory
Status WinDirectory : : Fsync ( ) { return Status : : OK ( ) ; }
IOStatus WinDirectory : : Fsync ( const IOOptions & /*options*/ ,
IODebugContext * /*dbg*/ ) {
return IOStatus : : OK ( ) ;
}
size_t WinDirectory : : GetUniqueId ( char * id , size_t max_size ) const {
size_t WinDirectory : : GetUniqueId ( char * id , size_t max_size ) const {
return GetUniqueIdFromFile ( handle_ , id , max_size ) ;
return GetUniqueIdFromFile ( handle_ , id , max_size ) ;
@ -1067,7 +1078,7 @@ WinFileLock::~WinFileLock() {
assert ( ret ) ;
assert ( ret ) ;
}
}
}
} // namespace port
} // namespace ROCKSDB_NAMESPACE
} // namespace ROCKSDB_NAMESPACE
# endif
# endif