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