Update to LevelDB 1.20
[bitcoinplatinum.git] / src / leveldb / util / env_win.cc
blobd32c4e676c3fcd6dd29394298f541832032ef1a7
1 // This file contains source that originates from:
2 // http://code.google.com/p/leveldbwin/source/browse/trunk/win32_impl_src/env_win32.h
3 // http://code.google.com/p/leveldbwin/source/browse/trunk/win32_impl_src/port_win32.cc
4 // Those files don't have any explicit license headers but the
5 // project (http://code.google.com/p/leveldbwin/) lists the 'New BSD License'
6 // as the license.
7 #if defined(LEVELDB_PLATFORM_WINDOWS)
8 #include <map>
11 #include "leveldb/env.h"
13 #include "port/port.h"
14 #include "leveldb/slice.h"
15 #include "util/logging.h"
17 #include <shlwapi.h>
18 #include <process.h>
19 #include <cstring>
20 #include <stdio.h>
21 #include <errno.h>
22 #include <io.h>
23 #include <algorithm>
25 #ifdef max
26 #undef max
27 #endif
29 #ifndef va_copy
30 #define va_copy(d,s) ((d) = (s))
31 #endif
33 #if defined DeleteFile
34 #undef DeleteFile
35 #endif
37 //Declarations
38 namespace leveldb
41 namespace Win32
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();
60 size_t GetPageSize();
62 typedef void (*ScheduleProc)(void*) ;
64 struct WorkItemWrapper
66 WorkItemWrapper(ScheduleProc proc_,void* content_);
67 ScheduleProc proc;
68 void* pContent;
71 DWORD WINAPI WorkItemWrapperProc(LPVOID pContent);
73 class Win32SequentialFile : public SequentialFile
75 public:
76 friend class Win32Env;
77 virtual ~Win32SequentialFile();
78 virtual Status Read(size_t n, Slice* result, char* scratch);
79 virtual Status Skip(uint64_t n);
80 BOOL isEnable();
81 private:
82 BOOL _Init();
83 void _CleanUp();
84 Win32SequentialFile(const std::string& fname);
85 std::string _filename;
86 ::HANDLE _hFile;
87 DISALLOW_COPY_AND_ASSIGN(Win32SequentialFile);
90 class Win32RandomAccessFile : public RandomAccessFile
92 public:
93 friend class Win32Env;
94 virtual ~Win32RandomAccessFile();
95 virtual Status Read(uint64_t offset, size_t n, Slice* result,char* scratch) const;
96 BOOL isEnable();
97 private:
98 BOOL _Init(LPCWSTR path);
99 void _CleanUp();
100 Win32RandomAccessFile(const std::string& fname);
101 HANDLE _hFile;
102 const std::string _filename;
103 DISALLOW_COPY_AND_ASSIGN(Win32RandomAccessFile);
106 class Win32WritableFile : public WritableFile
108 public:
109 Win32WritableFile(const std::string& fname, bool append);
110 ~Win32WritableFile();
112 virtual Status Append(const Slice& data);
113 virtual Status Close();
114 virtual Status Flush();
115 virtual Status Sync();
116 BOOL isEnable();
117 private:
118 std::string filename_;
119 ::HANDLE _hFile;
122 class Win32FileLock : public FileLock
124 public:
125 friend class Win32Env;
126 virtual ~Win32FileLock();
127 BOOL isEnable();
128 private:
129 BOOL _Init(LPCWSTR path);
130 void _CleanUp();
131 Win32FileLock(const std::string& fname);
132 HANDLE _hFile;
133 std::string _filename;
134 DISALLOW_COPY_AND_ASSIGN(Win32FileLock);
137 class Win32Logger : public Logger
139 public:
140 friend class Win32Env;
141 virtual ~Win32Logger();
142 virtual void Logv(const char* format, va_list ap);
143 private:
144 explicit Win32Logger(WritableFile* pFile);
145 WritableFile* _pFileProxy;
146 DISALLOW_COPY_AND_ASSIGN(Win32Logger);
149 class Win32Env : public Env
151 public:
152 Win32Env();
153 virtual ~Win32Env();
154 virtual Status NewSequentialFile(const std::string& fname,
155 SequentialFile** result);
157 virtual Status NewRandomAccessFile(const std::string& fname,
158 RandomAccessFile** result);
159 virtual Status NewWritableFile(const std::string& fname,
160 WritableFile** result);
161 virtual Status NewAppendableFile(const std::string& fname,
162 WritableFile** result);
164 virtual bool FileExists(const std::string& fname);
166 virtual Status GetChildren(const std::string& dir,
167 std::vector<std::string>* result);
169 virtual Status DeleteFile(const std::string& fname);
171 virtual Status CreateDir(const std::string& dirname);
173 virtual Status DeleteDir(const std::string& dirname);
175 virtual Status GetFileSize(const std::string& fname, uint64_t* file_size);
177 virtual Status RenameFile(const std::string& src,
178 const std::string& target);
180 virtual Status LockFile(const std::string& fname, FileLock** lock);
182 virtual Status UnlockFile(FileLock* lock);
184 virtual void Schedule(
185 void (*function)(void* arg),
186 void* arg);
188 virtual void StartThread(void (*function)(void* arg), void* arg);
190 virtual Status GetTestDirectory(std::string* path);
192 //virtual void Logv(WritableFile* log, const char* format, va_list ap);
194 virtual Status NewLogger(const std::string& fname, Logger** result);
196 virtual uint64_t NowMicros();
198 virtual void SleepForMicroseconds(int micros);
201 void ToWidePath(const std::string& value, std::wstring& target) {
202 wchar_t buffer[MAX_PATH];
203 MultiByteToWideChar(CP_ACP, 0, value.c_str(), -1, buffer, MAX_PATH);
204 target = buffer;
207 void ToNarrowPath(const std::wstring& value, std::string& target) {
208 char buffer[MAX_PATH];
209 WideCharToMultiByte(CP_ACP, 0, value.c_str(), -1, buffer, MAX_PATH, NULL, NULL);
210 target = buffer;
213 std::string GetCurrentDir()
215 CHAR path[MAX_PATH];
216 ::GetModuleFileNameA(::GetModuleHandleA(NULL),path,MAX_PATH);
217 *strrchr(path,'\\') = 0;
218 return std::string(path);
221 std::wstring GetCurrentDirW()
223 WCHAR path[MAX_PATH];
224 ::GetModuleFileNameW(::GetModuleHandleW(NULL),path,MAX_PATH);
225 *wcsrchr(path,L'\\') = 0;
226 return std::wstring(path);
229 std::string& ModifyPath(std::string& path)
231 if(path[0] == '/' || path[0] == '\\'){
232 path = CurrentDir + path;
234 std::replace(path.begin(),path.end(),'/','\\');
236 return path;
239 std::wstring& ModifyPath(std::wstring& path)
241 if(path[0] == L'/' || path[0] == L'\\'){
242 path = CurrentDirW + path;
244 std::replace(path.begin(),path.end(),L'/',L'\\');
245 return path;
248 std::string GetLastErrSz()
250 LPWSTR lpMsgBuf;
251 FormatMessageW(
252 FORMAT_MESSAGE_ALLOCATE_BUFFER |
253 FORMAT_MESSAGE_FROM_SYSTEM |
254 FORMAT_MESSAGE_IGNORE_INSERTS,
255 NULL,
256 GetLastError(),
257 0, // Default language
258 (LPWSTR) &lpMsgBuf,
260 NULL
262 std::string Err;
263 ToNarrowPath(lpMsgBuf, Err);
264 LocalFree( lpMsgBuf );
265 return Err;
268 std::wstring GetLastErrSzW()
270 LPVOID lpMsgBuf;
271 FormatMessageW(
272 FORMAT_MESSAGE_ALLOCATE_BUFFER |
273 FORMAT_MESSAGE_FROM_SYSTEM |
274 FORMAT_MESSAGE_IGNORE_INSERTS,
275 NULL,
276 GetLastError(),
277 0, // Default language
278 (LPWSTR) &lpMsgBuf,
280 NULL
282 std::wstring Err = (LPCWSTR)lpMsgBuf;
283 LocalFree(lpMsgBuf);
284 return Err;
287 WorkItemWrapper::WorkItemWrapper( ScheduleProc proc_,void* content_ ) :
288 proc(proc_),pContent(content_)
293 DWORD WINAPI WorkItemWrapperProc(LPVOID pContent)
295 WorkItemWrapper* item = static_cast<WorkItemWrapper*>(pContent);
296 ScheduleProc TempProc = item->proc;
297 void* arg = item->pContent;
298 delete item;
299 TempProc(arg);
300 return 0;
303 size_t GetPageSize()
305 SYSTEM_INFO si;
306 GetSystemInfo(&si);
307 return std::max(si.dwPageSize,si.dwAllocationGranularity);
310 const size_t g_PageSize = GetPageSize();
313 Win32SequentialFile::Win32SequentialFile( const std::string& fname ) :
314 _filename(fname),_hFile(NULL)
316 _Init();
319 Win32SequentialFile::~Win32SequentialFile()
321 _CleanUp();
324 Status Win32SequentialFile::Read( size_t n, Slice* result, char* scratch )
326 Status sRet;
327 DWORD hasRead = 0;
328 if(_hFile && ReadFile(_hFile,scratch,n,&hasRead,NULL) ){
329 *result = Slice(scratch,hasRead);
330 } else {
331 sRet = Status::IOError(_filename, Win32::GetLastErrSz() );
333 return sRet;
336 Status Win32SequentialFile::Skip( uint64_t n )
338 Status sRet;
339 LARGE_INTEGER Move,NowPointer;
340 Move.QuadPart = n;
341 if(!SetFilePointerEx(_hFile,Move,&NowPointer,FILE_CURRENT)){
342 sRet = Status::IOError(_filename,Win32::GetLastErrSz());
344 return sRet;
347 BOOL Win32SequentialFile::isEnable()
349 return _hFile ? TRUE : FALSE;
352 BOOL Win32SequentialFile::_Init()
354 std::wstring path;
355 ToWidePath(_filename, path);
356 _hFile = CreateFileW(path.c_str(),
357 GENERIC_READ,
358 FILE_SHARE_READ | FILE_SHARE_WRITE,
359 NULL,
360 OPEN_EXISTING,
361 FILE_ATTRIBUTE_NORMAL | FILE_FLAG_SEQUENTIAL_SCAN,
362 NULL);
363 if (_hFile == INVALID_HANDLE_VALUE)
364 _hFile = NULL;
365 return _hFile ? TRUE : FALSE;
368 void Win32SequentialFile::_CleanUp()
370 if(_hFile){
371 CloseHandle(_hFile);
372 _hFile = NULL;
376 Win32RandomAccessFile::Win32RandomAccessFile( const std::string& fname ) :
377 _filename(fname),_hFile(NULL)
379 std::wstring path;
380 ToWidePath(fname, path);
381 _Init( path.c_str() );
384 Win32RandomAccessFile::~Win32RandomAccessFile()
386 _CleanUp();
389 Status Win32RandomAccessFile::Read(uint64_t offset,size_t n,Slice* result,char* scratch) const
391 Status sRet;
392 OVERLAPPED ol = {0};
393 ZeroMemory(&ol,sizeof(ol));
394 ol.Offset = (DWORD)offset;
395 ol.OffsetHigh = (DWORD)(offset >> 32);
396 DWORD hasRead = 0;
397 if(!ReadFile(_hFile,scratch,n,&hasRead,&ol))
398 sRet = Status::IOError(_filename,Win32::GetLastErrSz());
399 else
400 *result = Slice(scratch,hasRead);
401 return sRet;
404 BOOL Win32RandomAccessFile::_Init( LPCWSTR path )
406 BOOL bRet = FALSE;
407 if(!_hFile)
408 _hFile = ::CreateFileW(path,GENERIC_READ,FILE_SHARE_READ|FILE_SHARE_WRITE,NULL,OPEN_EXISTING,
409 FILE_ATTRIBUTE_NORMAL | FILE_FLAG_RANDOM_ACCESS,NULL);
410 if(!_hFile || _hFile == INVALID_HANDLE_VALUE )
411 _hFile = NULL;
412 else
413 bRet = TRUE;
414 return bRet;
417 BOOL Win32RandomAccessFile::isEnable()
419 return _hFile ? TRUE : FALSE;
422 void Win32RandomAccessFile::_CleanUp()
424 if(_hFile){
425 ::CloseHandle(_hFile);
426 _hFile = NULL;
430 Win32WritableFile::Win32WritableFile(const std::string& fname, bool append)
431 : filename_(fname)
433 std::wstring path;
434 ToWidePath(fname, path);
435 // NewAppendableFile: append to an existing file, or create a new one
436 // if none exists - this is OPEN_ALWAYS behavior, with
437 // FILE_APPEND_DATA to avoid having to manually position the file
438 // pointer at the end of the file.
439 // NewWritableFile: create a new file, delete if it exists - this is
440 // CREATE_ALWAYS behavior. This file is used for writing only so
441 // use GENERIC_WRITE.
442 _hFile = CreateFileW(path.c_str(),
443 append ? FILE_APPEND_DATA : GENERIC_WRITE,
444 FILE_SHARE_READ|FILE_SHARE_DELETE|FILE_SHARE_WRITE,
445 NULL,
446 append ? OPEN_ALWAYS : CREATE_ALWAYS,
447 FILE_ATTRIBUTE_NORMAL,
448 NULL);
449 // CreateFileW returns INVALID_HANDLE_VALUE in case of error, always check isEnable() before use
452 Win32WritableFile::~Win32WritableFile()
454 if (_hFile != INVALID_HANDLE_VALUE)
455 Close();
458 Status Win32WritableFile::Append(const Slice& data)
460 DWORD r = 0;
461 if (!WriteFile(_hFile, data.data(), data.size(), &r, NULL) || r != data.size()) {
462 return Status::IOError("Win32WritableFile.Append::WriteFile: "+filename_, Win32::GetLastErrSz());
464 return Status::OK();
467 Status Win32WritableFile::Close()
469 if (!CloseHandle(_hFile)) {
470 return Status::IOError("Win32WritableFile.Close::CloseHandle: "+filename_, Win32::GetLastErrSz());
472 _hFile = INVALID_HANDLE_VALUE;
473 return Status::OK();
476 Status Win32WritableFile::Flush()
478 // Nothing to do here, there are no application-side buffers
479 return Status::OK();
482 Status Win32WritableFile::Sync()
484 if (!FlushFileBuffers(_hFile)) {
485 return Status::IOError("Win32WritableFile.Sync::FlushFileBuffers "+filename_, Win32::GetLastErrSz());
487 return Status::OK();
490 BOOL Win32WritableFile::isEnable()
492 return _hFile != INVALID_HANDLE_VALUE;
495 Win32FileLock::Win32FileLock( const std::string& fname ) :
496 _hFile(NULL),_filename(fname)
498 std::wstring path;
499 ToWidePath(fname, path);
500 _Init(path.c_str());
503 Win32FileLock::~Win32FileLock()
505 _CleanUp();
508 BOOL Win32FileLock::_Init( LPCWSTR path )
510 BOOL bRet = FALSE;
511 if(!_hFile)
512 _hFile = ::CreateFileW(path,0,0,NULL,CREATE_ALWAYS,FILE_ATTRIBUTE_NORMAL,NULL);
513 if(!_hFile || _hFile == INVALID_HANDLE_VALUE ){
514 _hFile = NULL;
516 else
517 bRet = TRUE;
518 return bRet;
521 void Win32FileLock::_CleanUp()
523 ::CloseHandle(_hFile);
524 _hFile = NULL;
527 BOOL Win32FileLock::isEnable()
529 return _hFile ? TRUE : FALSE;
532 Win32Logger::Win32Logger(WritableFile* pFile) : _pFileProxy(pFile)
534 assert(_pFileProxy);
537 Win32Logger::~Win32Logger()
539 if(_pFileProxy)
540 delete _pFileProxy;
543 void Win32Logger::Logv( const char* format, va_list ap )
545 uint64_t thread_id = ::GetCurrentThreadId();
547 // We try twice: the first time with a fixed-size stack allocated buffer,
548 // and the second time with a much larger dynamically allocated buffer.
549 char buffer[500];
550 for (int iter = 0; iter < 2; iter++) {
551 char* base;
552 int bufsize;
553 if (iter == 0) {
554 bufsize = sizeof(buffer);
555 base = buffer;
556 } else {
557 bufsize = 30000;
558 base = new char[bufsize];
560 char* p = base;
561 char* limit = base + bufsize;
563 SYSTEMTIME st;
564 GetLocalTime(&st);
565 p += snprintf(p, limit - p,
566 "%04d/%02d/%02d-%02d:%02d:%02d.%06d %llx ",
567 int(st.wYear),
568 int(st.wMonth),
569 int(st.wDay),
570 int(st.wHour),
571 int(st.wMinute),
572 int(st.wMinute),
573 int(st.wMilliseconds),
574 static_cast<long long unsigned int>(thread_id));
576 // Print the message
577 if (p < limit) {
578 va_list backup_ap;
579 va_copy(backup_ap, ap);
580 p += vsnprintf(p, limit - p, format, backup_ap);
581 va_end(backup_ap);
584 // Truncate to available space if necessary
585 if (p >= limit) {
586 if (iter == 0) {
587 continue; // Try again with larger buffer
588 } else {
589 p = limit - 1;
593 // Add newline if necessary
594 if (p == base || p[-1] != '\n') {
595 *p++ = '\n';
598 assert(p <= limit);
599 DWORD hasWritten = 0;
600 if(_pFileProxy){
601 _pFileProxy->Append(Slice(base, p - base));
602 _pFileProxy->Flush();
604 if (base != buffer) {
605 delete[] base;
607 break;
611 bool Win32Env::FileExists(const std::string& fname)
613 std::string path = fname;
614 std::wstring wpath;
615 ToWidePath(ModifyPath(path), wpath);
616 return ::PathFileExistsW(wpath.c_str()) ? true : false;
619 Status Win32Env::GetChildren(const std::string& dir, std::vector<std::string>* result)
621 Status sRet;
622 ::WIN32_FIND_DATAW wfd;
623 std::string path = dir;
624 ModifyPath(path);
625 path += "\\*.*";
626 std::wstring wpath;
627 ToWidePath(path, wpath);
629 ::HANDLE hFind = ::FindFirstFileW(wpath.c_str() ,&wfd);
630 if(hFind && hFind != INVALID_HANDLE_VALUE){
631 BOOL hasNext = TRUE;
632 std::string child;
633 while(hasNext){
634 ToNarrowPath(wfd.cFileName, child);
635 if(child != ".." && child != ".") {
636 result->push_back(child);
638 hasNext = ::FindNextFileW(hFind,&wfd);
640 ::FindClose(hFind);
642 else
643 sRet = Status::IOError(dir,"Could not get children.");
644 return sRet;
647 void Win32Env::SleepForMicroseconds( int micros )
649 ::Sleep((micros + 999) /1000);
653 Status Win32Env::DeleteFile( const std::string& fname )
655 Status sRet;
656 std::string path = fname;
657 std::wstring wpath;
658 ToWidePath(ModifyPath(path), wpath);
660 if(!::DeleteFileW(wpath.c_str())) {
661 sRet = Status::IOError(path, "Could not delete file.");
663 return sRet;
666 Status Win32Env::GetFileSize( const std::string& fname, uint64_t* file_size )
668 Status sRet;
669 std::string path = fname;
670 std::wstring wpath;
671 ToWidePath(ModifyPath(path), wpath);
673 HANDLE file = ::CreateFileW(wpath.c_str(),
674 GENERIC_READ,FILE_SHARE_READ|FILE_SHARE_WRITE,NULL,OPEN_EXISTING,FILE_ATTRIBUTE_NORMAL,NULL);
675 LARGE_INTEGER li;
676 if(::GetFileSizeEx(file,&li)){
677 *file_size = (uint64_t)li.QuadPart;
678 }else
679 sRet = Status::IOError(path,"Could not get the file size.");
680 CloseHandle(file);
681 return sRet;
684 Status Win32Env::RenameFile( const std::string& src, const std::string& target )
686 Status sRet;
687 std::string src_path = src;
688 std::wstring wsrc_path;
689 ToWidePath(ModifyPath(src_path), wsrc_path);
690 std::string target_path = target;
691 std::wstring wtarget_path;
692 ToWidePath(ModifyPath(target_path), wtarget_path);
694 if(!MoveFileW(wsrc_path.c_str(), wtarget_path.c_str() ) ){
695 DWORD err = GetLastError();
696 if(err == 0x000000b7){
697 if(!::DeleteFileW(wtarget_path.c_str() ) )
698 sRet = Status::IOError(src, "Could not rename file.");
699 else if(!::MoveFileW(wsrc_path.c_str(),
700 wtarget_path.c_str() ) )
701 sRet = Status::IOError(src, "Could not rename file.");
704 return sRet;
707 Status Win32Env::LockFile( const std::string& fname, FileLock** lock )
709 Status sRet;
710 std::string path = fname;
711 ModifyPath(path);
712 Win32FileLock* _lock = new Win32FileLock(path);
713 if(!_lock->isEnable()){
714 delete _lock;
715 *lock = NULL;
716 sRet = Status::IOError(path, "Could not lock file.");
718 else
719 *lock = _lock;
720 return sRet;
723 Status Win32Env::UnlockFile( FileLock* lock )
725 Status sRet;
726 delete lock;
727 return sRet;
730 void Win32Env::Schedule( void (*function)(void* arg), void* arg )
732 QueueUserWorkItem(Win32::WorkItemWrapperProc,
733 new Win32::WorkItemWrapper(function,arg),
734 WT_EXECUTEDEFAULT);
737 void Win32Env::StartThread( void (*function)(void* arg), void* arg )
739 ::_beginthread(function,0,arg);
742 Status Win32Env::GetTestDirectory( std::string* path )
744 Status sRet;
745 WCHAR TempPath[MAX_PATH];
746 ::GetTempPathW(MAX_PATH,TempPath);
747 ToNarrowPath(TempPath, *path);
748 path->append("leveldb\\test\\");
749 ModifyPath(*path);
750 return sRet;
753 uint64_t Win32Env::NowMicros()
755 #ifndef USE_VISTA_API
756 #define GetTickCount64 GetTickCount
757 #endif
758 return (uint64_t)(GetTickCount64()*1000);
761 static Status CreateDirInner( const std::string& dirname )
763 Status sRet;
764 DWORD attr = ::GetFileAttributes(dirname.c_str());
765 if (attr == INVALID_FILE_ATTRIBUTES) { // doesn't exist:
766 std::size_t slash = dirname.find_last_of("\\");
767 if (slash != std::string::npos){
768 sRet = CreateDirInner(dirname.substr(0, slash));
769 if (!sRet.ok()) return sRet;
771 BOOL result = ::CreateDirectory(dirname.c_str(), NULL);
772 if (result == FALSE) {
773 sRet = Status::IOError(dirname, "Could not create directory.");
774 return sRet;
777 return sRet;
780 Status Win32Env::CreateDir( const std::string& dirname )
782 std::string path = dirname;
783 if(path[path.length() - 1] != '\\'){
784 path += '\\';
786 ModifyPath(path);
788 return CreateDirInner(path);
791 Status Win32Env::DeleteDir( const std::string& dirname )
793 Status sRet;
794 std::wstring path;
795 ToWidePath(dirname, path);
796 ModifyPath(path);
797 if(!::RemoveDirectoryW( path.c_str() ) ){
798 sRet = Status::IOError(dirname, "Could not delete directory.");
800 return sRet;
803 Status Win32Env::NewSequentialFile( const std::string& fname, SequentialFile** result )
805 Status sRet;
806 std::string path = fname;
807 ModifyPath(path);
808 Win32SequentialFile* pFile = new Win32SequentialFile(path);
809 if(pFile->isEnable()){
810 *result = pFile;
811 }else {
812 delete pFile;
813 sRet = Status::IOError(path, Win32::GetLastErrSz());
815 return sRet;
818 Status Win32Env::NewRandomAccessFile( const std::string& fname, RandomAccessFile** result )
820 Status sRet;
821 std::string path = fname;
822 Win32RandomAccessFile* pFile = new Win32RandomAccessFile(ModifyPath(path));
823 if(!pFile->isEnable()){
824 delete pFile;
825 *result = NULL;
826 sRet = Status::IOError(path, Win32::GetLastErrSz());
827 }else
828 *result = pFile;
829 return sRet;
832 Status Win32Env::NewLogger( const std::string& fname, Logger** result )
834 Status sRet;
835 std::string path = fname;
836 // Logs are opened with write semantics, not with append semantics
837 // (see PosixEnv::NewLogger)
838 Win32WritableFile* pMapFile = new Win32WritableFile(ModifyPath(path), false);
839 if(!pMapFile->isEnable()){
840 delete pMapFile;
841 *result = NULL;
842 sRet = Status::IOError(path,"could not create a logger.");
843 }else
844 *result = new Win32Logger(pMapFile);
845 return sRet;
848 Status Win32Env::NewWritableFile( const std::string& fname, WritableFile** result )
850 Status sRet;
851 std::string path = fname;
852 Win32WritableFile* pFile = new Win32WritableFile(ModifyPath(path), false);
853 if(!pFile->isEnable()){
854 *result = NULL;
855 sRet = Status::IOError(fname,Win32::GetLastErrSz());
856 }else
857 *result = pFile;
858 return sRet;
861 Status Win32Env::NewAppendableFile( const std::string& fname, WritableFile** result )
863 Status sRet;
864 std::string path = fname;
865 Win32WritableFile* pFile = new Win32WritableFile(ModifyPath(path), true);
866 if(!pFile->isEnable()){
867 *result = NULL;
868 sRet = Status::IOError(fname,Win32::GetLastErrSz());
869 }else
870 *result = pFile;
871 return sRet;
874 Win32Env::Win32Env()
879 Win32Env::~Win32Env()
885 } // Win32 namespace
887 static port::OnceType once = LEVELDB_ONCE_INIT;
888 static Env* default_env;
889 static void InitDefaultEnv() { default_env = new Win32::Win32Env(); }
891 Env* Env::Default() {
892 port::InitOnce(&once, InitDefaultEnv);
893 return default_env;
896 } // namespace leveldb
898 #endif // defined(LEVELDB_PLATFORM_WINDOWS)