Feathercoin  0.5.0
P2P Digital Currency
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros
env_win.cc
Go to the documentation of this file.
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 dont' have any explict 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>
9 
10 
11 #include "leveldb/env.h"
12 
13 #include "port/port.h"
14 #include "leveldb/slice.h"
15 #include "util/logging.h"
16 
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>
24 
25 #ifdef max
26 #undef max
27 #endif
28 
29 #ifndef va_copy
30 #define va_copy(d,s) ((d) = (s))
31 #endif
32 
33 #if defined DeleteFile
34 #undef DeleteFile
35 #endif
36 
37 //Declarations
38 namespace leveldb
39 {
40 
41 namespace Win32
42 {
43 
44 #define DISALLOW_COPY_AND_ASSIGN(TypeName) \
45  TypeName(const TypeName&); \
46  void operator=(const TypeName&)
47 
48 std::string GetCurrentDir();
49 std::wstring GetCurrentDirW();
50 
51 static const std::string CurrentDir = GetCurrentDir();
52 static const std::wstring CurrentDirW = GetCurrentDirW();
53 
54 std::string& ModifyPath(std::string& path);
55 std::wstring& ModifyPath(std::wstring& path);
56 
57 std::string GetLastErrSz();
58 std::wstring GetLastErrSzW();
59 
60 size_t GetPageSize();
61 
62 typedef void (*ScheduleProc)(void*) ;
63 
64 struct WorkItemWrapper
65 {
66  WorkItemWrapper(ScheduleProc proc_,void* content_);
67  ScheduleProc proc;
68  void* pContent;
69 };
70 
71 DWORD WINAPI WorkItemWrapperProc(LPVOID pContent);
72 
73 class Win32SequentialFile : public SequentialFile
74 {
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);
88 };
89 
90 class Win32RandomAccessFile : public RandomAccessFile
91 {
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);
104 };
105 
106 class Win32MapFile : public WritableFile
107 {
108 public:
109  Win32MapFile(const std::string& fname);
110 
111  ~Win32MapFile();
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;
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);
139 };
140 
141 class Win32FileLock : public FileLock
142 {
143 public:
144  friend class Win32Env;
145  virtual ~Win32FileLock();
146  BOOL isEnable();
147 private:
148  BOOL _Init(LPCWSTR path);
149  void _CleanUp();
150  Win32FileLock(const std::string& fname);
151  HANDLE _hFile;
152  std::string _filename;
153  DISALLOW_COPY_AND_ASSIGN(Win32FileLock);
154 };
155 
156 class Win32Logger : public Logger
157 {
158 public:
159  friend class Win32Env;
160  virtual ~Win32Logger();
161  virtual void Logv(const char* format, va_list ap);
162 private:
163  explicit Win32Logger(WritableFile* pFile);
164  WritableFile* _pFileProxy;
165  DISALLOW_COPY_AND_ASSIGN(Win32Logger);
166 };
167 
168 class Win32Env : public Env
169 {
170 public:
171  Win32Env();
172  virtual ~Win32Env();
173  virtual Status NewSequentialFile(const std::string& fname,
174  SequentialFile** result);
175 
176  virtual Status NewRandomAccessFile(const std::string& fname,
177  RandomAccessFile** result);
178  virtual Status NewWritableFile(const std::string& fname,
179  WritableFile** result);
180 
181  virtual bool FileExists(const std::string& fname);
182 
183  virtual Status GetChildren(const std::string& dir,
184  std::vector<std::string>* result);
185 
186  virtual Status DeleteFile(const std::string& fname);
187 
188  virtual Status CreateDir(const std::string& dirname);
189 
190  virtual Status DeleteDir(const std::string& dirname);
191 
192  virtual Status GetFileSize(const std::string& fname, uint64_t* file_size);
193 
194  virtual Status RenameFile(const std::string& src,
195  const std::string& target);
196 
197  virtual Status LockFile(const std::string& fname, FileLock** lock);
198 
199  virtual Status UnlockFile(FileLock* lock);
200 
201  virtual void Schedule(
202  void (*function)(void* arg),
203  void* arg);
204 
205  virtual void StartThread(void (*function)(void* arg), void* arg);
206 
207  virtual Status GetTestDirectory(std::string* path);
208 
209  //virtual void Logv(WritableFile* log, const char* format, va_list ap);
210 
211  virtual Status NewLogger(const std::string& fname, Logger** result);
212 
213  virtual uint64_t NowMicros();
214 
215  virtual void SleepForMicroseconds(int micros);
216 };
217 
218 void ToWidePath(const std::string& value, std::wstring& target) {
219  wchar_t buffer[MAX_PATH];
220  MultiByteToWideChar(CP_ACP, 0, value.c_str(), -1, buffer, MAX_PATH);
221  target = buffer;
222 }
223 
224 void ToNarrowPath(const std::wstring& value, std::string& target) {
225  char buffer[MAX_PATH];
226  WideCharToMultiByte(CP_ACP, 0, value.c_str(), -1, buffer, MAX_PATH, NULL, NULL);
227  target = buffer;
228 }
229 
230 std::string GetCurrentDir()
231 {
232  CHAR path[MAX_PATH];
233  ::GetModuleFileNameA(::GetModuleHandleA(NULL),path,MAX_PATH);
234  *strrchr(path,'\\') = 0;
235  return std::string(path);
236 }
237 
238 std::wstring GetCurrentDirW()
239 {
240  WCHAR path[MAX_PATH];
241  ::GetModuleFileNameW(::GetModuleHandleW(NULL),path,MAX_PATH);
242  *wcsrchr(path,L'\\') = 0;
243  return std::wstring(path);
244 }
245 
246 std::string& ModifyPath(std::string& path)
247 {
248  if(path[0] == '/' || path[0] == '\\'){
249  path = CurrentDir + path;
250  }
251  std::replace(path.begin(),path.end(),'/','\\');
252 
253  return path;
254 }
255 
256 std::wstring& ModifyPath(std::wstring& path)
257 {
258  if(path[0] == L'/' || path[0] == L'\\'){
259  path = CurrentDirW + path;
260  }
261  std::replace(path.begin(),path.end(),L'/',L'\\');
262  return path;
263 }
264 
265 std::string GetLastErrSz()
266 {
267  LPWSTR lpMsgBuf;
268  FormatMessageW(
269  FORMAT_MESSAGE_ALLOCATE_BUFFER |
270  FORMAT_MESSAGE_FROM_SYSTEM |
271  FORMAT_MESSAGE_IGNORE_INSERTS,
272  NULL,
273  GetLastError(),
274  0, // Default language
275  (LPWSTR) &lpMsgBuf,
276  0,
277  NULL
278  );
279  std::string Err;
280  ToNarrowPath(lpMsgBuf, Err);
281  LocalFree( lpMsgBuf );
282  return Err;
283 }
284 
285 std::wstring GetLastErrSzW()
286 {
287  LPVOID lpMsgBuf;
288  FormatMessageW(
289  FORMAT_MESSAGE_ALLOCATE_BUFFER |
290  FORMAT_MESSAGE_FROM_SYSTEM |
291  FORMAT_MESSAGE_IGNORE_INSERTS,
292  NULL,
293  GetLastError(),
294  0, // Default language
295  (LPWSTR) &lpMsgBuf,
296  0,
297  NULL
298  );
299  std::wstring Err = (LPCWSTR)lpMsgBuf;
300  LocalFree(lpMsgBuf);
301  return Err;
302 }
303 
304 WorkItemWrapper::WorkItemWrapper( ScheduleProc proc_,void* content_ ) :
305  proc(proc_),pContent(content_)
306 {
307 
308 }
309 
310 DWORD WINAPI WorkItemWrapperProc(LPVOID pContent)
311 {
312  WorkItemWrapper* item = static_cast<WorkItemWrapper*>(pContent);
313  ScheduleProc TempProc = item->proc;
314  void* arg = item->pContent;
315  delete item;
316  TempProc(arg);
317  return 0;
318 }
319 
320 size_t GetPageSize()
321 {
322  SYSTEM_INFO si;
323  GetSystemInfo(&si);
324  return std::max(si.dwPageSize,si.dwAllocationGranularity);
325 }
326 
327 const size_t g_PageSize = GetPageSize();
328 
329 
330 Win32SequentialFile::Win32SequentialFile( const std::string& fname ) :
331  _filename(fname),_hFile(NULL)
332 {
333  _Init();
334 }
335 
336 Win32SequentialFile::~Win32SequentialFile()
337 {
338  _CleanUp();
339 }
340 
341 Status Win32SequentialFile::Read( size_t n, Slice* result, char* scratch )
342 {
343  Status sRet;
344  DWORD hasRead = 0;
345  if(_hFile && ReadFile(_hFile,scratch,n,&hasRead,NULL) ){
346  *result = Slice(scratch,hasRead);
347  } else {
348  sRet = Status::IOError(_filename, Win32::GetLastErrSz() );
349  }
350  return sRet;
351 }
352 
353 Status Win32SequentialFile::Skip( uint64_t n )
354 {
355  Status sRet;
356  LARGE_INTEGER Move,NowPointer;
357  Move.QuadPart = n;
358  if(!SetFilePointerEx(_hFile,Move,&NowPointer,FILE_CURRENT)){
359  sRet = Status::IOError(_filename,Win32::GetLastErrSz());
360  }
361  return sRet;
362 }
363 
364 BOOL Win32SequentialFile::isEnable()
365 {
366  return _hFile ? TRUE : FALSE;
367 }
368 
369 BOOL Win32SequentialFile::_Init()
370 {
371  std::wstring path;
372  ToWidePath(_filename, path);
373  _hFile = CreateFileW(path.c_str(),
374  GENERIC_READ,
375  FILE_SHARE_READ,
376  NULL,
377  OPEN_EXISTING,
378  FILE_ATTRIBUTE_NORMAL,
379  NULL);
380  return _hFile ? TRUE : FALSE;
381 }
382 
383 void Win32SequentialFile::_CleanUp()
384 {
385  if(_hFile){
386  CloseHandle(_hFile);
387  _hFile = NULL;
388  }
389 }
390 
391 Win32RandomAccessFile::Win32RandomAccessFile( const std::string& fname ) :
392  _filename(fname),_hFile(NULL)
393 {
394  std::wstring path;
395  ToWidePath(fname, path);
396  _Init( path.c_str() );
397 }
398 
399 Win32RandomAccessFile::~Win32RandomAccessFile()
400 {
401  _CleanUp();
402 }
403 
404 Status Win32RandomAccessFile::Read(uint64_t offset,size_t n,Slice* result,char* scratch) const
405 {
406  Status sRet;
407  OVERLAPPED ol = {0};
408  ZeroMemory(&ol,sizeof(ol));
409  ol.Offset = (DWORD)offset;
410  ol.OffsetHigh = (DWORD)(offset >> 32);
411  DWORD hasRead = 0;
412  if(!ReadFile(_hFile,scratch,n,&hasRead,&ol))
413  sRet = Status::IOError(_filename,Win32::GetLastErrSz());
414  else
415  *result = Slice(scratch,hasRead);
416  return sRet;
417 }
418 
419 BOOL Win32RandomAccessFile::_Init( LPCWSTR path )
420 {
421  BOOL bRet = FALSE;
422  if(!_hFile)
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 )
426  _hFile = NULL;
427  else
428  bRet = TRUE;
429  return bRet;
430 }
431 
432 BOOL Win32RandomAccessFile::isEnable()
433 {
434  return _hFile ? TRUE : FALSE;
435 }
436 
437 void Win32RandomAccessFile::_CleanUp()
438 {
439  if(_hFile){
440  ::CloseHandle(_hFile);
441  _hFile = NULL;
442  }
443 }
444 
445 size_t Win32MapFile::_Roundup( size_t x, size_t y )
446 {
447  return ((x + y - 1) / y) * y;
448 }
449 
450 size_t Win32MapFile::_TruncateToPageBoundary( size_t s )
451 {
452  s -= (s & (_page_size - 1));
453  assert((s % _page_size) == 0);
454  return s;
455 }
456 
457 bool Win32MapFile::_UnmapCurrentRegion()
458 {
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  }
477  }
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;
514 }
515 
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)
528 {
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  }
574  if (!CloseHandle(_hFile)) {
575  if (s.ok()) {
576  s = Status::IOError("WinMmapFile.Close::CloseHandle: ", Win32::GetLastErrSz());
577  }
578  }
579  _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;
608 }
609 
610 Status Win32MapFile::Flush()
611 {
612  return Status::OK();
613 }
614 
615 Win32MapFile::~Win32MapFile()
616 {
617  if (_hFile != INVALID_HANDLE_VALUE) {
618  Win32MapFile::Close();
619  }
620 }
621 
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()
639 {
640  return _hFile ? TRUE : FALSE;
641 }
642 
643 Win32FileLock::Win32FileLock( const std::string& fname ) :
644  _hFile(NULL),_filename(fname)
645 {
646  std::wstring path;
647  ToWidePath(fname, path);
648  _Init(path.c_str());
649 }
650 
651 Win32FileLock::~Win32FileLock()
652 {
653  _CleanUp();
654 }
655 
656 BOOL Win32FileLock::_Init( LPCWSTR path )
657 {
658  BOOL bRet = FALSE;
659  if(!_hFile)
660  _hFile = ::CreateFileW(path,0,0,NULL,CREATE_ALWAYS,FILE_ATTRIBUTE_NORMAL,NULL);
661  if(!_hFile || _hFile == INVALID_HANDLE_VALUE ){
662  _hFile = NULL;
663  }
664  else
665  bRet = TRUE;
666  return bRet;
667 }
668 
669 void Win32FileLock::_CleanUp()
670 {
671  ::CloseHandle(_hFile);
672  _hFile = NULL;
673 }
674 
675 BOOL Win32FileLock::isEnable()
676 {
677  return _hFile ? TRUE : FALSE;
678 }
679 
680 Win32Logger::Win32Logger(WritableFile* pFile) : _pFileProxy(pFile)
681 {
682  assert(_pFileProxy);
683 }
684 
685 Win32Logger::~Win32Logger()
686 {
687  if(_pFileProxy)
688  delete _pFileProxy;
689 }
690 
691 void Win32Logger::Logv( const char* format, va_list ap )
692 {
693  uint64_t thread_id = ::GetCurrentThreadId();
694 
695  // We try twice: the first time with a fixed-size stack allocated buffer,
696  // and the second time with a much larger dynamically allocated buffer.
697  char buffer[500];
698  for (int iter = 0; iter < 2; iter++) {
699  char* base;
700  int bufsize;
701  if (iter == 0) {
702  bufsize = sizeof(buffer);
703  base = buffer;
704  } else {
705  bufsize = 30000;
706  base = new char[bufsize];
707  }
708  char* p = base;
709  char* limit = base + bufsize;
710 
711  SYSTEMTIME st;
712  GetLocalTime(&st);
713  p += snprintf(p, limit - p,
714  "%04d/%02d/%02d-%02d:%02d:%02d.%06d %llx ",
715  int(st.wYear),
716  int(st.wMonth),
717  int(st.wDay),
718  int(st.wHour),
719  int(st.wMinute),
720  int(st.wMinute),
721  int(st.wMilliseconds),
722  static_cast<long long unsigned int>(thread_id));
723 
724  // Print the message
725  if (p < limit) {
726  va_list backup_ap;
727  va_copy(backup_ap, ap);
728  p += vsnprintf(p, limit - p, format, backup_ap);
729  va_end(backup_ap);
730  }
731 
732  // Truncate to available space if necessary
733  if (p >= limit) {
734  if (iter == 0) {
735  continue; // Try again with larger buffer
736  } else {
737  p = limit - 1;
738  }
739  }
740 
741  // Add newline if necessary
742  if (p == base || p[-1] != '\n') {
743  *p++ = '\n';
744  }
745 
746  assert(p <= limit);
747  DWORD hasWritten = 0;
748  if(_pFileProxy){
749  _pFileProxy->Append(Slice(base, p - base));
750  _pFileProxy->Flush();
751  }
752  if (base != buffer) {
753  delete[] base;
754  }
755  break;
756  }
757 }
758 
759 bool Win32Env::FileExists(const std::string& fname)
760 {
761  std::string path = fname;
762  std::wstring wpath;
763  ToWidePath(ModifyPath(path), wpath);
764  return ::PathFileExistsW(wpath.c_str()) ? true : false;
765 }
766 
767 Status Win32Env::GetChildren(const std::string& dir, std::vector<std::string>* result)
768 {
769  Status sRet;
770  ::WIN32_FIND_DATAW wfd;
771  std::string path = dir;
772  ModifyPath(path);
773  path += "\\*.*";
774  std::wstring wpath;
775  ToWidePath(path, wpath);
776 
777  ::HANDLE hFind = ::FindFirstFileW(wpath.c_str() ,&wfd);
778  if(hFind && hFind != INVALID_HANDLE_VALUE){
779  BOOL hasNext = TRUE;
780  std::string child;
781  while(hasNext){
782  ToNarrowPath(wfd.cFileName, child);
783  if(child != ".." && child != ".") {
784  result->push_back(child);
785  }
786  hasNext = ::FindNextFileW(hFind,&wfd);
787  }
788  ::FindClose(hFind);
789  }
790  else
791  sRet = Status::IOError(dir,"Could not get children.");
792  return sRet;
793 }
794 
795 void Win32Env::SleepForMicroseconds( int micros )
796 {
797  ::Sleep((micros + 999) /1000);
798 }
799 
800 
801 Status Win32Env::DeleteFile( const std::string& fname )
802 {
803  Status sRet;
804  std::string path = fname;
805  std::wstring wpath;
806  ToWidePath(ModifyPath(path), wpath);
807 
808  if(!::DeleteFileW(wpath.c_str())) {
809  sRet = Status::IOError(path, "Could not delete file.");
810  }
811  return sRet;
812 }
813 
814 Status Win32Env::GetFileSize( const std::string& fname, uint64_t* file_size )
815 {
816  Status sRet;
817  std::string path = fname;
818  std::wstring wpath;
819  ToWidePath(ModifyPath(path), wpath);
820 
821  HANDLE file = ::CreateFileW(wpath.c_str(),
822  GENERIC_READ,FILE_SHARE_READ,NULL,OPEN_EXISTING,FILE_ATTRIBUTE_NORMAL,NULL);
823  LARGE_INTEGER li;
824  if(::GetFileSizeEx(file,&li)){
825  *file_size = (uint64_t)li.QuadPart;
826  }else
827  sRet = Status::IOError(path,"Could not get the file size.");
828  CloseHandle(file);
829  return sRet;
830 }
831 
832 Status Win32Env::RenameFile( const std::string& src, const std::string& target )
833 {
834  Status sRet;
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);
841 
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.");
850  }
851  }
852  return sRet;
853 }
854 
855 Status Win32Env::LockFile( const std::string& fname, FileLock** lock )
856 {
857  Status sRet;
858  std::string path = fname;
859  ModifyPath(path);
860  Win32FileLock* _lock = new Win32FileLock(path);
861  if(!_lock->isEnable()){
862  delete _lock;
863  *lock = NULL;
864  sRet = Status::IOError(path, "Could not lock file.");
865  }
866  else
867  *lock = _lock;
868  return sRet;
869 }
870 
871 Status Win32Env::UnlockFile( FileLock* lock )
872 {
873  Status sRet;
874  delete lock;
875  return sRet;
876 }
877 
878 void Win32Env::Schedule( void (*function)(void* arg), void* arg )
879 {
880  QueueUserWorkItem(Win32::WorkItemWrapperProc,
881  new Win32::WorkItemWrapper(function,arg),
882  WT_EXECUTEDEFAULT);
883 }
884 
885 void Win32Env::StartThread( void (*function)(void* arg), void* arg )
886 {
887  ::_beginthread(function,0,arg);
888 }
889 
890 Status Win32Env::GetTestDirectory( std::string* path )
891 {
892  Status sRet;
893  WCHAR TempPath[MAX_PATH];
894  ::GetTempPathW(MAX_PATH,TempPath);
895  ToNarrowPath(TempPath, *path);
896  path->append("leveldb\\test\\");
897  ModifyPath(*path);
898  return sRet;
899 }
900 
901 uint64_t Win32Env::NowMicros()
902 {
903 #ifndef USE_VISTA_API
904 #define GetTickCount64 GetTickCount
905 #endif
906  return (uint64_t)(GetTickCount64()*1000);
907 }
908 
909 static Status CreateDirInner( const std::string& dirname )
910 {
911  Status sRet;
912  DWORD attr = ::GetFileAttributes(dirname.c_str());
913  if (attr == INVALID_FILE_ATTRIBUTES) { // doesn't exist:
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;
918  }
919  BOOL result = ::CreateDirectory(dirname.c_str(), NULL);
920  if (result == FALSE) {
921  sRet = Status::IOError(dirname, "Could not create directory.");
922  return sRet;
923  }
924  }
925  return sRet;
926 }
927 
928 Status Win32Env::CreateDir( const std::string& dirname )
929 {
930  std::string path = dirname;
931  if(path[path.length() - 1] != '\\'){
932  path += '\\';
933  }
934  ModifyPath(path);
935 
936  return CreateDirInner(path);
937 }
938 
939 Status Win32Env::DeleteDir( const std::string& dirname )
940 {
941  Status sRet;
942  std::wstring path;
943  ToWidePath(dirname, path);
944  ModifyPath(path);
945  if(!::RemoveDirectoryW( path.c_str() ) ){
946  sRet = Status::IOError(dirname, "Could not delete directory.");
947  }
948  return sRet;
949 }
950 
951 Status Win32Env::NewSequentialFile( const std::string& fname, SequentialFile** result )
952 {
953  Status sRet;
954  std::string path = fname;
955  ModifyPath(path);
956  Win32SequentialFile* pFile = new Win32SequentialFile(path);
957  if(pFile->isEnable()){
958  *result = pFile;
959  }else {
960  delete pFile;
961  sRet = Status::IOError(path, Win32::GetLastErrSz());
962  }
963  return sRet;
964 }
965 
966 Status Win32Env::NewRandomAccessFile( const std::string& fname, RandomAccessFile** result )
967 {
968  Status sRet;
969  std::string path = fname;
970  Win32RandomAccessFile* pFile = new Win32RandomAccessFile(ModifyPath(path));
971  if(!pFile->isEnable()){
972  delete pFile;
973  *result = NULL;
974  sRet = Status::IOError(path, Win32::GetLastErrSz());
975  }else
976  *result = pFile;
977  return sRet;
978 }
979 
980 Status Win32Env::NewLogger( const std::string& fname, Logger** result )
981 {
982  Status sRet;
983  std::string path = fname;
984  Win32MapFile* pMapFile = new Win32MapFile(ModifyPath(path));
985  if(!pMapFile->isEnable()){
986  delete pMapFile;
987  *result = NULL;
988  sRet = Status::IOError(path,"could not create a logger.");
989  }else
990  *result = new Win32Logger(pMapFile);
991  return sRet;
992 }
993 
994 Status Win32Env::NewWritableFile( const std::string& fname, WritableFile** result )
995 {
996  Status sRet;
997  std::string path = fname;
998  Win32MapFile* pFile = new Win32MapFile(ModifyPath(path));
999  if(!pFile->isEnable()){
1000  *result = NULL;
1001  sRet = Status::IOError(fname,Win32::GetLastErrSz());
1002  }else
1003  *result = pFile;
1004  return sRet;
1005 }
1006 
1007 Win32Env::Win32Env()
1008 {
1009 
1010 }
1011 
1012 Win32Env::~Win32Env()
1013 {
1014 
1015 }
1016 
1017 
1018 } // Win32 namespace
1019 
1020 static port::OnceType once = LEVELDB_ONCE_INIT;
1021 static Env* default_env;
1022 static void InitDefaultEnv() { default_env = new Win32::Win32Env(); }
1023 
1024 Env* Env::Default() {
1025  port::InitOnce(&once, InitDefaultEnv);
1026  return default_env;
1027 }
1028 
1029 } // namespace leveldb
1030 
1031 #endif // defined(LEVELDB_PLATFORM_WINDOWS)
std::string * value
Definition: version_set.cc:270
unsigned long long uint64_t
Definition: stdint.h:22
void InitOnce(port::OnceType *, void(*initializer)())
Definition: port_posix.cc:49
#define MAX_PATH
Definition: util.h:103
const char * base
Definition: testharness.cc:17
intptr_t OnceType
Definition: port_example.h:69
#define LEVELDB_ONCE_INIT
Definition: port_example.h:70
void * arg
Definition: env_posix.cc:716