Browse Source

Squashed 'src/leveldb/' changes from 7d41e6f..20ca81f

20ca81f Merge pull request #9
7aa105e leveldb: Win32WritableFile without memory mapping

git-subtree-dir: src/leveldb
git-subtree-split: 20ca81f08fb7fa108923a091668e447dcf5c6b9d
0.15
Pieter Wuille 9 years ago
parent
commit
fb9857bfd6
  1. 236
      util/env_win.cc

236
util/env_win.cc

@ -103,39 +103,20 @@ private:
DISALLOW_COPY_AND_ASSIGN(Win32RandomAccessFile); DISALLOW_COPY_AND_ASSIGN(Win32RandomAccessFile);
}; };
class Win32MapFile : public WritableFile class Win32WritableFile : public WritableFile
{ {
public: public:
Win32MapFile(const std::string& fname); Win32WritableFile(const std::string& fname);
~Win32WritableFile();
~Win32MapFile();
virtual Status Append(const Slice& data); virtual Status Append(const Slice& data);
virtual Status Close(); virtual Status Close();
virtual Status Flush(); virtual Status Flush();
virtual Status Sync(); virtual Status Sync();
BOOL isEnable(); BOOL isEnable();
private: private:
std::string _filename; std::string filename_;
HANDLE _hFile; ::HANDLE _hFile;
size_t _page_size;
size_t _map_size; // How much extra memory to map at a time
char* _base; // The mapped region
HANDLE _base_handle;
char* _limit; // Limit of the mapped region
char* _dst; // Where to write next (in range [base_,limit_])
char* _last_sync; // Where have we synced up to
uint64_t _file_offset; // Offset of base_ in file
//LARGE_INTEGER file_offset_;
// Have we done an munmap of unsynced data?
bool _pending_sync;
// Roundup x to a multiple of y
static size_t _Roundup(size_t x, size_t y);
size_t _TruncateToPageBoundary(size_t s);
bool _UnmapCurrentRegion();
bool _MapNewRegion();
DISALLOW_COPY_AND_ASSIGN(Win32MapFile);
BOOL _Init(LPCWSTR Path);
}; };
class Win32FileLock : public FileLock class Win32FileLock : public FileLock
@ -442,202 +423,63 @@ void Win32RandomAccessFile::_CleanUp()
} }
} }
size_t Win32MapFile::_Roundup( size_t x, size_t y ) Win32WritableFile::Win32WritableFile(const std::string& fname)
{ : filename_(fname)
return ((x + y - 1) / y) * y;
}
size_t Win32MapFile::_TruncateToPageBoundary( size_t s )
{
s -= (s & (_page_size - 1));
assert((s % _page_size) == 0);
return s;
}
bool Win32MapFile::_UnmapCurrentRegion()
{
bool result = true;
if (_base != NULL) {
if (_last_sync < _limit) {
// Defer syncing this data until next Sync() call, if any
_pending_sync = true;
}
if (!UnmapViewOfFile(_base) || !CloseHandle(_base_handle))
result = false;
_file_offset += _limit - _base;
_base = NULL;
_base_handle = NULL;
_limit = NULL;
_last_sync = NULL;
_dst = NULL;
// Increase the amount we map the next time, but capped at 1MB
if (_map_size < (1<<20)) {
_map_size *= 2;
}
}
return result;
}
bool Win32MapFile::_MapNewRegion()
{
assert(_base == NULL);
//LONG newSizeHigh = (LONG)((file_offset_ + map_size_) >> 32);
//LONG newSizeLow = (LONG)((file_offset_ + map_size_) & 0xFFFFFFFF);
DWORD off_hi = (DWORD)(_file_offset >> 32);
DWORD off_lo = (DWORD)(_file_offset & 0xFFFFFFFF);
LARGE_INTEGER newSize;
newSize.QuadPart = _file_offset + _map_size;
SetFilePointerEx(_hFile, newSize, NULL, FILE_BEGIN);
SetEndOfFile(_hFile);
_base_handle = CreateFileMappingA(
_hFile,
NULL,
PAGE_READWRITE,
0,
0,
0);
if (_base_handle != NULL) {
_base = (char*) MapViewOfFile(_base_handle,
FILE_MAP_ALL_ACCESS,
off_hi,
off_lo,
_map_size);
if (_base != NULL) {
_limit = _base + _map_size;
_dst = _base;
_last_sync = _base;
return true;
}
}
return false;
}
Win32MapFile::Win32MapFile( const std::string& fname) :
_filename(fname),
_hFile(NULL),
_page_size(Win32::g_PageSize),
_map_size(_Roundup(65536, Win32::g_PageSize)),
_base(NULL),
_base_handle(NULL),
_limit(NULL),
_dst(NULL),
_last_sync(NULL),
_file_offset(0),
_pending_sync(false)
{ {
std::wstring path; std::wstring path;
ToWidePath(fname, path); ToWidePath(fname, path);
_Init(path.c_str()); DWORD Flag = PathFileExistsW(path.c_str()) ? OPEN_EXISTING : CREATE_ALWAYS;
assert((Win32::g_PageSize & (Win32::g_PageSize - 1)) == 0); _hFile = CreateFileW(path.c_str(),
GENERIC_READ | GENERIC_WRITE,
FILE_SHARE_READ|FILE_SHARE_DELETE|FILE_SHARE_WRITE,
NULL,
Flag,
FILE_ATTRIBUTE_NORMAL,
NULL);
// CreateFileW returns INVALID_HANDLE_VALUE in case of error, always check isEnable() before use
} }
Status Win32MapFile::Append( const Slice& data ) Win32WritableFile::~Win32WritableFile()
{ {
const char* src = data.data(); if (_hFile != INVALID_HANDLE_VALUE)
size_t left = data.size(); Close();
Status s;
while (left > 0) {
assert(_base <= _dst);
assert(_dst <= _limit);
size_t avail = _limit - _dst;
if (avail == 0) {
if (!_UnmapCurrentRegion() ||
!_MapNewRegion()) {
return Status::IOError("WinMmapFile.Append::UnmapCurrentRegion or MapNewRegion: ", Win32::GetLastErrSz());
}
}
size_t n = (left <= avail) ? left : avail;
memcpy(_dst, src, n);
_dst += n;
src += n;
left -= n;
}
return s;
} }
Status Win32MapFile::Close() Status Win32WritableFile::Append(const Slice& data)
{ {
Status s; DWORD r = 0;
size_t unused = _limit - _dst; if (!WriteFile(_hFile, data.data(), data.size(), &r, NULL) || r != data.size()) {
if (!_UnmapCurrentRegion()) { return Status::IOError("Win32WritableFile.Append::WriteFile: "+filename_, Win32::GetLastErrSz());
s = Status::IOError("WinMmapFile.Close::UnmapCurrentRegion: ",Win32::GetLastErrSz());
} else if (unused > 0) {
// Trim the extra space at the end of the file
LARGE_INTEGER newSize;
newSize.QuadPart = _file_offset - unused;
if (!SetFilePointerEx(_hFile, newSize, NULL, FILE_BEGIN)) {
s = Status::IOError("WinMmapFile.Close::SetFilePointer: ",Win32::GetLastErrSz());
} else
SetEndOfFile(_hFile);
}
if (!CloseHandle(_hFile)) {
if (s.ok()) {
s = Status::IOError("WinMmapFile.Close::CloseHandle: ", Win32::GetLastErrSz());
} }
} return Status::OK();
_hFile = INVALID_HANDLE_VALUE;
_base = NULL;
_base_handle = NULL;
_limit = NULL;
return s;
} }
Status Win32MapFile::Sync() Status Win32WritableFile::Close()
{ {
Status s; if (!CloseHandle(_hFile)) {
if (_pending_sync) { return Status::IOError("Win32WritableFile.Close::CloseHandle: "+filename_, Win32::GetLastErrSz());
// Some unmapped data was not synced
_pending_sync = false;
if (!FlushFileBuffers(_hFile)) {
s = Status::IOError("WinMmapFile.Sync::FlushFileBuffers: ",Win32::GetLastErrSz());
}
}
if (_dst > _last_sync) {
// Find the beginnings of the pages that contain the first and last
// bytes to be synced.
size_t p1 = _TruncateToPageBoundary(_last_sync - _base);
size_t p2 = _TruncateToPageBoundary(_dst - _base - 1);
_last_sync = _dst;
if (!FlushViewOfFile(_base + p1, p2 - p1 + _page_size)) {
s = Status::IOError("WinMmapFile.Sync::FlushViewOfFile: ",Win32::GetLastErrSz());
}
} }
return s; _hFile = INVALID_HANDLE_VALUE;
return Status::OK();
} }
Status Win32MapFile::Flush() Status Win32WritableFile::Flush()
{ {
// Nothing to do here, there are no application-side buffers
return Status::OK(); return Status::OK();
} }
Win32MapFile::~Win32MapFile() Status Win32WritableFile::Sync()
{ {
if (_hFile != INVALID_HANDLE_VALUE) { if (!FlushFileBuffers(_hFile)) {
Win32MapFile::Close(); return Status::IOError("Win32WritableFile.Sync::FlushFileBuffers "+filename_, Win32::GetLastErrSz());
}
} }
return Status::OK();
BOOL Win32MapFile::_Init( LPCWSTR Path )
{
DWORD Flag = PathFileExistsW(Path) ? OPEN_EXISTING : CREATE_ALWAYS;
_hFile = CreateFileW(Path,
GENERIC_READ | GENERIC_WRITE,
FILE_SHARE_READ|FILE_SHARE_DELETE|FILE_SHARE_WRITE,
NULL,
Flag,
FILE_ATTRIBUTE_NORMAL,
NULL);
if(!_hFile || _hFile == INVALID_HANDLE_VALUE)
return FALSE;
else
return TRUE;
} }
BOOL Win32MapFile::isEnable() BOOL Win32WritableFile::isEnable()
{ {
return _hFile ? TRUE : FALSE; return _hFile != INVALID_HANDLE_VALUE;
} }
Win32FileLock::Win32FileLock( const std::string& fname ) : Win32FileLock::Win32FileLock( const std::string& fname ) :
@ -981,7 +823,7 @@ Status Win32Env::NewLogger( const std::string& fname, Logger** result )
{ {
Status sRet; Status sRet;
std::string path = fname; std::string path = fname;
Win32MapFile* pMapFile = new Win32MapFile(ModifyPath(path)); Win32WritableFile* pMapFile = new Win32WritableFile(ModifyPath(path));
if(!pMapFile->isEnable()){ if(!pMapFile->isEnable()){
delete pMapFile; delete pMapFile;
*result = NULL; *result = NULL;
@ -995,7 +837,7 @@ Status Win32Env::NewWritableFile( const std::string& fname, WritableFile** resul
{ {
Status sRet; Status sRet;
std::string path = fname; std::string path = fname;
Win32MapFile* pFile = new Win32MapFile(ModifyPath(path)); Win32WritableFile* pFile = new Win32WritableFile(ModifyPath(path));
if(!pFile->isEnable()){ if(!pFile->isEnable()){
*result = NULL; *result = NULL;
sRet = Status::IOError(fname,Win32::GetLastErrSz()); sRet = Status::IOError(fname,Win32::GetLastErrSz());

Loading…
Cancel
Save