7 #if defined(LEVELDB_PLATFORM_WINDOWS)
30 #define va_copy(d,s) ((d) = (s))
33 #if defined DeleteFile
44 #define DISALLOW_COPY_AND_ASSIGN(TypeName) \
45 TypeName(const TypeName&); \
46 void operator=(const TypeName&)
48 std::string GetCurrentDir();
49 std::wstring GetCurrentDirW();
51 static const std::string CurrentDir = GetCurrentDir();
52 static const std::wstring CurrentDirW = GetCurrentDirW();
54 std::string& ModifyPath(std::string& path);
55 std::wstring& ModifyPath(std::wstring& path);
57 std::string GetLastErrSz();
58 std::wstring GetLastErrSzW();
62 typedef void (*ScheduleProc)(
void*) ;
64 struct WorkItemWrapper
66 WorkItemWrapper(ScheduleProc proc_,
void* content_);
71 DWORD WINAPI WorkItemWrapperProc(LPVOID pContent);
73 class Win32SequentialFile :
public SequentialFile
76 friend class Win32Env;
77 virtual ~Win32SequentialFile();
78 virtual Status Read(
size_t n, Slice* result,
char* scratch);
84 Win32SequentialFile(
const std::string& fname);
85 std::string _filename;
87 DISALLOW_COPY_AND_ASSIGN(Win32SequentialFile);
90 class Win32RandomAccessFile :
public RandomAccessFile
93 friend class Win32Env;
94 virtual ~Win32RandomAccessFile();
95 virtual Status Read(
uint64_t offset,
size_t n, Slice* result,
char* scratch)
const;
98 BOOL _Init(LPCWSTR path);
100 Win32RandomAccessFile(
const std::string& fname);
102 const std::string _filename;
103 DISALLOW_COPY_AND_ASSIGN(Win32RandomAccessFile);
106 class Win32MapFile :
public WritableFile
109 Win32MapFile(
const std::string& fname);
112 virtual Status Append(
const Slice& data);
113 virtual Status Close();
114 virtual Status Flush();
115 virtual Status Sync();
118 std::string _filename;
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);
141 class Win32FileLock :
public FileLock
144 friend class Win32Env;
145 virtual ~Win32FileLock();
148 BOOL _Init(LPCWSTR path);
150 Win32FileLock(
const std::string& fname);
152 std::string _filename;
153 DISALLOW_COPY_AND_ASSIGN(Win32FileLock);
156 class Win32Logger :
public Logger
159 friend class Win32Env;
160 virtual ~Win32Logger();
161 virtual void Logv(
const char* format, va_list ap);
163 explicit Win32Logger(WritableFile* pFile);
164 WritableFile* _pFileProxy;
165 DISALLOW_COPY_AND_ASSIGN(Win32Logger);
168 class Win32Env :
public Env
173 virtual Status NewSequentialFile(
const std::string& fname,
174 SequentialFile** result);
176 virtual Status NewRandomAccessFile(
const std::string& fname,
177 RandomAccessFile** result);
178 virtual Status NewWritableFile(
const std::string& fname,
179 WritableFile** result);
181 virtual bool FileExists(
const std::string& fname);
183 virtual Status GetChildren(
const std::string& dir,
184 std::vector<std::string>* result);
186 virtual Status DeleteFile(
const std::string& fname);
188 virtual Status CreateDir(
const std::string& dirname);
190 virtual Status DeleteDir(
const std::string& dirname);
192 virtual Status GetFileSize(
const std::string& fname,
uint64_t* file_size);
194 virtual Status RenameFile(
const std::string& src,
195 const std::string& target);
197 virtual Status LockFile(
const std::string& fname, FileLock** lock);
199 virtual Status UnlockFile(FileLock* lock);
201 virtual void Schedule(
202 void (*
function)(
void*
arg),
205 virtual void StartThread(
void (*
function)(
void*
arg),
void* arg);
207 virtual Status GetTestDirectory(std::string* path);
211 virtual Status NewLogger(
const std::string& fname, Logger** result);
215 virtual void SleepForMicroseconds(
int micros);
218 void ToWidePath(
const std::string&
value, std::wstring& target) {
220 MultiByteToWideChar(CP_ACP, 0, value.c_str(), -1, buffer,
MAX_PATH);
224 void ToNarrowPath(
const std::wstring& value, std::string& target) {
226 WideCharToMultiByte(CP_ACP, 0, value.c_str(), -1, buffer,
MAX_PATH, NULL, NULL);
230 std::string GetCurrentDir()
233 ::GetModuleFileNameA(::GetModuleHandleA(NULL),path,
MAX_PATH);
234 *strrchr(path,
'\\') = 0;
235 return std::string(path);
238 std::wstring GetCurrentDirW()
241 ::GetModuleFileNameW(::GetModuleHandleW(NULL),path,
MAX_PATH);
242 *wcsrchr(path,L
'\\') = 0;
243 return std::wstring(path);
246 std::string& ModifyPath(std::string& path)
248 if(path[0] ==
'/' || path[0] ==
'\\'){
249 path = CurrentDir + path;
251 std::replace(path.begin(),path.end(),
'/',
'\\');
256 std::wstring& ModifyPath(std::wstring& path)
258 if(path[0] == L
'/' || path[0] == L
'\\'){
259 path = CurrentDirW + path;
261 std::replace(path.begin(),path.end(),L
'/',L
'\\');
265 std::string GetLastErrSz()
269 FORMAT_MESSAGE_ALLOCATE_BUFFER |
270 FORMAT_MESSAGE_FROM_SYSTEM |
271 FORMAT_MESSAGE_IGNORE_INSERTS,
280 ToNarrowPath(lpMsgBuf, Err);
281 LocalFree( lpMsgBuf );
285 std::wstring GetLastErrSzW()
289 FORMAT_MESSAGE_ALLOCATE_BUFFER |
290 FORMAT_MESSAGE_FROM_SYSTEM |
291 FORMAT_MESSAGE_IGNORE_INSERTS,
299 std::wstring Err = (LPCWSTR)lpMsgBuf;
304 WorkItemWrapper::WorkItemWrapper( ScheduleProc proc_,
void* content_ ) :
305 proc(proc_),pContent(content_)
310 DWORD WINAPI WorkItemWrapperProc(LPVOID pContent)
312 WorkItemWrapper* item =
static_cast<WorkItemWrapper*
>(pContent);
313 ScheduleProc TempProc = item->proc;
314 void*
arg = item->pContent;
324 return std::max(si.dwPageSize,si.dwAllocationGranularity);
327 const size_t g_PageSize = GetPageSize();
330 Win32SequentialFile::Win32SequentialFile(
const std::string& fname ) :
331 _filename(fname),_hFile(NULL)
336 Win32SequentialFile::~Win32SequentialFile()
341 Status Win32SequentialFile::Read(
size_t n, Slice* result,
char* scratch )
345 if(_hFile && ReadFile(_hFile,scratch,n,&hasRead,NULL) ){
346 *result = Slice(scratch,hasRead);
348 sRet = Status::IOError(_filename, Win32::GetLastErrSz() );
353 Status Win32SequentialFile::Skip(
uint64_t n )
356 LARGE_INTEGER Move,NowPointer;
358 if(!SetFilePointerEx(_hFile,Move,&NowPointer,FILE_CURRENT)){
359 sRet = Status::IOError(_filename,Win32::GetLastErrSz());
364 BOOL Win32SequentialFile::isEnable()
366 return _hFile ? TRUE : FALSE;
369 BOOL Win32SequentialFile::_Init()
372 ToWidePath(_filename, path);
373 _hFile = CreateFileW(path.c_str(),
378 FILE_ATTRIBUTE_NORMAL,
380 return _hFile ? TRUE : FALSE;
383 void Win32SequentialFile::_CleanUp()
391 Win32RandomAccessFile::Win32RandomAccessFile(
const std::string& fname ) :
392 _filename(fname),_hFile(NULL)
395 ToWidePath(fname, path);
396 _Init( path.c_str() );
399 Win32RandomAccessFile::~Win32RandomAccessFile()
404 Status Win32RandomAccessFile::Read(
uint64_t offset,
size_t n,Slice* result,
char* scratch)
const
408 ZeroMemory(&ol,
sizeof(ol));
409 ol.Offset = (DWORD)offset;
410 ol.OffsetHigh = (DWORD)(offset >> 32);
412 if(!ReadFile(_hFile,scratch,n,&hasRead,&ol))
413 sRet = Status::IOError(_filename,Win32::GetLastErrSz());
415 *result = Slice(scratch,hasRead);
419 BOOL Win32RandomAccessFile::_Init( LPCWSTR path )
423 _hFile = ::CreateFileW(path,GENERIC_READ,FILE_SHARE_READ,NULL,OPEN_EXISTING,
424 FILE_ATTRIBUTE_NORMAL | FILE_FLAG_RANDOM_ACCESS,NULL);
425 if(!_hFile || _hFile == INVALID_HANDLE_VALUE )
432 BOOL Win32RandomAccessFile::isEnable()
434 return _hFile ? TRUE : FALSE;
437 void Win32RandomAccessFile::_CleanUp()
440 ::CloseHandle(_hFile);
445 size_t Win32MapFile::_Roundup(
size_t x,
size_t y )
447 return ((x + y - 1) / y) * y;
450 size_t Win32MapFile::_TruncateToPageBoundary(
size_t s )
452 s -= (s & (_page_size - 1));
453 assert((s % _page_size) == 0);
457 bool Win32MapFile::_UnmapCurrentRegion()
461 if (_last_sync < _limit) {
463 _pending_sync =
true;
465 if (!UnmapViewOfFile(_base) || !CloseHandle(_base_handle))
467 _file_offset += _limit - _base;
474 if (_map_size < (1<<20)) {
481 bool Win32MapFile::_MapNewRegion()
483 assert(_base == NULL);
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);
493 _base_handle = CreateFileMappingA(
500 if (_base_handle != NULL) {
501 _base = (
char*) MapViewOfFile(_base_handle,
507 _limit = _base + _map_size;
516 Win32MapFile::Win32MapFile(
const std::string& fname) :
519 _page_size(Win32::g_PageSize),
520 _map_size(_Roundup(65536, Win32::g_PageSize)),
530 ToWidePath(fname, path);
532 assert((Win32::g_PageSize & (Win32::g_PageSize - 1)) == 0);
535 Status Win32MapFile::Append(
const Slice& data )
537 const char* src = data.data();
538 size_t left = data.size();
541 assert(_base <= _dst);
542 assert(_dst <= _limit);
543 size_t avail = _limit - _dst;
545 if (!_UnmapCurrentRegion() ||
547 return Status::IOError(
"WinMmapFile.Append::UnmapCurrentRegion or MapNewRegion: ", Win32::GetLastErrSz());
550 size_t n = (left <= avail) ? left : avail;
551 memcpy(_dst, src, n);
559 Status Win32MapFile::Close()
562 size_t unused = _limit - _dst;
563 if (!_UnmapCurrentRegion()) {
564 s = Status::IOError(
"WinMmapFile.Close::UnmapCurrentRegion: ",Win32::GetLastErrSz());
565 }
else if (unused > 0) {
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());
572 SetEndOfFile(_hFile);
574 if (!CloseHandle(_hFile)) {
576 s = Status::IOError(
"WinMmapFile.Close::CloseHandle: ", Win32::GetLastErrSz());
579 _hFile = INVALID_HANDLE_VALUE;
587 Status Win32MapFile::Sync()
592 _pending_sync =
false;
593 if (!FlushFileBuffers(_hFile)) {
594 s = Status::IOError(
"WinMmapFile.Sync::FlushFileBuffers: ",Win32::GetLastErrSz());
597 if (_dst > _last_sync) {
600 size_t p1 = _TruncateToPageBoundary(_last_sync - _base);
601 size_t p2 = _TruncateToPageBoundary(_dst - _base - 1);
603 if (!FlushViewOfFile(_base + p1, p2 - p1 + _page_size)) {
604 s = Status::IOError(
"WinMmapFile.Sync::FlushViewOfFile: ",Win32::GetLastErrSz());
610 Status Win32MapFile::Flush()
615 Win32MapFile::~Win32MapFile()
617 if (_hFile != INVALID_HANDLE_VALUE) {
618 Win32MapFile::Close();
622 BOOL Win32MapFile::_Init( LPCWSTR Path )
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,
630 FILE_ATTRIBUTE_NORMAL,
632 if(!_hFile || _hFile == INVALID_HANDLE_VALUE)
638 BOOL Win32MapFile::isEnable()
640 return _hFile ? TRUE : FALSE;
643 Win32FileLock::Win32FileLock(
const std::string& fname ) :
644 _hFile(NULL),_filename(fname)
647 ToWidePath(fname, path);
651 Win32FileLock::~Win32FileLock()
656 BOOL Win32FileLock::_Init( LPCWSTR path )
660 _hFile = ::CreateFileW(path,0,0,NULL,CREATE_ALWAYS,FILE_ATTRIBUTE_NORMAL,NULL);
661 if(!_hFile || _hFile == INVALID_HANDLE_VALUE ){
669 void Win32FileLock::_CleanUp()
671 ::CloseHandle(_hFile);
675 BOOL Win32FileLock::isEnable()
677 return _hFile ? TRUE : FALSE;
680 Win32Logger::Win32Logger(WritableFile* pFile) : _pFileProxy(pFile)
685 Win32Logger::~Win32Logger()
691 void Win32Logger::Logv(
const char* format, va_list ap )
693 uint64_t thread_id = ::GetCurrentThreadId();
698 for (
int iter = 0; iter < 2; iter++) {
702 bufsize =
sizeof(buffer);
706 base =
new char[bufsize];
709 char* limit = base + bufsize;
713 p += snprintf(p, limit - p,
714 "%04d/%02d/%02d-%02d:%02d:%02d.%06d %llx ",
721 int(st.wMilliseconds),
722 static_cast<long long unsigned int>(thread_id));
727 va_copy(backup_ap, ap);
728 p += vsnprintf(p, limit - p, format, backup_ap);
742 if (p == base || p[-1] !=
'\n') {
747 DWORD hasWritten = 0;
749 _pFileProxy->Append(Slice(base, p - base));
750 _pFileProxy->Flush();
752 if (base != buffer) {
759 bool Win32Env::FileExists(
const std::string& fname)
761 std::string path = fname;
763 ToWidePath(ModifyPath(path), wpath);
764 return ::PathFileExistsW(wpath.c_str()) ?
true :
false;
767 Status Win32Env::GetChildren(
const std::string& dir, std::vector<std::string>* result)
770 ::WIN32_FIND_DATAW wfd;
771 std::string path = dir;
775 ToWidePath(path, wpath);
777 ::HANDLE hFind = ::FindFirstFileW(wpath.c_str() ,&wfd);
778 if(hFind && hFind != INVALID_HANDLE_VALUE){
782 ToNarrowPath(wfd.cFileName, child);
783 if(child !=
".." && child !=
".") {
784 result->push_back(child);
786 hasNext = ::FindNextFileW(hFind,&wfd);
791 sRet = Status::IOError(dir,
"Could not get children.");
795 void Win32Env::SleepForMicroseconds(
int micros )
797 ::Sleep((micros + 999) /1000);
801 Status Win32Env::DeleteFile(
const std::string& fname )
804 std::string path = fname;
806 ToWidePath(ModifyPath(path), wpath);
808 if(!::DeleteFileW(wpath.c_str())) {
809 sRet = Status::IOError(path,
"Could not delete file.");
814 Status Win32Env::GetFileSize(
const std::string& fname,
uint64_t* file_size )
817 std::string path = fname;
819 ToWidePath(ModifyPath(path), wpath);
821 HANDLE file = ::CreateFileW(wpath.c_str(),
822 GENERIC_READ,FILE_SHARE_READ,NULL,OPEN_EXISTING,FILE_ATTRIBUTE_NORMAL,NULL);
824 if(::GetFileSizeEx(file,&li)){
827 sRet = Status::IOError(path,
"Could not get the file size.");
832 Status Win32Env::RenameFile(
const std::string& src,
const std::string& target )
835 std::string src_path = src;
836 std::wstring wsrc_path;
837 ToWidePath(ModifyPath(src_path), wsrc_path);
838 std::string target_path = target;
839 std::wstring wtarget_path;
840 ToWidePath(ModifyPath(target_path), wtarget_path);
842 if(!MoveFileW(wsrc_path.c_str(), wtarget_path.c_str() ) ){
843 DWORD err = GetLastError();
844 if(err == 0x000000b7){
845 if(!::DeleteFileW(wtarget_path.c_str() ) )
846 sRet = Status::IOError(src,
"Could not rename file.");
847 else if(!::MoveFileW(wsrc_path.c_str(),
848 wtarget_path.c_str() ) )
849 sRet = Status::IOError(src,
"Could not rename file.");
855 Status Win32Env::LockFile(
const std::string& fname, FileLock** lock )
858 std::string path = fname;
860 Win32FileLock* _lock =
new Win32FileLock(path);
861 if(!_lock->isEnable()){
864 sRet = Status::IOError(path,
"Could not lock file.");
871 Status Win32Env::UnlockFile( FileLock* lock )
878 void Win32Env::Schedule(
void (*
function)(
void*
arg),
void* arg )
880 QueueUserWorkItem(Win32::WorkItemWrapperProc,
881 new Win32::WorkItemWrapper(
function,arg),
885 void Win32Env::StartThread(
void (*
function)(
void* arg),
void* arg )
887 ::_beginthread(
function,0,arg);
890 Status Win32Env::GetTestDirectory( std::string* path )
895 ToNarrowPath(TempPath, *path);
896 path->append(
"leveldb\\test\\");
903 #ifndef USE_VISTA_API
904 #define GetTickCount64 GetTickCount
906 return (
uint64_t)(GetTickCount64()*1000);
909 static Status CreateDirInner(
const std::string& dirname )
912 DWORD attr = ::GetFileAttributes(dirname.c_str());
913 if (attr == INVALID_FILE_ATTRIBUTES) {
914 std::size_t slash = dirname.find_last_of(
"\\");
915 if (slash != std::string::npos){
916 sRet = CreateDirInner(dirname.substr(0, slash));
917 if (!sRet.ok())
return sRet;
919 BOOL result = ::CreateDirectory(dirname.c_str(), NULL);
920 if (result == FALSE) {
921 sRet = Status::IOError(dirname,
"Could not create directory.");
928 Status Win32Env::CreateDir(
const std::string& dirname )
930 std::string path = dirname;
931 if(path[path.length() - 1] !=
'\\'){
936 return CreateDirInner(path);
939 Status Win32Env::DeleteDir(
const std::string& dirname )
943 ToWidePath(dirname, path);
945 if(!::RemoveDirectoryW( path.c_str() ) ){
946 sRet = Status::IOError(dirname,
"Could not delete directory.");
951 Status Win32Env::NewSequentialFile(
const std::string& fname, SequentialFile** result )
954 std::string path = fname;
956 Win32SequentialFile* pFile =
new Win32SequentialFile(path);
957 if(pFile->isEnable()){
961 sRet = Status::IOError(path, Win32::GetLastErrSz());
966 Status Win32Env::NewRandomAccessFile(
const std::string& fname, RandomAccessFile** result )
969 std::string path = fname;
970 Win32RandomAccessFile* pFile =
new Win32RandomAccessFile(ModifyPath(path));
971 if(!pFile->isEnable()){
974 sRet = Status::IOError(path, Win32::GetLastErrSz());
980 Status Win32Env::NewLogger(
const std::string& fname, Logger** result )
983 std::string path = fname;
984 Win32MapFile* pMapFile =
new Win32MapFile(ModifyPath(path));
985 if(!pMapFile->isEnable()){
988 sRet = Status::IOError(path,
"could not create a logger.");
990 *result =
new Win32Logger(pMapFile);
994 Status Win32Env::NewWritableFile(
const std::string& fname, WritableFile** result )
997 std::string path = fname;
998 Win32MapFile* pFile =
new Win32MapFile(ModifyPath(path));
999 if(!pFile->isEnable()){
1001 sRet = Status::IOError(fname,Win32::GetLastErrSz());
1007 Win32Env::Win32Env()
1012 Win32Env::~Win32Env()
1021 static Env* default_env;
1022 static void InitDefaultEnv() { default_env =
new Win32::Win32Env(); }
1024 Env* Env::Default() {
1031 #endif // defined(LEVELDB_PLATFORM_WINDOWS)
unsigned long long uint64_t
void InitOnce(port::OnceType *, void(*initializer)())
#define LEVELDB_ONCE_INIT