Вы не можете выбрать более 25 тем Темы должны начинаться с буквы или цифры, могут содержать дефисы(-) и должны содержать не более 35 символов.

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901
  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>
  9. #include "leveldb/env.h"
  10. #include "port/port.h"
  11. #include "leveldb/slice.h"
  12. #include "util/logging.h"
  13. #include <shlwapi.h>
  14. #include <process.h>
  15. #include <cstring>
  16. #include <stdio.h>
  17. #include <errno.h>
  18. #include <io.h>
  19. #include <algorithm>
  20. #ifdef max
  21. #undef max
  22. #endif
  23. #ifndef va_copy
  24. #define va_copy(d,s) ((d) = (s))
  25. #endif
  26. #if defined DeleteFile
  27. #undef DeleteFile
  28. #endif
  29. //Declarations
  30. namespace leveldb
  31. {
  32. namespace Win32
  33. {
  34. #define DISALLOW_COPY_AND_ASSIGN(TypeName) \
  35. TypeName(const TypeName&); \
  36. void operator=(const TypeName&)
  37. std::string GetCurrentDir();
  38. std::wstring GetCurrentDirW();
  39. static const std::string CurrentDir = GetCurrentDir();
  40. static const std::wstring CurrentDirW = GetCurrentDirW();
  41. std::string& ModifyPath(std::string& path);
  42. std::wstring& ModifyPath(std::wstring& path);
  43. std::string GetLastErrSz();
  44. std::wstring GetLastErrSzW();
  45. size_t GetPageSize();
  46. typedef void (*ScheduleProc)(void*) ;
  47. struct WorkItemWrapper
  48. {
  49. WorkItemWrapper(ScheduleProc proc_,void* content_);
  50. ScheduleProc proc;
  51. void* pContent;
  52. };
  53. DWORD WINAPI WorkItemWrapperProc(LPVOID pContent);
  54. class Win32SequentialFile : public SequentialFile
  55. {
  56. public:
  57. friend class Win32Env;
  58. virtual ~Win32SequentialFile();
  59. virtual Status Read(size_t n, Slice* result, char* scratch);
  60. virtual Status Skip(uint64_t n);
  61. BOOL isEnable();
  62. virtual std::string GetName() const { return _filename; }
  63. private:
  64. BOOL _Init();
  65. void _CleanUp();
  66. Win32SequentialFile(const std::string& fname);
  67. std::string _filename;
  68. ::HANDLE _hFile;
  69. DISALLOW_COPY_AND_ASSIGN(Win32SequentialFile);
  70. };
  71. class Win32RandomAccessFile : public RandomAccessFile
  72. {
  73. public:
  74. friend class Win32Env;
  75. virtual ~Win32RandomAccessFile();
  76. virtual Status Read(uint64_t offset, size_t n, Slice* result,char* scratch) const;
  77. BOOL isEnable();
  78. virtual std::string GetName() const { return _filename; }
  79. private:
  80. BOOL _Init(LPCWSTR path);
  81. void _CleanUp();
  82. Win32RandomAccessFile(const std::string& fname);
  83. HANDLE _hFile;
  84. const std::string _filename;
  85. DISALLOW_COPY_AND_ASSIGN(Win32RandomAccessFile);
  86. };
  87. class Win32WritableFile : public WritableFile
  88. {
  89. public:
  90. Win32WritableFile(const std::string& fname, bool append);
  91. ~Win32WritableFile();
  92. virtual Status Append(const Slice& data);
  93. virtual Status Close();
  94. virtual Status Flush();
  95. virtual Status Sync();
  96. BOOL isEnable();
  97. virtual std::string GetName() const { return filename_; }
  98. private:
  99. std::string filename_;
  100. ::HANDLE _hFile;
  101. };
  102. class Win32FileLock : public FileLock
  103. {
  104. public:
  105. friend class Win32Env;
  106. virtual ~Win32FileLock();
  107. BOOL isEnable();
  108. private:
  109. BOOL _Init(LPCWSTR path);
  110. void _CleanUp();
  111. Win32FileLock(const std::string& fname);
  112. HANDLE _hFile;
  113. std::string _filename;
  114. DISALLOW_COPY_AND_ASSIGN(Win32FileLock);
  115. };
  116. class Win32Logger : public Logger
  117. {
  118. public:
  119. friend class Win32Env;
  120. virtual ~Win32Logger();
  121. virtual void Logv(const char* format, va_list ap);
  122. private:
  123. explicit Win32Logger(WritableFile* pFile);
  124. WritableFile* _pFileProxy;
  125. DISALLOW_COPY_AND_ASSIGN(Win32Logger);
  126. };
  127. class Win32Env : public Env
  128. {
  129. public:
  130. Win32Env();
  131. virtual ~Win32Env();
  132. virtual Status NewSequentialFile(const std::string& fname,
  133. SequentialFile** result);
  134. virtual Status NewRandomAccessFile(const std::string& fname,
  135. RandomAccessFile** result);
  136. virtual Status NewWritableFile(const std::string& fname,
  137. WritableFile** result);
  138. virtual Status NewAppendableFile(const std::string& fname,
  139. WritableFile** result);
  140. virtual bool FileExists(const std::string& fname);
  141. virtual Status GetChildren(const std::string& dir,
  142. std::vector<std::string>* result);
  143. virtual Status DeleteFile(const std::string& fname);
  144. virtual Status CreateDir(const std::string& dirname);
  145. virtual Status DeleteDir(const std::string& dirname);
  146. virtual Status GetFileSize(const std::string& fname, uint64_t* file_size);
  147. virtual Status RenameFile(const std::string& src,
  148. const std::string& target);
  149. virtual Status LockFile(const std::string& fname, FileLock** lock);
  150. virtual Status UnlockFile(FileLock* lock);
  151. virtual void Schedule(
  152. void (*function)(void* arg),
  153. void* arg);
  154. virtual void StartThread(void (*function)(void* arg), void* arg);
  155. virtual Status GetTestDirectory(std::string* path);
  156. //virtual void Logv(WritableFile* log, const char* format, va_list ap);
  157. virtual Status NewLogger(const std::string& fname, Logger** result);
  158. virtual uint64_t NowMicros();
  159. virtual void SleepForMicroseconds(int micros);
  160. };
  161. void ToWidePath(const std::string& value, std::wstring& target) {
  162. wchar_t buffer[MAX_PATH];
  163. MultiByteToWideChar(CP_ACP, 0, value.c_str(), -1, buffer, MAX_PATH);
  164. target = buffer;
  165. }
  166. void ToNarrowPath(const std::wstring& value, std::string& target) {
  167. char buffer[MAX_PATH];
  168. WideCharToMultiByte(CP_ACP, 0, value.c_str(), -1, buffer, MAX_PATH, NULL, NULL);
  169. target = buffer;
  170. }
  171. std::string GetCurrentDir()
  172. {
  173. CHAR path[MAX_PATH];
  174. ::GetModuleFileNameA(::GetModuleHandleA(NULL),path,MAX_PATH);
  175. *strrchr(path,'\\') = 0;
  176. return std::string(path);
  177. }
  178. std::wstring GetCurrentDirW()
  179. {
  180. WCHAR path[MAX_PATH];
  181. ::GetModuleFileNameW(::GetModuleHandleW(NULL),path,MAX_PATH);
  182. *wcsrchr(path,L'\\') = 0;
  183. return std::wstring(path);
  184. }
  185. std::string& ModifyPath(std::string& path)
  186. {
  187. if(path[0] == '/' || path[0] == '\\'){
  188. path = CurrentDir + path;
  189. }
  190. std::replace(path.begin(),path.end(),'/','\\');
  191. return path;
  192. }
  193. std::wstring& ModifyPath(std::wstring& path)
  194. {
  195. if(path[0] == L'/' || path[0] == L'\\'){
  196. path = CurrentDirW + path;
  197. }
  198. std::replace(path.begin(),path.end(),L'/',L'\\');
  199. return path;
  200. }
  201. std::string GetLastErrSz()
  202. {
  203. LPWSTR lpMsgBuf;
  204. FormatMessageW(
  205. FORMAT_MESSAGE_ALLOCATE_BUFFER |
  206. FORMAT_MESSAGE_FROM_SYSTEM |
  207. FORMAT_MESSAGE_IGNORE_INSERTS,
  208. NULL,
  209. GetLastError(),
  210. 0, // Default language
  211. (LPWSTR) &lpMsgBuf,
  212. 0,
  213. NULL
  214. );
  215. std::string Err;
  216. ToNarrowPath(lpMsgBuf, Err);
  217. LocalFree( lpMsgBuf );
  218. return Err;
  219. }
  220. std::wstring GetLastErrSzW()
  221. {
  222. LPVOID lpMsgBuf;
  223. FormatMessageW(
  224. FORMAT_MESSAGE_ALLOCATE_BUFFER |
  225. FORMAT_MESSAGE_FROM_SYSTEM |
  226. FORMAT_MESSAGE_IGNORE_INSERTS,
  227. NULL,
  228. GetLastError(),
  229. 0, // Default language
  230. (LPWSTR) &lpMsgBuf,
  231. 0,
  232. NULL
  233. );
  234. std::wstring Err = (LPCWSTR)lpMsgBuf;
  235. LocalFree(lpMsgBuf);
  236. return Err;
  237. }
  238. WorkItemWrapper::WorkItemWrapper( ScheduleProc proc_,void* content_ ) :
  239. proc(proc_),pContent(content_)
  240. {
  241. }
  242. DWORD WINAPI WorkItemWrapperProc(LPVOID pContent)
  243. {
  244. WorkItemWrapper* item = static_cast<WorkItemWrapper*>(pContent);
  245. ScheduleProc TempProc = item->proc;
  246. void* arg = item->pContent;
  247. delete item;
  248. TempProc(arg);
  249. return 0;
  250. }
  251. size_t GetPageSize()
  252. {
  253. SYSTEM_INFO si;
  254. GetSystemInfo(&si);
  255. return std::max(si.dwPageSize,si.dwAllocationGranularity);
  256. }
  257. const size_t g_PageSize = GetPageSize();
  258. Win32SequentialFile::Win32SequentialFile( const std::string& fname ) :
  259. _filename(fname),_hFile(NULL)
  260. {
  261. _Init();
  262. }
  263. Win32SequentialFile::~Win32SequentialFile()
  264. {
  265. _CleanUp();
  266. }
  267. Status Win32SequentialFile::Read( size_t n, Slice* result, char* scratch )
  268. {
  269. Status sRet;
  270. DWORD hasRead = 0;
  271. if(_hFile && ReadFile(_hFile,scratch,n,&hasRead,NULL) ){
  272. *result = Slice(scratch,hasRead);
  273. } else {
  274. sRet = Status::IOError(_filename, Win32::GetLastErrSz() );
  275. }
  276. return sRet;
  277. }
  278. Status Win32SequentialFile::Skip( uint64_t n )
  279. {
  280. Status sRet;
  281. LARGE_INTEGER Move,NowPointer;
  282. Move.QuadPart = n;
  283. if(!SetFilePointerEx(_hFile,Move,&NowPointer,FILE_CURRENT)){
  284. sRet = Status::IOError(_filename,Win32::GetLastErrSz());
  285. }
  286. return sRet;
  287. }
  288. BOOL Win32SequentialFile::isEnable()
  289. {
  290. return _hFile ? TRUE : FALSE;
  291. }
  292. BOOL Win32SequentialFile::_Init()
  293. {
  294. std::wstring path;
  295. ToWidePath(_filename, path);
  296. _hFile = CreateFileW(path.c_str(),
  297. GENERIC_READ,
  298. FILE_SHARE_READ | FILE_SHARE_WRITE,
  299. NULL,
  300. OPEN_EXISTING,
  301. FILE_ATTRIBUTE_NORMAL | FILE_FLAG_SEQUENTIAL_SCAN,
  302. NULL);
  303. if (_hFile == INVALID_HANDLE_VALUE)
  304. _hFile = NULL;
  305. return _hFile ? TRUE : FALSE;
  306. }
  307. void Win32SequentialFile::_CleanUp()
  308. {
  309. if(_hFile){
  310. CloseHandle(_hFile);
  311. _hFile = NULL;
  312. }
  313. }
  314. Win32RandomAccessFile::Win32RandomAccessFile( const std::string& fname ) :
  315. _filename(fname),_hFile(NULL)
  316. {
  317. std::wstring path;
  318. ToWidePath(fname, path);
  319. _Init( path.c_str() );
  320. }
  321. Win32RandomAccessFile::~Win32RandomAccessFile()
  322. {
  323. _CleanUp();
  324. }
  325. Status Win32RandomAccessFile::Read(uint64_t offset,size_t n,Slice* result,char* scratch) const
  326. {
  327. Status sRet;
  328. OVERLAPPED ol = {0};
  329. ZeroMemory(&ol,sizeof(ol));
  330. ol.Offset = (DWORD)offset;
  331. ol.OffsetHigh = (DWORD)(offset >> 32);
  332. DWORD hasRead = 0;
  333. if(!ReadFile(_hFile,scratch,n,&hasRead,&ol))
  334. sRet = Status::IOError(_filename,Win32::GetLastErrSz());
  335. else
  336. *result = Slice(scratch,hasRead);
  337. return sRet;
  338. }
  339. BOOL Win32RandomAccessFile::_Init( LPCWSTR path )
  340. {
  341. BOOL bRet = FALSE;
  342. if(!_hFile)
  343. _hFile = ::CreateFileW(path,GENERIC_READ,FILE_SHARE_READ|FILE_SHARE_WRITE,NULL,OPEN_EXISTING,
  344. FILE_ATTRIBUTE_NORMAL | FILE_FLAG_RANDOM_ACCESS,NULL);
  345. if(!_hFile || _hFile == INVALID_HANDLE_VALUE )
  346. _hFile = NULL;
  347. else
  348. bRet = TRUE;
  349. return bRet;
  350. }
  351. BOOL Win32RandomAccessFile::isEnable()
  352. {
  353. return _hFile ? TRUE : FALSE;
  354. }
  355. void Win32RandomAccessFile::_CleanUp()
  356. {
  357. if(_hFile){
  358. ::CloseHandle(_hFile);
  359. _hFile = NULL;
  360. }
  361. }
  362. Win32WritableFile::Win32WritableFile(const std::string& fname, bool append)
  363. : filename_(fname)
  364. {
  365. std::wstring path;
  366. ToWidePath(fname, path);
  367. // NewAppendableFile: append to an existing file, or create a new one
  368. // if none exists - this is OPEN_ALWAYS behavior, with
  369. // FILE_APPEND_DATA to avoid having to manually position the file
  370. // pointer at the end of the file.
  371. // NewWritableFile: create a new file, delete if it exists - this is
  372. // CREATE_ALWAYS behavior. This file is used for writing only so
  373. // use GENERIC_WRITE.
  374. _hFile = CreateFileW(path.c_str(),
  375. append ? FILE_APPEND_DATA : GENERIC_WRITE,
  376. FILE_SHARE_READ|FILE_SHARE_DELETE|FILE_SHARE_WRITE,
  377. NULL,
  378. append ? OPEN_ALWAYS : CREATE_ALWAYS,
  379. FILE_ATTRIBUTE_NORMAL,
  380. NULL);
  381. // CreateFileW returns INVALID_HANDLE_VALUE in case of error, always check isEnable() before use
  382. }
  383. Win32WritableFile::~Win32WritableFile()
  384. {
  385. if (_hFile != INVALID_HANDLE_VALUE)
  386. Close();
  387. }
  388. Status Win32WritableFile::Append(const Slice& data)
  389. {
  390. DWORD r = 0;
  391. if (!WriteFile(_hFile, data.data(), data.size(), &r, NULL) || r != data.size()) {
  392. return Status::IOError("Win32WritableFile.Append::WriteFile: "+filename_, Win32::GetLastErrSz());
  393. }
  394. return Status::OK();
  395. }
  396. Status Win32WritableFile::Close()
  397. {
  398. if (!CloseHandle(_hFile)) {
  399. return Status::IOError("Win32WritableFile.Close::CloseHandle: "+filename_, Win32::GetLastErrSz());
  400. }
  401. _hFile = INVALID_HANDLE_VALUE;
  402. return Status::OK();
  403. }
  404. Status Win32WritableFile::Flush()
  405. {
  406. // Nothing to do here, there are no application-side buffers
  407. return Status::OK();
  408. }
  409. Status Win32WritableFile::Sync()
  410. {
  411. if (!FlushFileBuffers(_hFile)) {
  412. return Status::IOError("Win32WritableFile.Sync::FlushFileBuffers "+filename_, Win32::GetLastErrSz());
  413. }
  414. return Status::OK();
  415. }
  416. BOOL Win32WritableFile::isEnable()
  417. {
  418. return _hFile != INVALID_HANDLE_VALUE;
  419. }
  420. Win32FileLock::Win32FileLock( const std::string& fname ) :
  421. _hFile(NULL),_filename(fname)
  422. {
  423. std::wstring path;
  424. ToWidePath(fname, path);
  425. _Init(path.c_str());
  426. }
  427. Win32FileLock::~Win32FileLock()
  428. {
  429. _CleanUp();
  430. }
  431. BOOL Win32FileLock::_Init( LPCWSTR path )
  432. {
  433. BOOL bRet = FALSE;
  434. if(!_hFile)
  435. _hFile = ::CreateFileW(path,0,0,NULL,CREATE_ALWAYS,FILE_ATTRIBUTE_NORMAL,NULL);
  436. if(!_hFile || _hFile == INVALID_HANDLE_VALUE ){
  437. _hFile = NULL;
  438. }
  439. else
  440. bRet = TRUE;
  441. return bRet;
  442. }
  443. void Win32FileLock::_CleanUp()
  444. {
  445. ::CloseHandle(_hFile);
  446. _hFile = NULL;
  447. }
  448. BOOL Win32FileLock::isEnable()
  449. {
  450. return _hFile ? TRUE : FALSE;
  451. }
  452. Win32Logger::Win32Logger(WritableFile* pFile) : _pFileProxy(pFile)
  453. {
  454. assert(_pFileProxy);
  455. }
  456. Win32Logger::~Win32Logger()
  457. {
  458. if(_pFileProxy)
  459. delete _pFileProxy;
  460. }
  461. void Win32Logger::Logv( const char* format, va_list ap )
  462. {
  463. uint64_t thread_id = ::GetCurrentThreadId();
  464. // We try twice: the first time with a fixed-size stack allocated buffer,
  465. // and the second time with a much larger dynamically allocated buffer.
  466. char buffer[500];
  467. for (int iter = 0; iter < 2; iter++) {
  468. char* base;
  469. int bufsize;
  470. if (iter == 0) {
  471. bufsize = sizeof(buffer);
  472. base = buffer;
  473. } else {
  474. bufsize = 30000;
  475. base = new char[bufsize];
  476. }
  477. char* p = base;
  478. char* limit = base + bufsize;
  479. SYSTEMTIME st;
  480. GetLocalTime(&st);
  481. p += snprintf(p, limit - p,
  482. "%04d/%02d/%02d-%02d:%02d:%02d.%06d %llx ",
  483. int(st.wYear),
  484. int(st.wMonth),
  485. int(st.wDay),
  486. int(st.wHour),
  487. int(st.wMinute),
  488. int(st.wMinute),
  489. int(st.wMilliseconds),
  490. static_cast<long long unsigned int>(thread_id));
  491. // Print the message
  492. if (p < limit) {
  493. va_list backup_ap;
  494. va_copy(backup_ap, ap);
  495. p += vsnprintf(p, limit - p, format, backup_ap);
  496. va_end(backup_ap);
  497. }
  498. // Truncate to available space if necessary
  499. if (p >= limit) {
  500. if (iter == 0) {
  501. continue; // Try again with larger buffer
  502. } else {
  503. p = limit - 1;
  504. }
  505. }
  506. // Add newline if necessary
  507. if (p == base || p[-1] != '\n') {
  508. *p++ = '\n';
  509. }
  510. assert(p <= limit);
  511. DWORD hasWritten = 0;
  512. if(_pFileProxy){
  513. _pFileProxy->Append(Slice(base, p - base));
  514. _pFileProxy->Flush();
  515. }
  516. if (base != buffer) {
  517. delete[] base;
  518. }
  519. break;
  520. }
  521. }
  522. bool Win32Env::FileExists(const std::string& fname)
  523. {
  524. std::string path = fname;
  525. std::wstring wpath;
  526. ToWidePath(ModifyPath(path), wpath);
  527. return ::PathFileExistsW(wpath.c_str()) ? true : false;
  528. }
  529. Status Win32Env::GetChildren(const std::string& dir, std::vector<std::string>* result)
  530. {
  531. Status sRet;
  532. ::WIN32_FIND_DATAW wfd;
  533. std::string path = dir;
  534. ModifyPath(path);
  535. path += "\\*.*";
  536. std::wstring wpath;
  537. ToWidePath(path, wpath);
  538. ::HANDLE hFind = ::FindFirstFileW(wpath.c_str() ,&wfd);
  539. if(hFind && hFind != INVALID_HANDLE_VALUE){
  540. BOOL hasNext = TRUE;
  541. std::string child;
  542. while(hasNext){
  543. ToNarrowPath(wfd.cFileName, child);
  544. if(child != ".." && child != ".") {
  545. result->push_back(child);
  546. }
  547. hasNext = ::FindNextFileW(hFind,&wfd);
  548. }
  549. ::FindClose(hFind);
  550. }
  551. else
  552. sRet = Status::IOError(dir,"Could not get children.");
  553. return sRet;
  554. }
  555. void Win32Env::SleepForMicroseconds( int micros )
  556. {
  557. ::Sleep((micros + 999) /1000);
  558. }
  559. Status Win32Env::DeleteFile( const std::string& fname )
  560. {
  561. Status sRet;
  562. std::string path = fname;
  563. std::wstring wpath;
  564. ToWidePath(ModifyPath(path), wpath);
  565. if(!::DeleteFileW(wpath.c_str())) {
  566. sRet = Status::IOError(path, "Could not delete file.");
  567. }
  568. return sRet;
  569. }
  570. Status Win32Env::GetFileSize( const std::string& fname, uint64_t* file_size )
  571. {
  572. Status sRet;
  573. std::string path = fname;
  574. std::wstring wpath;
  575. ToWidePath(ModifyPath(path), wpath);
  576. HANDLE file = ::CreateFileW(wpath.c_str(),
  577. GENERIC_READ,FILE_SHARE_READ|FILE_SHARE_WRITE,NULL,OPEN_EXISTING,FILE_ATTRIBUTE_NORMAL,NULL);
  578. LARGE_INTEGER li;
  579. if(::GetFileSizeEx(file,&li)){
  580. *file_size = (uint64_t)li.QuadPart;
  581. }else
  582. sRet = Status::IOError(path,"Could not get the file size.");
  583. CloseHandle(file);
  584. return sRet;
  585. }
  586. Status Win32Env::RenameFile( const std::string& src, const std::string& target )
  587. {
  588. Status sRet;
  589. std::string src_path = src;
  590. std::wstring wsrc_path;
  591. ToWidePath(ModifyPath(src_path), wsrc_path);
  592. std::string target_path = target;
  593. std::wstring wtarget_path;
  594. ToWidePath(ModifyPath(target_path), wtarget_path);
  595. if(!MoveFileW(wsrc_path.c_str(), wtarget_path.c_str() ) ){
  596. DWORD err = GetLastError();
  597. if(err == 0x000000b7){
  598. if(!::DeleteFileW(wtarget_path.c_str() ) )
  599. sRet = Status::IOError(src, "Could not rename file.");
  600. else if(!::MoveFileW(wsrc_path.c_str(),
  601. wtarget_path.c_str() ) )
  602. sRet = Status::IOError(src, "Could not rename file.");
  603. }
  604. }
  605. return sRet;
  606. }
  607. Status Win32Env::LockFile( const std::string& fname, FileLock** lock )
  608. {
  609. Status sRet;
  610. std::string path = fname;
  611. ModifyPath(path);
  612. Win32FileLock* _lock = new Win32FileLock(path);
  613. if(!_lock->isEnable()){
  614. delete _lock;
  615. *lock = NULL;
  616. sRet = Status::IOError(path, "Could not lock file.");
  617. }
  618. else
  619. *lock = _lock;
  620. return sRet;
  621. }
  622. Status Win32Env::UnlockFile( FileLock* lock )
  623. {
  624. Status sRet;
  625. delete lock;
  626. return sRet;
  627. }
  628. void Win32Env::Schedule( void (*function)(void* arg), void* arg )
  629. {
  630. QueueUserWorkItem(Win32::WorkItemWrapperProc,
  631. new Win32::WorkItemWrapper(function,arg),
  632. WT_EXECUTEDEFAULT);
  633. }
  634. void Win32Env::StartThread( void (*function)(void* arg), void* arg )
  635. {
  636. ::_beginthread(function,0,arg);
  637. }
  638. Status Win32Env::GetTestDirectory( std::string* path )
  639. {
  640. Status sRet;
  641. WCHAR TempPath[MAX_PATH];
  642. ::GetTempPathW(MAX_PATH,TempPath);
  643. ToNarrowPath(TempPath, *path);
  644. path->append("leveldb\\test\\");
  645. ModifyPath(*path);
  646. return sRet;
  647. }
  648. uint64_t Win32Env::NowMicros()
  649. {
  650. #ifndef USE_VISTA_API
  651. #define GetTickCount64 GetTickCount
  652. #endif
  653. return (uint64_t)(GetTickCount64()*1000);
  654. }
  655. static Status CreateDirInner( const std::string& dirname )
  656. {
  657. Status sRet;
  658. DWORD attr = ::GetFileAttributes(dirname.c_str());
  659. if (attr == INVALID_FILE_ATTRIBUTES) { // doesn't exist:
  660. std::size_t slash = dirname.find_last_of("\\");
  661. if (slash != std::string::npos){
  662. sRet = CreateDirInner(dirname.substr(0, slash));
  663. if (!sRet.ok()) return sRet;
  664. }
  665. BOOL result = ::CreateDirectory(dirname.c_str(), NULL);
  666. if (result == FALSE) {
  667. sRet = Status::IOError(dirname, "Could not create directory.");
  668. return sRet;
  669. }
  670. }
  671. return sRet;
  672. }
  673. Status Win32Env::CreateDir( const std::string& dirname )
  674. {
  675. std::string path = dirname;
  676. if(path[path.length() - 1] != '\\'){
  677. path += '\\';
  678. }
  679. ModifyPath(path);
  680. return CreateDirInner(path);
  681. }
  682. Status Win32Env::DeleteDir( const std::string& dirname )
  683. {
  684. Status sRet;
  685. std::wstring path;
  686. ToWidePath(dirname, path);
  687. ModifyPath(path);
  688. if(!::RemoveDirectoryW( path.c_str() ) ){
  689. sRet = Status::IOError(dirname, "Could not delete directory.");
  690. }
  691. return sRet;
  692. }
  693. Status Win32Env::NewSequentialFile( const std::string& fname, SequentialFile** result )
  694. {
  695. Status sRet;
  696. std::string path = fname;
  697. ModifyPath(path);
  698. Win32SequentialFile* pFile = new Win32SequentialFile(path);
  699. if(pFile->isEnable()){
  700. *result = pFile;
  701. }else {
  702. delete pFile;
  703. sRet = Status::IOError(path, Win32::GetLastErrSz());
  704. }
  705. return sRet;
  706. }
  707. Status Win32Env::NewRandomAccessFile( const std::string& fname, RandomAccessFile** result )
  708. {
  709. Status sRet;
  710. std::string path = fname;
  711. Win32RandomAccessFile* pFile = new Win32RandomAccessFile(ModifyPath(path));
  712. if(!pFile->isEnable()){
  713. delete pFile;
  714. *result = NULL;
  715. sRet = Status::IOError(path, Win32::GetLastErrSz());
  716. }else
  717. *result = pFile;
  718. return sRet;
  719. }
  720. Status Win32Env::NewLogger( const std::string& fname, Logger** result )
  721. {
  722. Status sRet;
  723. std::string path = fname;
  724. // Logs are opened with write semantics, not with append semantics
  725. // (see PosixEnv::NewLogger)
  726. Win32WritableFile* pMapFile = new Win32WritableFile(ModifyPath(path), false);
  727. if(!pMapFile->isEnable()){
  728. delete pMapFile;
  729. *result = NULL;
  730. sRet = Status::IOError(path,"could not create a logger.");
  731. }else
  732. *result = new Win32Logger(pMapFile);
  733. return sRet;
  734. }
  735. Status Win32Env::NewWritableFile( const std::string& fname, WritableFile** result )
  736. {
  737. Status sRet;
  738. std::string path = fname;
  739. Win32WritableFile* pFile = new Win32WritableFile(ModifyPath(path), false);
  740. if(!pFile->isEnable()){
  741. *result = NULL;
  742. sRet = Status::IOError(fname,Win32::GetLastErrSz());
  743. }else
  744. *result = pFile;
  745. return sRet;
  746. }
  747. Status Win32Env::NewAppendableFile( const std::string& fname, WritableFile** result )
  748. {
  749. Status sRet;
  750. std::string path = fname;
  751. Win32WritableFile* pFile = new Win32WritableFile(ModifyPath(path), true);
  752. if(!pFile->isEnable()){
  753. *result = NULL;
  754. sRet = Status::IOError(fname,Win32::GetLastErrSz());
  755. }else
  756. *result = pFile;
  757. return sRet;
  758. }
  759. Win32Env::Win32Env()
  760. {
  761. }
  762. Win32Env::~Win32Env()
  763. {
  764. }
  765. } // Win32 namespace
  766. static port::OnceType once = LEVELDB_ONCE_INIT;
  767. static Env* default_env;
  768. static void InitDefaultEnv() { default_env = new Win32::Win32Env(); }
  769. Env* Env::Default() {
  770. port::InitOnce(&once, InitDefaultEnv);
  771. return default_env;
  772. }
  773. } // namespace leveldb
  774. #endif // defined(LEVELDB_PLATFORM_WINDOWS)