env_chromium.cc revision 5821806d5e7f356e8fa4b058a389a808ea183019
15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright (c) 2011 The LevelDB Authors. All rights reserved. 25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be 35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file. See the AUTHORS file for names of contributors. 45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <deque> 65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <errno.h> 75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <stdio.h> 85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/at_exit.h" 95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/file_path.h" 105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/file_util.h" 115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/lazy_instance.h" 125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/memory/ref_counted.h" 135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/message_loop.h" 145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/platform_file.h" 155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/process_util.h" 165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/stringprintf.h" 175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/synchronization/lock.h" 185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/sys_info.h" 195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/threading/platform_thread.h" 205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/threading/thread.h" 215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/utf_string_conversions.h" 225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chromium_logger.h" 235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "leveldb/env.h" 245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "leveldb/slice.h" 255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "port/port.h" 265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "util/logging.h" 275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if defined(OS_WIN) 295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <io.h> 305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/win/win_util.h" 315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif 325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace { 345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if defined(OS_MACOSX) || defined(OS_WIN) || defined(OS_ANDROID) || \ 365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) defined(OS_OPENBSD) 375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// The following are glibc-specific 385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)size_t fread_unlocked(void *ptr, size_t size, size_t n, FILE *file) { 405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return fread(ptr, size, n, file); 415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)size_t fwrite_unlocked(const void *ptr, size_t size, size_t n, FILE *file) { 445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return fwrite(ptr, size, n, file); 455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int fflush_unlocked(FILE *file) { 485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return fflush(file); 495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if !defined(OS_ANDROID) 525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int fdatasync(int fildes) { 535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if defined(OS_WIN) 545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return _commit(fildes); 555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#else 565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return fsync(fildes); 575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif 585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif 605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif 625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Wide-char safe fopen wrapper. 645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)FILE* fopen_internal(const char* fname, const char* mode) { 655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if defined(OS_WIN) 665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return _wfopen(UTF8ToUTF16(fname).c_str(), ASCIIToUTF16(mode).c_str()); 675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#else 685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return fopen(fname, mode); 695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif 705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} // namespace 735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace leveldb { 755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace { 775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class Thread; 795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static const ::FilePath::CharType kLevelDBTestDirectoryPrefix[] 815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) = FILE_PATH_LITERAL("leveldb-test-"); 825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)::FilePath CreateFilePath(const std::string& file_path) { 845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if defined(OS_WIN) 855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return FilePath(UTF8ToUTF16(file_path)); 865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#else 875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return FilePath(file_path); 885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif 895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)std::string FilePathToString(const ::FilePath& file_path) { 925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if defined(OS_WIN) 935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return UTF16ToUTF8(file_path.value()); 945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#else 955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return file_path.value(); 965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif 975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// TODO(jorlow): This should be moved into Chromium's base. 1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const char* PlatformFileErrorString(const ::base::PlatformFileError& error) { 1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) switch (error) { 1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case ::base::PLATFORM_FILE_ERROR_FAILED: 1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return "Opening file failed."; 1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case ::base::PLATFORM_FILE_ERROR_IN_USE: 1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return "File currently in use."; 1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case ::base::PLATFORM_FILE_ERROR_EXISTS: 1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return "File already exists."; 1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case ::base::PLATFORM_FILE_ERROR_NOT_FOUND: 1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return "File not found."; 1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case ::base::PLATFORM_FILE_ERROR_ACCESS_DENIED: 1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return "Access denied."; 1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case ::base::PLATFORM_FILE_ERROR_TOO_MANY_OPENED: 1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return "Too many files open."; 1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case ::base::PLATFORM_FILE_ERROR_NO_MEMORY: 1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return "Out of memory."; 1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case ::base::PLATFORM_FILE_ERROR_NO_SPACE: 1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return "No space left on drive."; 1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case ::base::PLATFORM_FILE_ERROR_NOT_A_DIRECTORY: 1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return "Not a directory."; 1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case ::base::PLATFORM_FILE_ERROR_INVALID_OPERATION: 1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return "Invalid operation."; 1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case ::base::PLATFORM_FILE_ERROR_SECURITY: 1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return "Security error."; 1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case ::base::PLATFORM_FILE_ERROR_ABORT: 1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return "File operation aborted."; 1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case ::base::PLATFORM_FILE_ERROR_NOT_A_FILE: 1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return "The supplied path was not a file."; 1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case ::base::PLATFORM_FILE_ERROR_NOT_EMPTY: 1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return "The file was not empty."; 1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case ::base::PLATFORM_FILE_ERROR_INVALID_URL: 1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return "Invalid URL."; 1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case ::base::PLATFORM_FILE_OK: 1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return "OK."; 1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) NOTIMPLEMENTED(); 1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return "Unknown error."; 1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class ChromiumSequentialFile: public SequentialFile { 1405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private: 1415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::string filename_; 1425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) FILE* file_; 1435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public: 1455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ChromiumSequentialFile(const std::string& fname, FILE* f) 1465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) : filename_(fname), file_(f) { } 1475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) virtual ~ChromiumSequentialFile() { fclose(file_); } 1485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) virtual Status Read(size_t n, Slice* result, char* scratch) { 1505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Status s; 1515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) size_t r = fread_unlocked(scratch, 1, n, file_); 1525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *result = Slice(scratch, r); 1535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (r < n) { 1545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (feof(file_)) { 1555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // We leave status as ok if we hit the end of the file 1565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 1575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // A partial read with an error: return a non-ok status 1585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) s = Status::IOError(filename_, strerror(errno)); 1595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return s; 1625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) virtual Status Skip(uint64_t n) { 1655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (fseek(file_, n, SEEK_CUR)) { 1665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return Status::IOError(filename_, strerror(errno)); 1675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return Status::OK(); 1695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}; 1715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class ChromiumRandomAccessFile: public RandomAccessFile { 1735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private: 1745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::string filename_; 1755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ::base::PlatformFile file_; 1765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public: 1785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ChromiumRandomAccessFile(const std::string& fname, ::base::PlatformFile file) 1795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) : filename_(fname), file_(file) { } 1805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) virtual ~ChromiumRandomAccessFile() { ::base::ClosePlatformFile(file_); } 1815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) virtual Status Read(uint64_t offset, size_t n, Slice* result, 1835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) char* scratch) const { 1845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Status s; 1855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int r = ::base::ReadPlatformFile(file_, offset, scratch, n); 1865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *result = Slice(scratch, (r < 0) ? 0 : r); 1875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (r < 0) { 1885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // An error: return a non-ok status 1895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) s = Status::IOError(filename_, "Could not perform read"); 1905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return s; 1925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}; 1945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class ChromiumWritableFile : public WritableFile { 1965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private: 1975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::string filename_; 1985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) FILE* file_; 1995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public: 2015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ChromiumWritableFile(const std::string& fname, FILE* f) 2025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) : filename_(fname), file_(f) { } 2035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ~ChromiumWritableFile() { 2055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (file_ != NULL) { 2065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Ignoring any potential errors 2075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) fclose(file_); 2085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) virtual Status Append(const Slice& data) { 2125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) size_t r = fwrite_unlocked(data.data(), 1, data.size(), file_); 2135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Status result; 2145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (r != data.size()) { 2155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) result = Status::IOError(filename_, strerror(errno)); 2165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return result; 2185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) virtual Status Close() { 2215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Status result; 2225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (fclose(file_) != 0) { 2235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) result = Status::IOError(filename_, strerror(errno)); 2245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) file_ = NULL; 2265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return result; 2275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) virtual Status Flush() { 2305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Status result; 2315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (fflush_unlocked(file_) != 0) { 2325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) result = Status::IOError(filename_, strerror(errno)); 2335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return result; 2355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) virtual Status Sync() { 2385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Status result; 2395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if ((fflush_unlocked(file_) != 0) || 2405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) (fdatasync(fileno(file_)) != 0)) { 2415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) result = Status::IOError(filename_, strerror(errno)); 2425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return result; 2445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}; 2465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class ChromiumFileLock : public FileLock { 2485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public: 2495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ::base::PlatformFile file_; 2505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}; 2515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class ChromiumEnv : public Env { 2535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public: 2545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ChromiumEnv(); 2555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) virtual ~ChromiumEnv() { 2565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) NOTREACHED(); 2575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) virtual Status NewSequentialFile(const std::string& fname, 2605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SequentialFile** result) { 2615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) FILE* f = fopen_internal(fname.c_str(), "rb"); 2625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (f == NULL) { 2635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *result = NULL; 2645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return Status::IOError(fname, strerror(errno)); 2655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 2665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *result = new ChromiumSequentialFile(fname, f); 2675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return Status::OK(); 2685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) virtual Status NewRandomAccessFile(const std::string& fname, 2725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) RandomAccessFile** result) { 2735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int flags = ::base::PLATFORM_FILE_READ | ::base::PLATFORM_FILE_OPEN; 2745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool created; 2755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ::base::PlatformFileError error_code; 2765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ::base::PlatformFile file = ::base::CreatePlatformFile( 2775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CreateFilePath(fname), flags, &created, &error_code); 2785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (error_code != ::base::PLATFORM_FILE_OK) { 2795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *result = NULL; 2805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return Status::IOError(fname, PlatformFileErrorString(error_code)); 2815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *result = new ChromiumRandomAccessFile(fname, file); 2835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return Status::OK(); 2845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) virtual Status NewWritableFile(const std::string& fname, 2875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) WritableFile** result) { 2885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *result = NULL; 2895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) FILE* f = fopen_internal(fname.c_str(), "wb"); 2905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (f == NULL) { 2915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return Status::IOError(fname, strerror(errno)); 2925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 2935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *result = new ChromiumWritableFile(fname, f); 2945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return Status::OK(); 2955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) virtual bool FileExists(const std::string& fname) { 2995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return ::file_util::PathExists(CreateFilePath(fname)); 3005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) virtual Status GetChildren(const std::string& dir, 3035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::vector<std::string>* result) { 3045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) result->clear(); 3055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ::file_util::FileEnumerator iter( 3065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CreateFilePath(dir), false, ::file_util::FileEnumerator::FILES); 3075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ::FilePath current = iter.Next(); 3085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) while (!current.empty()) { 3095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) result->push_back(FilePathToString(current.BaseName())); 3105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) current = iter.Next(); 3115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // TODO(jorlow): Unfortunately, the FileEnumerator swallows errors, so 3135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // we'll always return OK. Maybe manually check for error 3145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // conditions like the file not existing? 3155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return Status::OK(); 3165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) virtual Status DeleteFile(const std::string& fname) { 3195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Status result; 3205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // TODO(jorlow): Should we assert this is a file? 3215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!::file_util::Delete(CreateFilePath(fname), false)) { 3225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) result = Status::IOError(fname, "Could not delete file."); 3235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return result; 3255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) }; 3265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) virtual Status CreateDir(const std::string& name) { 3285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Status result; 3295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!::file_util::CreateDirectory(CreateFilePath(name))) { 3305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) result = Status::IOError(name, "Could not create directory."); 3315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return result; 3335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) }; 3345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) virtual Status DeleteDir(const std::string& name) { 3365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Status result; 3375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // TODO(jorlow): Should we assert this is a directory? 3385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!::file_util::Delete(CreateFilePath(name), false)) { 3395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) result = Status::IOError(name, "Could not delete directory."); 3405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return result; 3425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) }; 3435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) virtual Status GetFileSize(const std::string& fname, uint64_t* size) { 3455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Status s; 3465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int64_t signed_size; 3475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!::file_util::GetFileSize(CreateFilePath(fname), &signed_size)) { 3485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *size = 0; 3495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) s = Status::IOError(fname, "Could not determine file size."); 3505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 3515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *size = static_cast<uint64_t>(signed_size); 3525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return s; 3545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) virtual Status RenameFile(const std::string& src, const std::string& dst) { 3575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Status result; 3585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!::file_util::ReplaceFile(CreateFilePath(src), CreateFilePath(dst))) { 3595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) result = Status::IOError(src, "Could not rename file."); 3605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return result; 3625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) virtual Status LockFile(const std::string& fname, FileLock** lock) { 3655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *lock = NULL; 3665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Status result; 3675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int flags = ::base::PLATFORM_FILE_OPEN_ALWAYS | 3685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ::base::PLATFORM_FILE_READ | 3695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ::base::PLATFORM_FILE_WRITE | 3705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ::base::PLATFORM_FILE_EXCLUSIVE_READ | 3715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ::base::PLATFORM_FILE_EXCLUSIVE_WRITE; 3725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool created; 3735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ::base::PlatformFileError error_code; 3745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ::base::PlatformFile file = ::base::CreatePlatformFile( 3755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CreateFilePath(fname), flags, &created, &error_code); 3765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (error_code != ::base::PLATFORM_FILE_OK) { 3775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) result = Status::IOError(fname, PlatformFileErrorString(error_code)); 3785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 3795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ChromiumFileLock* my_lock = new ChromiumFileLock; 3805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) my_lock->file_ = file; 3815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *lock = my_lock; 3825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return result; 3845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) virtual Status UnlockFile(FileLock* lock) { 3875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ChromiumFileLock* my_lock = reinterpret_cast<ChromiumFileLock*>(lock); 3885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Status result; 3895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!::base::ClosePlatformFile(my_lock->file_)) { 3905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) result = Status::IOError("Could not close lock file."); 3915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) delete my_lock; 3935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return result; 3945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) virtual void Schedule(void (*function)(void*), void* arg); 3975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) virtual void StartThread(void (*function)(void* arg), void* arg); 3995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) virtual std::string UserIdentifier() { 4015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if defined(OS_WIN) 4025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::wstring user_sid; 4035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool ret = ::base::win::GetUserSidString(&user_sid); 4045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(ret); 4055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return UTF16ToUTF8(user_sid); 4065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#else 4075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) char buf[100]; 4085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) snprintf(buf, sizeof(buf), "%d", int(geteuid())); 4095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return buf; 4105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif 4115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 4125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) virtual Status GetTestDirectory(std::string* path) { 4145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) mu_.Acquire(); 4155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (test_directory_.empty()) { 4165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!::file_util::CreateNewTempDirectory(kLevelDBTestDirectoryPrefix, 4175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) &test_directory_)) { 4185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) mu_.Release(); 4195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return Status::IOError("Could not create temp directory."); 4205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 4215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 4225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *path = FilePathToString(test_directory_); 4235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) mu_.Release(); 4245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return Status::OK(); 4255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 4265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) virtual Status NewLogger(const std::string& fname, Logger** result) { 4285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) FILE* f = fopen_internal(fname.c_str(), "w"); 4295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (f == NULL) { 4305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *result = NULL; 4315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return Status::IOError(fname, strerror(errno)); 4325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 4335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *result = new ChromiumLogger(f); 4345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return Status::OK(); 4355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 4365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 4375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) virtual uint64_t NowMicros() { 4395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return ::base::TimeTicks::Now().ToInternalValue(); 4405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 4415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) virtual void SleepForMicroseconds(int micros) { 4435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Round up to the next millisecond. 4445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ::base::PlatformThread::Sleep(::base::TimeDelta::FromMicroseconds(micros)); 4455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 4465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private: 4485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // BGThread() is the body of the background thread 4495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) void BGThread(); 4505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) static void BGThreadWrapper(void* arg) { 4515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) reinterpret_cast<ChromiumEnv*>(arg)->BGThread(); 4525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 4535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) FilePath test_directory_; 4555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) size_t page_size_; 4575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ::base::Lock mu_; 4585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ::base::ConditionVariable bgsignal_; 4595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool started_bgthread_; 4605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Entry per Schedule() call 4625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) struct BGItem { void* arg; void (*function)(void*); }; 4635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) typedef std::deque<BGItem> BGQueue; 4645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) BGQueue queue_; 4655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}; 4665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)ChromiumEnv::ChromiumEnv() 4685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) : page_size_(::base::SysInfo::VMAllocationGranularity()), 4695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bgsignal_(&mu_), 4705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) started_bgthread_(false) { 4715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if defined(OS_MACOSX) 4725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ::base::EnableTerminationOnHeapCorruption(); 4735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ::base::EnableTerminationOnOutOfMemory(); 4745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif // OS_MACOSX 4755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 4765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class Thread : public ::base::PlatformThread::Delegate { 4785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public: 4795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Thread(void (*function)(void* arg), void* arg) 4805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) : function_(function), arg_(arg) { 4815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ::base::PlatformThreadHandle handle; 4825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool success = ::base::PlatformThread::Create(0, this, &handle); 4835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(success); 4845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 4855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) virtual ~Thread() {} 4865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) virtual void ThreadMain() { 4875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) (*function_)(arg_); 4885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) delete this; 4895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 4905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private: 4925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) void (*function_)(void* arg); 4935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) void* arg_; 4945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}; 4955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void ChromiumEnv::Schedule(void (*function)(void*), void* arg) { 4975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) mu_.Acquire(); 4985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Start background thread if necessary 5005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!started_bgthread_) { 5015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) started_bgthread_ = true; 5025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) StartThread(&ChromiumEnv::BGThreadWrapper, this); 5035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 5045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // If the queue is currently empty, the background thread may currently be 5065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // waiting. 5075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (queue_.empty()) { 5085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bgsignal_.Signal(); 5095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 5105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Add to priority queue 5125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) queue_.push_back(BGItem()); 5135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) queue_.back().function = function; 5145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) queue_.back().arg = arg; 5155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) mu_.Release(); 5175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 5185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void ChromiumEnv::BGThread() { 5205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) while (true) { 5215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Wait until there is an item that is ready to run 5225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) mu_.Acquire(); 5235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) while (queue_.empty()) { 5245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bgsignal_.Wait(); 5255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 5265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) void (*function)(void*) = queue_.front().function; 5285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) void* arg = queue_.front().arg; 5295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) queue_.pop_front(); 5305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) mu_.Release(); 5325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) (*function)(arg); 5335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 5345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 5355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void ChromiumEnv::StartThread(void (*function)(void* arg), void* arg) { 5375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) new Thread(function, arg); // Will self-delete. 5385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 5395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)::base::LazyInstance<ChromiumEnv>::Leaky 5415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) default_env = LAZY_INSTANCE_INITIALIZER; 5425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 5445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)Env* Env::Default() { 5465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return default_env.Pointer(); 5475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 5485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 550