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
This commit is contained in:
parent
4b0e2d75d7
commit
fb9857bfd6
1 changed files with 54 additions and 212 deletions
266
util/env_win.cc
266
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;
|
std::wstring path;
|
||||||
}
|
ToWidePath(fname, path);
|
||||||
|
DWORD Flag = PathFileExistsW(path.c_str()) ? OPEN_EXISTING : CREATE_ALWAYS;
|
||||||
size_t Win32MapFile::_TruncateToPageBoundary( size_t s )
|
_hFile = CreateFileW(path.c_str(),
|
||||||
{
|
|
||||||
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;
|
|
||||||
ToWidePath(fname, path);
|
|
||||||
_Init(path.c_str());
|
|
||||||
assert((Win32::g_PageSize & (Win32::g_PageSize - 1)) == 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
Status Win32MapFile::Append( const Slice& data )
|
|
||||||
{
|
|
||||||
const char* src = data.data();
|
|
||||||
size_t left = data.size();
|
|
||||||
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 s;
|
|
||||||
size_t unused = _limit - _dst;
|
|
||||||
if (!_UnmapCurrentRegion()) {
|
|
||||||
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());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
_hFile = INVALID_HANDLE_VALUE;
|
|
||||||
_base = NULL;
|
|
||||||
_base_handle = NULL;
|
|
||||||
_limit = NULL;
|
|
||||||
|
|
||||||
return s;
|
|
||||||
}
|
|
||||||
|
|
||||||
Status Win32MapFile::Sync()
|
|
||||||
{
|
|
||||||
Status s;
|
|
||||||
if (_pending_sync) {
|
|
||||||
// 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;
|
|
||||||
}
|
|
||||||
|
|
||||||
Status Win32MapFile::Flush()
|
|
||||||
{
|
|
||||||
return Status::OK();
|
|
||||||
}
|
|
||||||
|
|
||||||
Win32MapFile::~Win32MapFile()
|
|
||||||
{
|
|
||||||
if (_hFile != INVALID_HANDLE_VALUE) {
|
|
||||||
Win32MapFile::Close();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
BOOL Win32MapFile::_Init( LPCWSTR Path )
|
|
||||||
{
|
|
||||||
DWORD Flag = PathFileExistsW(Path) ? OPEN_EXISTING : CREATE_ALWAYS;
|
|
||||||
_hFile = CreateFileW(Path,
|
|
||||||
GENERIC_READ | GENERIC_WRITE,
|
GENERIC_READ | GENERIC_WRITE,
|
||||||
FILE_SHARE_READ|FILE_SHARE_DELETE|FILE_SHARE_WRITE,
|
FILE_SHARE_READ|FILE_SHARE_DELETE|FILE_SHARE_WRITE,
|
||||||
NULL,
|
NULL,
|
||||||
Flag,
|
Flag,
|
||||||
FILE_ATTRIBUTE_NORMAL,
|
FILE_ATTRIBUTE_NORMAL,
|
||||||
NULL);
|
NULL);
|
||||||
if(!_hFile || _hFile == INVALID_HANDLE_VALUE)
|
// CreateFileW returns INVALID_HANDLE_VALUE in case of error, always check isEnable() before use
|
||||||
return FALSE;
|
|
||||||
else
|
|
||||||
return TRUE;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
BOOL Win32MapFile::isEnable()
|
Win32WritableFile::~Win32WritableFile()
|
||||||
{
|
{
|
||||||
return _hFile ? TRUE : FALSE;
|
if (_hFile != INVALID_HANDLE_VALUE)
|
||||||
|
Close();
|
||||||
|
}
|
||||||
|
|
||||||
|
Status Win32WritableFile::Append(const Slice& data)
|
||||||
|
{
|
||||||
|
DWORD r = 0;
|
||||||
|
if (!WriteFile(_hFile, data.data(), data.size(), &r, NULL) || r != data.size()) {
|
||||||
|
return Status::IOError("Win32WritableFile.Append::WriteFile: "+filename_, Win32::GetLastErrSz());
|
||||||
|
}
|
||||||
|
return Status::OK();
|
||||||
|
}
|
||||||
|
|
||||||
|
Status Win32WritableFile::Close()
|
||||||
|
{
|
||||||
|
if (!CloseHandle(_hFile)) {
|
||||||
|
return Status::IOError("Win32WritableFile.Close::CloseHandle: "+filename_, Win32::GetLastErrSz());
|
||||||
|
}
|
||||||
|
_hFile = INVALID_HANDLE_VALUE;
|
||||||
|
return Status::OK();
|
||||||
|
}
|
||||||
|
|
||||||
|
Status Win32WritableFile::Flush()
|
||||||
|
{
|
||||||
|
// Nothing to do here, there are no application-side buffers
|
||||||
|
return Status::OK();
|
||||||
|
}
|
||||||
|
|
||||||
|
Status Win32WritableFile::Sync()
|
||||||
|
{
|
||||||
|
if (!FlushFileBuffers(_hFile)) {
|
||||||
|
return Status::IOError("Win32WritableFile.Sync::FlushFileBuffers "+filename_, Win32::GetLastErrSz());
|
||||||
|
}
|
||||||
|
return Status::OK();
|
||||||
|
}
|
||||||
|
|
||||||
|
BOOL Win32WritableFile::isEnable()
|
||||||
|
{
|
||||||
|
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…
Reference in a new issue