Skip to content

Commit 20ca81f

Browse files
committed
Merge pull request #9
7aa105e leveldb: Win32WritableFile without memory mapping (Wladimir J. van der Laan)
2 parents 7d41e6f + 7aa105e commit 20ca81f

File tree

1 file changed

+39
-197
lines changed

1 file changed

+39
-197
lines changed

util/env_win.cc

+39-197
Original file line numberDiff line numberDiff line change
@@ -103,39 +103,20 @@ class Win32RandomAccessFile : public RandomAccessFile
103103
DISALLOW_COPY_AND_ASSIGN(Win32RandomAccessFile);
104104
};
105105

106-
class Win32MapFile : public WritableFile
106+
class Win32WritableFile : public WritableFile
107107
{
108108
public:
109-
Win32MapFile(const std::string& fname);
109+
Win32WritableFile(const std::string& fname);
110+
~Win32WritableFile();
110111

111-
~Win32MapFile();
112112
virtual Status Append(const Slice& data);
113113
virtual Status Close();
114114
virtual Status Flush();
115115
virtual Status Sync();
116116
BOOL isEnable();
117117
private:
118-
std::string _filename;
119-
HANDLE _hFile;
120-
size_t _page_size;
121-
size_t _map_size; // How much extra memory to map at a time
122-
char* _base; // The mapped region
123-
HANDLE _base_handle;
124-
char* _limit; // Limit of the mapped region
125-
char* _dst; // Where to write next (in range [base_,limit_])
126-
char* _last_sync; // Where have we synced up to
127-
uint64_t _file_offset; // Offset of base_ in file
128-
//LARGE_INTEGER file_offset_;
129-
// Have we done an munmap of unsynced data?
130-
bool _pending_sync;
131-
132-
// Roundup x to a multiple of y
133-
static size_t _Roundup(size_t x, size_t y);
134-
size_t _TruncateToPageBoundary(size_t s);
135-
bool _UnmapCurrentRegion();
136-
bool _MapNewRegion();
137-
DISALLOW_COPY_AND_ASSIGN(Win32MapFile);
138-
BOOL _Init(LPCWSTR Path);
118+
std::string filename_;
119+
::HANDLE _hFile;
139120
};
140121

141122
class Win32FileLock : public FileLock
@@ -442,202 +423,63 @@ void Win32RandomAccessFile::_CleanUp()
442423
}
443424
}
444425

445-
size_t Win32MapFile::_Roundup( size_t x, size_t y )
426+
Win32WritableFile::Win32WritableFile(const std::string& fname)
427+
: filename_(fname)
446428
{
447-
return ((x + y - 1) / y) * y;
429+
std::wstring path;
430+
ToWidePath(fname, path);
431+
DWORD Flag = PathFileExistsW(path.c_str()) ? OPEN_EXISTING : CREATE_ALWAYS;
432+
_hFile = CreateFileW(path.c_str(),
433+
GENERIC_READ | GENERIC_WRITE,
434+
FILE_SHARE_READ|FILE_SHARE_DELETE|FILE_SHARE_WRITE,
435+
NULL,
436+
Flag,
437+
FILE_ATTRIBUTE_NORMAL,
438+
NULL);
439+
// CreateFileW returns INVALID_HANDLE_VALUE in case of error, always check isEnable() before use
448440
}
449441

450-
size_t Win32MapFile::_TruncateToPageBoundary( size_t s )
442+
Win32WritableFile::~Win32WritableFile()
451443
{
452-
s -= (s & (_page_size - 1));
453-
assert((s % _page_size) == 0);
454-
return s;
444+
if (_hFile != INVALID_HANDLE_VALUE)
445+
Close();
455446
}
456447

457-
bool Win32MapFile::_UnmapCurrentRegion()
448+
Status Win32WritableFile::Append(const Slice& data)
458449
{
459-
bool result = true;
460-
if (_base != NULL) {
461-
if (_last_sync < _limit) {
462-
// Defer syncing this data until next Sync() call, if any
463-
_pending_sync = true;
464-
}
465-
if (!UnmapViewOfFile(_base) || !CloseHandle(_base_handle))
466-
result = false;
467-
_file_offset += _limit - _base;
468-
_base = NULL;
469-
_base_handle = NULL;
470-
_limit = NULL;
471-
_last_sync = NULL;
472-
_dst = NULL;
473-
// Increase the amount we map the next time, but capped at 1MB
474-
if (_map_size < (1<<20)) {
475-
_map_size *= 2;
476-
}
450+
DWORD r = 0;
451+
if (!WriteFile(_hFile, data.data(), data.size(), &r, NULL) || r != data.size()) {
452+
return Status::IOError("Win32WritableFile.Append::WriteFile: "+filename_, Win32::GetLastErrSz());
477453
}
478-
return result;
479-
}
480-
481-
bool Win32MapFile::_MapNewRegion()
482-
{
483-
assert(_base == NULL);
484-
//LONG newSizeHigh = (LONG)((file_offset_ + map_size_) >> 32);
485-
//LONG newSizeLow = (LONG)((file_offset_ + map_size_) & 0xFFFFFFFF);
486-
DWORD off_hi = (DWORD)(_file_offset >> 32);
487-
DWORD off_lo = (DWORD)(_file_offset & 0xFFFFFFFF);
488-
LARGE_INTEGER newSize;
489-
newSize.QuadPart = _file_offset + _map_size;
490-
SetFilePointerEx(_hFile, newSize, NULL, FILE_BEGIN);
491-
SetEndOfFile(_hFile);
492-
493-
_base_handle = CreateFileMappingA(
494-
_hFile,
495-
NULL,
496-
PAGE_READWRITE,
497-
0,
498-
0,
499-
0);
500-
if (_base_handle != NULL) {
501-
_base = (char*) MapViewOfFile(_base_handle,
502-
FILE_MAP_ALL_ACCESS,
503-
off_hi,
504-
off_lo,
505-
_map_size);
506-
if (_base != NULL) {
507-
_limit = _base + _map_size;
508-
_dst = _base;
509-
_last_sync = _base;
510-
return true;
511-
}
512-
}
513-
return false;
454+
return Status::OK();
514455
}
515456

516-
Win32MapFile::Win32MapFile( const std::string& fname) :
517-
_filename(fname),
518-
_hFile(NULL),
519-
_page_size(Win32::g_PageSize),
520-
_map_size(_Roundup(65536, Win32::g_PageSize)),
521-
_base(NULL),
522-
_base_handle(NULL),
523-
_limit(NULL),
524-
_dst(NULL),
525-
_last_sync(NULL),
526-
_file_offset(0),
527-
_pending_sync(false)
457+
Status Win32WritableFile::Close()
528458
{
529-
std::wstring path;
530-
ToWidePath(fname, path);
531-
_Init(path.c_str());
532-
assert((Win32::g_PageSize & (Win32::g_PageSize - 1)) == 0);
533-
}
534-
535-
Status Win32MapFile::Append( const Slice& data )
536-
{
537-
const char* src = data.data();
538-
size_t left = data.size();
539-
Status s;
540-
while (left > 0) {
541-
assert(_base <= _dst);
542-
assert(_dst <= _limit);
543-
size_t avail = _limit - _dst;
544-
if (avail == 0) {
545-
if (!_UnmapCurrentRegion() ||
546-
!_MapNewRegion()) {
547-
return Status::IOError("WinMmapFile.Append::UnmapCurrentRegion or MapNewRegion: ", Win32::GetLastErrSz());
548-
}
549-
}
550-
size_t n = (left <= avail) ? left : avail;
551-
memcpy(_dst, src, n);
552-
_dst += n;
553-
src += n;
554-
left -= n;
555-
}
556-
return s;
557-
}
558-
559-
Status Win32MapFile::Close()
560-
{
561-
Status s;
562-
size_t unused = _limit - _dst;
563-
if (!_UnmapCurrentRegion()) {
564-
s = Status::IOError("WinMmapFile.Close::UnmapCurrentRegion: ",Win32::GetLastErrSz());
565-
} else if (unused > 0) {
566-
// Trim the extra space at the end of the file
567-
LARGE_INTEGER newSize;
568-
newSize.QuadPart = _file_offset - unused;
569-
if (!SetFilePointerEx(_hFile, newSize, NULL, FILE_BEGIN)) {
570-
s = Status::IOError("WinMmapFile.Close::SetFilePointer: ",Win32::GetLastErrSz());
571-
} else
572-
SetEndOfFile(_hFile);
573-
}
574459
if (!CloseHandle(_hFile)) {
575-
if (s.ok()) {
576-
s = Status::IOError("WinMmapFile.Close::CloseHandle: ", Win32::GetLastErrSz());
577-
}
460+
return Status::IOError("Win32WritableFile.Close::CloseHandle: "+filename_, Win32::GetLastErrSz());
578461
}
579462
_hFile = INVALID_HANDLE_VALUE;
580-
_base = NULL;
581-
_base_handle = NULL;
582-
_limit = NULL;
583-
584-
return s;
585-
}
586-
587-
Status Win32MapFile::Sync()
588-
{
589-
Status s;
590-
if (_pending_sync) {
591-
// Some unmapped data was not synced
592-
_pending_sync = false;
593-
if (!FlushFileBuffers(_hFile)) {
594-
s = Status::IOError("WinMmapFile.Sync::FlushFileBuffers: ",Win32::GetLastErrSz());
595-
}
596-
}
597-
if (_dst > _last_sync) {
598-
// Find the beginnings of the pages that contain the first and last
599-
// bytes to be synced.
600-
size_t p1 = _TruncateToPageBoundary(_last_sync - _base);
601-
size_t p2 = _TruncateToPageBoundary(_dst - _base - 1);
602-
_last_sync = _dst;
603-
if (!FlushViewOfFile(_base + p1, p2 - p1 + _page_size)) {
604-
s = Status::IOError("WinMmapFile.Sync::FlushViewOfFile: ",Win32::GetLastErrSz());
605-
}
606-
}
607-
return s;
463+
return Status::OK();
608464
}
609465

610-
Status Win32MapFile::Flush()
466+
Status Win32WritableFile::Flush()
611467
{
468+
// Nothing to do here, there are no application-side buffers
612469
return Status::OK();
613470
}
614471

615-
Win32MapFile::~Win32MapFile()
472+
Status Win32WritableFile::Sync()
616473
{
617-
if (_hFile != INVALID_HANDLE_VALUE) {
618-
Win32MapFile::Close();
474+
if (!FlushFileBuffers(_hFile)) {
475+
return Status::IOError("Win32WritableFile.Sync::FlushFileBuffers "+filename_, Win32::GetLastErrSz());
619476
}
477+
return Status::OK();
620478
}
621479

622-
BOOL Win32MapFile::_Init( LPCWSTR Path )
623-
{
624-
DWORD Flag = PathFileExistsW(Path) ? OPEN_EXISTING : CREATE_ALWAYS;
625-
_hFile = CreateFileW(Path,
626-
GENERIC_READ | GENERIC_WRITE,
627-
FILE_SHARE_READ|FILE_SHARE_DELETE|FILE_SHARE_WRITE,
628-
NULL,
629-
Flag,
630-
FILE_ATTRIBUTE_NORMAL,
631-
NULL);
632-
if(!_hFile || _hFile == INVALID_HANDLE_VALUE)
633-
return FALSE;
634-
else
635-
return TRUE;
636-
}
637-
638-
BOOL Win32MapFile::isEnable()
480+
BOOL Win32WritableFile::isEnable()
639481
{
640-
return _hFile ? TRUE : FALSE;
482+
return _hFile != INVALID_HANDLE_VALUE;
641483
}
642484

643485
Win32FileLock::Win32FileLock( const std::string& fname ) :
@@ -981,7 +823,7 @@ Status Win32Env::NewLogger( const std::string& fname, Logger** result )
981823
{
982824
Status sRet;
983825
std::string path = fname;
984-
Win32MapFile* pMapFile = new Win32MapFile(ModifyPath(path));
826+
Win32WritableFile* pMapFile = new Win32WritableFile(ModifyPath(path));
985827
if(!pMapFile->isEnable()){
986828
delete pMapFile;
987829
*result = NULL;
@@ -995,7 +837,7 @@ Status Win32Env::NewWritableFile( const std::string& fname, WritableFile** resul
995837
{
996838
Status sRet;
997839
std::string path = fname;
998-
Win32MapFile* pFile = new Win32MapFile(ModifyPath(path));
840+
Win32WritableFile* pFile = new Win32WritableFile(ModifyPath(path));
999841
if(!pFile->isEnable()){
1000842
*result = NULL;
1001843
sRet = Status::IOError(fname,Win32::GetLastErrSz());

0 commit comments

Comments
 (0)