1179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org// Copyright (c) 2011 The LevelDB Authors. All rights reserved. 2179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org// Use of this source code is governed by a BSD-style license that can be 3179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org// found in the LICENSE file. See the AUTHORS file for names of contributors. 4179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org 5179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org#include <deque> 629c68f16466b1704dc7a663cf51bf9c5579830c3dgrogan@chromium.org#include <set> 7179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org#include <dirent.h> 8179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org#include <errno.h> 9179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org#include <fcntl.h> 10179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org#include <pthread.h> 11179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org#include <stdio.h> 12179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org#include <stdlib.h> 13179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org#include <string.h> 14179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org#include <sys/mman.h> 15179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org#include <sys/stat.h> 16179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org#include <sys/time.h> 17179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org#include <sys/types.h> 18179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org#include <time.h> 19179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org#include <unistd.h> 20179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org#if defined(LEVELDB_PLATFORM_ANDROID) 21179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org#include <sys/stat.h> 22179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org#endif 23fbd97aa4c5325eace57d24b89845b9581bac9324jorlow@chromium.org#include "leveldb/env.h" 24fbd97aa4c5325eace57d24b89845b9581bac9324jorlow@chromium.org#include "leveldb/slice.h" 25179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org#include "port/port.h" 26179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org#include "util/logging.h" 2729c68f16466b1704dc7a663cf51bf9c5579830c3dgrogan@chromium.org#include "util/mutexlock.h" 28f65a55c8d0744b95be29a65d06b59b22b012f37bgabor@google.com#include "util/posix_logger.h" 29179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org 30179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.orgnamespace leveldb { 31179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org 32179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.orgnamespace { 33179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org 34917b88dd720b6e658c1fd7812bc61c605f315124gabor@google.comstatic Status IOError(const std::string& context, int err_number) { 35917b88dd720b6e658c1fd7812bc61c605f315124gabor@google.com return Status::IOError(context, strerror(err_number)); 36917b88dd720b6e658c1fd7812bc61c605f315124gabor@google.com} 37917b88dd720b6e658c1fd7812bc61c605f315124gabor@google.com 38179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.orgclass PosixSequentialFile: public SequentialFile { 39179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org private: 40179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org std::string filename_; 41179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org FILE* file_; 42179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org 43179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org public: 44179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org PosixSequentialFile(const std::string& fname, FILE* f) 45179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org : filename_(fname), file_(f) { } 46179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org virtual ~PosixSequentialFile() { fclose(file_); } 47179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org 48179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org virtual Status Read(size_t n, Slice* result, char* scratch) { 49179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org Status s; 50179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org size_t r = fread_unlocked(scratch, 1, n, file_); 51179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org *result = Slice(scratch, r); 52179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org if (r < n) { 53179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org if (feof(file_)) { 54179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org // We leave status as ok if we hit the end of the file 55179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org } else { 56179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org // A partial read with an error: return a non-ok status 57917b88dd720b6e658c1fd7812bc61c605f315124gabor@google.com s = IOError(filename_, errno); 58179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org } 59179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org } 60179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org return s; 61179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org } 62a5b4129c0a8c01158cde2244a5811f15b9d45ec0dgrogan@chromium.org 63a5b4129c0a8c01158cde2244a5811f15b9d45ec0dgrogan@chromium.org virtual Status Skip(uint64_t n) { 64a5b4129c0a8c01158cde2244a5811f15b9d45ec0dgrogan@chromium.org if (fseek(file_, n, SEEK_CUR)) { 65917b88dd720b6e658c1fd7812bc61c605f315124gabor@google.com return IOError(filename_, errno); 66a5b4129c0a8c01158cde2244a5811f15b9d45ec0dgrogan@chromium.org } 67a5b4129c0a8c01158cde2244a5811f15b9d45ec0dgrogan@chromium.org return Status::OK(); 68a5b4129c0a8c01158cde2244a5811f15b9d45ec0dgrogan@chromium.org } 69179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org}; 70179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org 71e83668fa64e932a64712c99398be0acfe75367afsanjay@google.com// pread() based random-access 72179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.orgclass PosixRandomAccessFile: public RandomAccessFile { 73179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org private: 74179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org std::string filename_; 75179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org int fd_; 76179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org 77179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org public: 78f85ede82f8c27a00c3120f67fbab89b2a89fe987jorlow@chromium.org PosixRandomAccessFile(const std::string& fname, int fd) 79f85ede82f8c27a00c3120f67fbab89b2a89fe987jorlow@chromium.org : filename_(fname), fd_(fd) { } 80179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org virtual ~PosixRandomAccessFile() { close(fd_); } 81179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org 82179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org virtual Status Read(uint64_t offset, size_t n, Slice* result, 83179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org char* scratch) const { 84179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org Status s; 85179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org ssize_t r = pread(fd_, scratch, n, static_cast<off_t>(offset)); 86179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org *result = Slice(scratch, (r < 0) ? 0 : r); 87179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org if (r < 0) { 88179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org // An error: return a non-ok status 89917b88dd720b6e658c1fd7812bc61c605f315124gabor@google.com s = IOError(filename_, errno); 90179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org } 91179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org return s; 92179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org } 93179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org}; 94179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org 9529c68f16466b1704dc7a663cf51bf9c5579830c3dgrogan@chromium.org// Helper class to limit mmap file usage so that we do not end up 9629c68f16466b1704dc7a663cf51bf9c5579830c3dgrogan@chromium.org// running out virtual memory or running into kernel performance 9729c68f16466b1704dc7a663cf51bf9c5579830c3dgrogan@chromium.org// problems for very large databases. 9829c68f16466b1704dc7a663cf51bf9c5579830c3dgrogan@chromium.orgclass MmapLimiter { 9929c68f16466b1704dc7a663cf51bf9c5579830c3dgrogan@chromium.org public: 10029c68f16466b1704dc7a663cf51bf9c5579830c3dgrogan@chromium.org // Up to 1000 mmaps for 64-bit binaries; none for smaller pointer sizes. 10129c68f16466b1704dc7a663cf51bf9c5579830c3dgrogan@chromium.org MmapLimiter() { 10229c68f16466b1704dc7a663cf51bf9c5579830c3dgrogan@chromium.org SetAllowed(sizeof(void*) >= 8 ? 1000 : 0); 10329c68f16466b1704dc7a663cf51bf9c5579830c3dgrogan@chromium.org } 10429c68f16466b1704dc7a663cf51bf9c5579830c3dgrogan@chromium.org 10529c68f16466b1704dc7a663cf51bf9c5579830c3dgrogan@chromium.org // If another mmap slot is available, acquire it and return true. 10629c68f16466b1704dc7a663cf51bf9c5579830c3dgrogan@chromium.org // Else return false. 10729c68f16466b1704dc7a663cf51bf9c5579830c3dgrogan@chromium.org bool Acquire() { 10829c68f16466b1704dc7a663cf51bf9c5579830c3dgrogan@chromium.org if (GetAllowed() <= 0) { 10929c68f16466b1704dc7a663cf51bf9c5579830c3dgrogan@chromium.org return false; 11029c68f16466b1704dc7a663cf51bf9c5579830c3dgrogan@chromium.org } 11129c68f16466b1704dc7a663cf51bf9c5579830c3dgrogan@chromium.org MutexLock l(&mu_); 11229c68f16466b1704dc7a663cf51bf9c5579830c3dgrogan@chromium.org intptr_t x = GetAllowed(); 11329c68f16466b1704dc7a663cf51bf9c5579830c3dgrogan@chromium.org if (x <= 0) { 11429c68f16466b1704dc7a663cf51bf9c5579830c3dgrogan@chromium.org return false; 11529c68f16466b1704dc7a663cf51bf9c5579830c3dgrogan@chromium.org } else { 11629c68f16466b1704dc7a663cf51bf9c5579830c3dgrogan@chromium.org SetAllowed(x - 1); 11729c68f16466b1704dc7a663cf51bf9c5579830c3dgrogan@chromium.org return true; 11829c68f16466b1704dc7a663cf51bf9c5579830c3dgrogan@chromium.org } 11929c68f16466b1704dc7a663cf51bf9c5579830c3dgrogan@chromium.org } 12029c68f16466b1704dc7a663cf51bf9c5579830c3dgrogan@chromium.org 12129c68f16466b1704dc7a663cf51bf9c5579830c3dgrogan@chromium.org // Release a slot acquired by a previous call to Acquire() that returned true. 12229c68f16466b1704dc7a663cf51bf9c5579830c3dgrogan@chromium.org void Release() { 12329c68f16466b1704dc7a663cf51bf9c5579830c3dgrogan@chromium.org MutexLock l(&mu_); 12429c68f16466b1704dc7a663cf51bf9c5579830c3dgrogan@chromium.org SetAllowed(GetAllowed() + 1); 12529c68f16466b1704dc7a663cf51bf9c5579830c3dgrogan@chromium.org } 12629c68f16466b1704dc7a663cf51bf9c5579830c3dgrogan@chromium.org 12729c68f16466b1704dc7a663cf51bf9c5579830c3dgrogan@chromium.org private: 12829c68f16466b1704dc7a663cf51bf9c5579830c3dgrogan@chromium.org port::Mutex mu_; 12929c68f16466b1704dc7a663cf51bf9c5579830c3dgrogan@chromium.org port::AtomicPointer allowed_; 13029c68f16466b1704dc7a663cf51bf9c5579830c3dgrogan@chromium.org 13129c68f16466b1704dc7a663cf51bf9c5579830c3dgrogan@chromium.org intptr_t GetAllowed() const { 13229c68f16466b1704dc7a663cf51bf9c5579830c3dgrogan@chromium.org return reinterpret_cast<intptr_t>(allowed_.Acquire_Load()); 13329c68f16466b1704dc7a663cf51bf9c5579830c3dgrogan@chromium.org } 13429c68f16466b1704dc7a663cf51bf9c5579830c3dgrogan@chromium.org 13529c68f16466b1704dc7a663cf51bf9c5579830c3dgrogan@chromium.org // REQUIRES: mu_ must be held 13629c68f16466b1704dc7a663cf51bf9c5579830c3dgrogan@chromium.org void SetAllowed(intptr_t v) { 13729c68f16466b1704dc7a663cf51bf9c5579830c3dgrogan@chromium.org allowed_.Release_Store(reinterpret_cast<void*>(v)); 13829c68f16466b1704dc7a663cf51bf9c5579830c3dgrogan@chromium.org } 13929c68f16466b1704dc7a663cf51bf9c5579830c3dgrogan@chromium.org 14029c68f16466b1704dc7a663cf51bf9c5579830c3dgrogan@chromium.org MmapLimiter(const MmapLimiter&); 14129c68f16466b1704dc7a663cf51bf9c5579830c3dgrogan@chromium.org void operator=(const MmapLimiter&); 14229c68f16466b1704dc7a663cf51bf9c5579830c3dgrogan@chromium.org}; 14329c68f16466b1704dc7a663cf51bf9c5579830c3dgrogan@chromium.org 144e83668fa64e932a64712c99398be0acfe75367afsanjay@google.com// mmap() based random-access 145e83668fa64e932a64712c99398be0acfe75367afsanjay@google.comclass PosixMmapReadableFile: public RandomAccessFile { 146e83668fa64e932a64712c99398be0acfe75367afsanjay@google.com private: 147e83668fa64e932a64712c99398be0acfe75367afsanjay@google.com std::string filename_; 148e83668fa64e932a64712c99398be0acfe75367afsanjay@google.com void* mmapped_region_; 149e83668fa64e932a64712c99398be0acfe75367afsanjay@google.com size_t length_; 15029c68f16466b1704dc7a663cf51bf9c5579830c3dgrogan@chromium.org MmapLimiter* limiter_; 151e83668fa64e932a64712c99398be0acfe75367afsanjay@google.com 152e83668fa64e932a64712c99398be0acfe75367afsanjay@google.com public: 153e83668fa64e932a64712c99398be0acfe75367afsanjay@google.com // base[0,length-1] contains the mmapped contents of the file. 15429c68f16466b1704dc7a663cf51bf9c5579830c3dgrogan@chromium.org PosixMmapReadableFile(const std::string& fname, void* base, size_t length, 15529c68f16466b1704dc7a663cf51bf9c5579830c3dgrogan@chromium.org MmapLimiter* limiter) 15629c68f16466b1704dc7a663cf51bf9c5579830c3dgrogan@chromium.org : filename_(fname), mmapped_region_(base), length_(length), 15729c68f16466b1704dc7a663cf51bf9c5579830c3dgrogan@chromium.org limiter_(limiter) { 15829c68f16466b1704dc7a663cf51bf9c5579830c3dgrogan@chromium.org } 15929c68f16466b1704dc7a663cf51bf9c5579830c3dgrogan@chromium.org 16029c68f16466b1704dc7a663cf51bf9c5579830c3dgrogan@chromium.org virtual ~PosixMmapReadableFile() { 16129c68f16466b1704dc7a663cf51bf9c5579830c3dgrogan@chromium.org munmap(mmapped_region_, length_); 16229c68f16466b1704dc7a663cf51bf9c5579830c3dgrogan@chromium.org limiter_->Release(); 16329c68f16466b1704dc7a663cf51bf9c5579830c3dgrogan@chromium.org } 164e83668fa64e932a64712c99398be0acfe75367afsanjay@google.com 165e83668fa64e932a64712c99398be0acfe75367afsanjay@google.com virtual Status Read(uint64_t offset, size_t n, Slice* result, 166e83668fa64e932a64712c99398be0acfe75367afsanjay@google.com char* scratch) const { 167e83668fa64e932a64712c99398be0acfe75367afsanjay@google.com Status s; 168e83668fa64e932a64712c99398be0acfe75367afsanjay@google.com if (offset + n > length_) { 169e83668fa64e932a64712c99398be0acfe75367afsanjay@google.com *result = Slice(); 170e83668fa64e932a64712c99398be0acfe75367afsanjay@google.com s = IOError(filename_, EINVAL); 171e83668fa64e932a64712c99398be0acfe75367afsanjay@google.com } else { 172e83668fa64e932a64712c99398be0acfe75367afsanjay@google.com *result = Slice(reinterpret_cast<char*>(mmapped_region_) + offset, n); 173e83668fa64e932a64712c99398be0acfe75367afsanjay@google.com } 174e83668fa64e932a64712c99398be0acfe75367afsanjay@google.com return s; 175e83668fa64e932a64712c99398be0acfe75367afsanjay@google.com } 176e83668fa64e932a64712c99398be0acfe75367afsanjay@google.com}; 177e83668fa64e932a64712c99398be0acfe75367afsanjay@google.com 178179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org// We preallocate up to an extra megabyte and use memcpy to append new 179179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org// data to the file. This is safe since we either properly close the 180179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org// file before reading from it, or for log files, the reading code 181179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org// knows enough to skip zero suffixes. 182179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.orgclass PosixMmapFile : public WritableFile { 183179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org private: 184179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org std::string filename_; 185179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org int fd_; 186179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org size_t page_size_; 187179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org size_t map_size_; // How much extra memory to map at a time 188179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org char* base_; // The mapped region 189179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org char* limit_; // Limit of the mapped region 190179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org char* dst_; // Where to write next (in range [base_,limit_]) 191179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org char* last_sync_; // Where have we synced up to 192179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org uint64_t file_offset_; // Offset of base_ in file 193179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org 194179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org // Have we done an munmap of unsynced data? 195179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org bool pending_sync_; 196179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org 197179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org // Roundup x to a multiple of y 198179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org static size_t Roundup(size_t x, size_t y) { 199179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org return ((x + y - 1) / y) * y; 200179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org } 201179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org 202179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org size_t TruncateToPageBoundary(size_t s) { 203179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org s -= (s & (page_size_ - 1)); 204179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org assert((s % page_size_) == 0); 205179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org return s; 206179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org } 207179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org 208917b88dd720b6e658c1fd7812bc61c605f315124gabor@google.com bool UnmapCurrentRegion() { 209917b88dd720b6e658c1fd7812bc61c605f315124gabor@google.com bool result = true; 210179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org if (base_ != NULL) { 211179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org if (last_sync_ < limit_) { 212179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org // Defer syncing this data until next Sync() call, if any 213179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org pending_sync_ = true; 214179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org } 215917b88dd720b6e658c1fd7812bc61c605f315124gabor@google.com if (munmap(base_, limit_ - base_) != 0) { 216917b88dd720b6e658c1fd7812bc61c605f315124gabor@google.com result = false; 217917b88dd720b6e658c1fd7812bc61c605f315124gabor@google.com } 218179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org file_offset_ += limit_ - base_; 219179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org base_ = NULL; 220179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org limit_ = NULL; 221179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org last_sync_ = NULL; 222179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org dst_ = NULL; 223179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org 224179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org // Increase the amount we map the next time, but capped at 1MB 225179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org if (map_size_ < (1<<20)) { 226179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org map_size_ *= 2; 227179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org } 228179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org } 229917b88dd720b6e658c1fd7812bc61c605f315124gabor@google.com return result; 230179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org } 231179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org 232179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org bool MapNewRegion() { 233179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org assert(base_ == NULL); 234179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org if (ftruncate(fd_, file_offset_ + map_size_) < 0) { 235179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org return false; 236179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org } 237179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org void* ptr = mmap(NULL, map_size_, PROT_READ | PROT_WRITE, MAP_SHARED, 238179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org fd_, file_offset_); 239179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org if (ptr == MAP_FAILED) { 240179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org return false; 241179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org } 242179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org base_ = reinterpret_cast<char*>(ptr); 243179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org limit_ = base_ + map_size_; 244179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org dst_ = base_; 245179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org last_sync_ = base_; 246179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org return true; 247179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org } 248179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org 249179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org public: 250179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org PosixMmapFile(const std::string& fname, int fd, size_t page_size) 251179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org : filename_(fname), 252179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org fd_(fd), 253179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org page_size_(page_size), 254179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org map_size_(Roundup(65536, page_size)), 255179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org base_(NULL), 256179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org limit_(NULL), 257179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org dst_(NULL), 258179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org last_sync_(NULL), 259179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org file_offset_(0), 260179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org pending_sync_(false) { 261179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org assert((page_size & (page_size - 1)) == 0); 262179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org } 263179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org 264179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org 265179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org ~PosixMmapFile() { 266179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org if (fd_ >= 0) { 267179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org PosixMmapFile::Close(); 268179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org } 269179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org } 270179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org 271179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org virtual Status Append(const Slice& data) { 272179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org const char* src = data.data(); 273179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org size_t left = data.size(); 274179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org while (left > 0) { 275179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org assert(base_ <= dst_); 276179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org assert(dst_ <= limit_); 277179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org size_t avail = limit_ - dst_; 278179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org if (avail == 0) { 279917b88dd720b6e658c1fd7812bc61c605f315124gabor@google.com if (!UnmapCurrentRegion() || 280917b88dd720b6e658c1fd7812bc61c605f315124gabor@google.com !MapNewRegion()) { 281917b88dd720b6e658c1fd7812bc61c605f315124gabor@google.com return IOError(filename_, errno); 282917b88dd720b6e658c1fd7812bc61c605f315124gabor@google.com } 283179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org } 284179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org 285179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org size_t n = (left <= avail) ? left : avail; 286179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org memcpy(dst_, src, n); 287179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org dst_ += n; 288179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org src += n; 289179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org left -= n; 290179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org } 291179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org return Status::OK(); 292179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org } 293179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org 294179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org virtual Status Close() { 295179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org Status s; 296179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org size_t unused = limit_ - dst_; 297917b88dd720b6e658c1fd7812bc61c605f315124gabor@google.com if (!UnmapCurrentRegion()) { 298917b88dd720b6e658c1fd7812bc61c605f315124gabor@google.com s = IOError(filename_, errno); 299917b88dd720b6e658c1fd7812bc61c605f315124gabor@google.com } else if (unused > 0) { 300179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org // Trim the extra space at the end of the file 301179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org if (ftruncate(fd_, file_offset_ - unused) < 0) { 302917b88dd720b6e658c1fd7812bc61c605f315124gabor@google.com s = IOError(filename_, errno); 303179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org } 304179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org } 305179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org 306179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org if (close(fd_) < 0) { 307179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org if (s.ok()) { 308917b88dd720b6e658c1fd7812bc61c605f315124gabor@google.com s = IOError(filename_, errno); 309179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org } 310179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org } 311179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org 312179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org fd_ = -1; 313179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org base_ = NULL; 314179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org limit_ = NULL; 315179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org return s; 316179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org } 317179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org 318179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org virtual Status Flush() { 319179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org return Status::OK(); 320179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org } 321179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org 322179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org virtual Status Sync() { 323179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org Status s; 324179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org 325179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org if (pending_sync_) { 326179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org // Some unmapped data was not synced 327179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org pending_sync_ = false; 328179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org if (fdatasync(fd_) < 0) { 329917b88dd720b6e658c1fd7812bc61c605f315124gabor@google.com s = IOError(filename_, errno); 330179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org } 331179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org } 332179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org 333179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org if (dst_ > last_sync_) { 334179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org // Find the beginnings of the pages that contain the first and last 335179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org // bytes to be synced. 336179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org size_t p1 = TruncateToPageBoundary(last_sync_ - base_); 337179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org size_t p2 = TruncateToPageBoundary(dst_ - base_ - 1); 338179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org last_sync_ = dst_; 339179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org if (msync(base_ + p1, p2 - p1 + page_size_, MS_SYNC) < 0) { 340917b88dd720b6e658c1fd7812bc61c605f315124gabor@google.com s = IOError(filename_, errno); 341179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org } 342179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org } 343179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org 344179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org return s; 345179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org } 346179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org}; 347179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org 348179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.orgstatic int LockOrUnlock(int fd, bool lock) { 349179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org errno = 0; 350179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org struct flock f; 351179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org memset(&f, 0, sizeof(f)); 352179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org f.l_type = (lock ? F_WRLCK : F_UNLCK); 353179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org f.l_whence = SEEK_SET; 354179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org f.l_start = 0; 355179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org f.l_len = 0; // Lock/unlock entire file 356179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org return fcntl(fd, F_SETLK, &f); 357179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org} 358179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org 359179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.orgclass PosixFileLock : public FileLock { 360179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org public: 361179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org int fd_; 36229c68f16466b1704dc7a663cf51bf9c5579830c3dgrogan@chromium.org std::string name_; 36329c68f16466b1704dc7a663cf51bf9c5579830c3dgrogan@chromium.org}; 36429c68f16466b1704dc7a663cf51bf9c5579830c3dgrogan@chromium.org 36529c68f16466b1704dc7a663cf51bf9c5579830c3dgrogan@chromium.org// Set of locked files. We keep a separate set instead of just 36629c68f16466b1704dc7a663cf51bf9c5579830c3dgrogan@chromium.org// relying on fcntrl(F_SETLK) since fcntl(F_SETLK) does not provide 36729c68f16466b1704dc7a663cf51bf9c5579830c3dgrogan@chromium.org// any protection against multiple uses from the same process. 36829c68f16466b1704dc7a663cf51bf9c5579830c3dgrogan@chromium.orgclass PosixLockTable { 36929c68f16466b1704dc7a663cf51bf9c5579830c3dgrogan@chromium.org private: 37029c68f16466b1704dc7a663cf51bf9c5579830c3dgrogan@chromium.org port::Mutex mu_; 37129c68f16466b1704dc7a663cf51bf9c5579830c3dgrogan@chromium.org std::set<std::string> locked_files_; 37229c68f16466b1704dc7a663cf51bf9c5579830c3dgrogan@chromium.org public: 37329c68f16466b1704dc7a663cf51bf9c5579830c3dgrogan@chromium.org bool Insert(const std::string& fname) { 37429c68f16466b1704dc7a663cf51bf9c5579830c3dgrogan@chromium.org MutexLock l(&mu_); 37529c68f16466b1704dc7a663cf51bf9c5579830c3dgrogan@chromium.org return locked_files_.insert(fname).second; 37629c68f16466b1704dc7a663cf51bf9c5579830c3dgrogan@chromium.org } 37729c68f16466b1704dc7a663cf51bf9c5579830c3dgrogan@chromium.org void Remove(const std::string& fname) { 37829c68f16466b1704dc7a663cf51bf9c5579830c3dgrogan@chromium.org MutexLock l(&mu_); 37929c68f16466b1704dc7a663cf51bf9c5579830c3dgrogan@chromium.org locked_files_.erase(fname); 38029c68f16466b1704dc7a663cf51bf9c5579830c3dgrogan@chromium.org } 381179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org}; 382179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org 383179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.orgclass PosixEnv : public Env { 384179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org public: 385179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org PosixEnv(); 386179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org virtual ~PosixEnv() { 387179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org fprintf(stderr, "Destroying Env::Default()\n"); 388bd534e2d9ba35e6ada9afe854ad0dbcef3f27c4fdgrogan@chromium.org abort(); 389179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org } 390179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org 391179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org virtual Status NewSequentialFile(const std::string& fname, 392179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org SequentialFile** result) { 393179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org FILE* f = fopen(fname.c_str(), "r"); 394179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org if (f == NULL) { 395179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org *result = NULL; 396917b88dd720b6e658c1fd7812bc61c605f315124gabor@google.com return IOError(fname, errno); 397179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org } else { 398179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org *result = new PosixSequentialFile(fname, f); 399179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org return Status::OK(); 400179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org } 401179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org } 402179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org 403179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org virtual Status NewRandomAccessFile(const std::string& fname, 404179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org RandomAccessFile** result) { 405e83668fa64e932a64712c99398be0acfe75367afsanjay@google.com *result = NULL; 406e83668fa64e932a64712c99398be0acfe75367afsanjay@google.com Status s; 407179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org int fd = open(fname.c_str(), O_RDONLY); 408179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org if (fd < 0) { 409e83668fa64e932a64712c99398be0acfe75367afsanjay@google.com s = IOError(fname, errno); 41029c68f16466b1704dc7a663cf51bf9c5579830c3dgrogan@chromium.org } else if (mmap_limit_.Acquire()) { 411e83668fa64e932a64712c99398be0acfe75367afsanjay@google.com uint64_t size; 412e83668fa64e932a64712c99398be0acfe75367afsanjay@google.com s = GetFileSize(fname, &size); 413e83668fa64e932a64712c99398be0acfe75367afsanjay@google.com if (s.ok()) { 414e83668fa64e932a64712c99398be0acfe75367afsanjay@google.com void* base = mmap(NULL, size, PROT_READ, MAP_SHARED, fd, 0); 415e83668fa64e932a64712c99398be0acfe75367afsanjay@google.com if (base != MAP_FAILED) { 41629c68f16466b1704dc7a663cf51bf9c5579830c3dgrogan@chromium.org *result = new PosixMmapReadableFile(fname, base, size, &mmap_limit_); 417e83668fa64e932a64712c99398be0acfe75367afsanjay@google.com } else { 418e83668fa64e932a64712c99398be0acfe75367afsanjay@google.com s = IOError(fname, errno); 419e83668fa64e932a64712c99398be0acfe75367afsanjay@google.com } 420e83668fa64e932a64712c99398be0acfe75367afsanjay@google.com } 421e83668fa64e932a64712c99398be0acfe75367afsanjay@google.com close(fd); 42229c68f16466b1704dc7a663cf51bf9c5579830c3dgrogan@chromium.org if (!s.ok()) { 42329c68f16466b1704dc7a663cf51bf9c5579830c3dgrogan@chromium.org mmap_limit_.Release(); 42429c68f16466b1704dc7a663cf51bf9c5579830c3dgrogan@chromium.org } 425e83668fa64e932a64712c99398be0acfe75367afsanjay@google.com } else { 426e83668fa64e932a64712c99398be0acfe75367afsanjay@google.com *result = new PosixRandomAccessFile(fname, fd); 427179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org } 428e83668fa64e932a64712c99398be0acfe75367afsanjay@google.com return s; 429179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org } 430179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org 431179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org virtual Status NewWritableFile(const std::string& fname, 432179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org WritableFile** result) { 433179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org Status s; 434179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org const int fd = open(fname.c_str(), O_CREAT | O_RDWR | O_TRUNC, 0644); 435179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org if (fd < 0) { 436179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org *result = NULL; 437917b88dd720b6e658c1fd7812bc61c605f315124gabor@google.com s = IOError(fname, errno); 438179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org } else { 439179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org *result = new PosixMmapFile(fname, fd, page_size_); 440179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org } 441179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org return s; 442179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org } 443179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org 444179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org virtual bool FileExists(const std::string& fname) { 445179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org return access(fname.c_str(), F_OK) == 0; 446179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org } 447179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org 448179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org virtual Status GetChildren(const std::string& dir, 449179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org std::vector<std::string>* result) { 450179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org result->clear(); 451179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org DIR* d = opendir(dir.c_str()); 452179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org if (d == NULL) { 453917b88dd720b6e658c1fd7812bc61c605f315124gabor@google.com return IOError(dir, errno); 454179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org } 455179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org struct dirent* entry; 456179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org while ((entry = readdir(d)) != NULL) { 457179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org result->push_back(entry->d_name); 458179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org } 459179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org closedir(d); 460179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org return Status::OK(); 461179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org } 462179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org 463179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org virtual Status DeleteFile(const std::string& fname) { 464179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org Status result; 465179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org if (unlink(fname.c_str()) != 0) { 466917b88dd720b6e658c1fd7812bc61c605f315124gabor@google.com result = IOError(fname, errno); 467179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org } 468179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org return result; 46911042098fe3e5a16ad70c388bb5914a907ae3faedgrogan@chromium.org } 470179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org 471179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org virtual Status CreateDir(const std::string& name) { 472179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org Status result; 473179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org if (mkdir(name.c_str(), 0755) != 0) { 474917b88dd720b6e658c1fd7812bc61c605f315124gabor@google.com result = IOError(name, errno); 475179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org } 476179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org return result; 47711042098fe3e5a16ad70c388bb5914a907ae3faedgrogan@chromium.org } 478179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org 479179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org virtual Status DeleteDir(const std::string& name) { 480179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org Status result; 481179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org if (rmdir(name.c_str()) != 0) { 482917b88dd720b6e658c1fd7812bc61c605f315124gabor@google.com result = IOError(name, errno); 483179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org } 484179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org return result; 48511042098fe3e5a16ad70c388bb5914a907ae3faedgrogan@chromium.org } 486179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org 487179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org virtual Status GetFileSize(const std::string& fname, uint64_t* size) { 488179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org Status s; 489179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org struct stat sbuf; 490179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org if (stat(fname.c_str(), &sbuf) != 0) { 491179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org *size = 0; 492917b88dd720b6e658c1fd7812bc61c605f315124gabor@google.com s = IOError(fname, errno); 493179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org } else { 494179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org *size = sbuf.st_size; 495179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org } 496179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org return s; 497179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org } 498179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org 499179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org virtual Status RenameFile(const std::string& src, const std::string& target) { 500179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org Status result; 501179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org if (rename(src.c_str(), target.c_str()) != 0) { 502917b88dd720b6e658c1fd7812bc61c605f315124gabor@google.com result = IOError(src, errno); 503179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org } 504179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org return result; 505179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org } 506179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org 507179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org virtual Status LockFile(const std::string& fname, FileLock** lock) { 508179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org *lock = NULL; 509179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org Status result; 510179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org int fd = open(fname.c_str(), O_RDWR | O_CREAT, 0644); 511179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org if (fd < 0) { 512917b88dd720b6e658c1fd7812bc61c605f315124gabor@google.com result = IOError(fname, errno); 51329c68f16466b1704dc7a663cf51bf9c5579830c3dgrogan@chromium.org } else if (!locks_.Insert(fname)) { 51429c68f16466b1704dc7a663cf51bf9c5579830c3dgrogan@chromium.org close(fd); 51529c68f16466b1704dc7a663cf51bf9c5579830c3dgrogan@chromium.org result = Status::IOError("lock " + fname, "already held by process"); 516179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org } else if (LockOrUnlock(fd, true) == -1) { 517917b88dd720b6e658c1fd7812bc61c605f315124gabor@google.com result = IOError("lock " + fname, errno); 518179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org close(fd); 51929c68f16466b1704dc7a663cf51bf9c5579830c3dgrogan@chromium.org locks_.Remove(fname); 520179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org } else { 521179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org PosixFileLock* my_lock = new PosixFileLock; 522179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org my_lock->fd_ = fd; 52329c68f16466b1704dc7a663cf51bf9c5579830c3dgrogan@chromium.org my_lock->name_ = fname; 524179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org *lock = my_lock; 525179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org } 526179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org return result; 527179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org } 528179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org 529179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org virtual Status UnlockFile(FileLock* lock) { 530179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org PosixFileLock* my_lock = reinterpret_cast<PosixFileLock*>(lock); 531179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org Status result; 532179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org if (LockOrUnlock(my_lock->fd_, false) == -1) { 533917b88dd720b6e658c1fd7812bc61c605f315124gabor@google.com result = IOError("unlock", errno); 534179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org } 53529c68f16466b1704dc7a663cf51bf9c5579830c3dgrogan@chromium.org locks_.Remove(my_lock->name_); 536179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org close(my_lock->fd_); 537179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org delete my_lock; 538179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org return result; 539179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org } 540179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org 541179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org virtual void Schedule(void (*function)(void*), void* arg); 542179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org 543179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org virtual void StartThread(void (*function)(void* arg), void* arg); 544179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org 545179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org virtual Status GetTestDirectory(std::string* result) { 546179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org const char* env = getenv("TEST_TMPDIR"); 547179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org if (env && env[0] != '\0') { 548179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org *result = env; 549179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org } else { 550179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org char buf[100]; 551179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org snprintf(buf, sizeof(buf), "/tmp/leveldbtest-%d", int(geteuid())); 552179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org *result = buf; 553179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org } 554179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org // Directory may already exist 555179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org CreateDir(*result); 556179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org return Status::OK(); 557179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org } 558179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org 559f65a55c8d0744b95be29a65d06b59b22b012f37bgabor@google.com static uint64_t gettid() { 560179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org pthread_t tid = pthread_self(); 561179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org uint64_t thread_id = 0; 56284744ee8e3e568ca5b24eabf31be706d69d80c4djorlow@chromium.org memcpy(&thread_id, &tid, std::min(sizeof(thread_id), sizeof(tid))); 563f65a55c8d0744b95be29a65d06b59b22b012f37bgabor@google.com return thread_id; 564f65a55c8d0744b95be29a65d06b59b22b012f37bgabor@google.com } 565179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org 566f65a55c8d0744b95be29a65d06b59b22b012f37bgabor@google.com virtual Status NewLogger(const std::string& fname, Logger** result) { 567f65a55c8d0744b95be29a65d06b59b22b012f37bgabor@google.com FILE* f = fopen(fname.c_str(), "w"); 568f65a55c8d0744b95be29a65d06b59b22b012f37bgabor@google.com if (f == NULL) { 569f65a55c8d0744b95be29a65d06b59b22b012f37bgabor@google.com *result = NULL; 570f65a55c8d0744b95be29a65d06b59b22b012f37bgabor@google.com return IOError(fname, errno); 571f65a55c8d0744b95be29a65d06b59b22b012f37bgabor@google.com } else { 572f65a55c8d0744b95be29a65d06b59b22b012f37bgabor@google.com *result = new PosixLogger(f, &PosixEnv::gettid); 573f65a55c8d0744b95be29a65d06b59b22b012f37bgabor@google.com return Status::OK(); 574179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org } 575179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org } 576179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org 577179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org virtual uint64_t NowMicros() { 578179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org struct timeval tv; 579179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org gettimeofday(&tv, NULL); 580179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org return static_cast<uint64_t>(tv.tv_sec) * 1000000 + tv.tv_usec; 581179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org } 582179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org 583179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org virtual void SleepForMicroseconds(int micros) { 584179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org usleep(micros); 585179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org } 586179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org 587179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org private: 588179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org void PthreadCall(const char* label, int result) { 589179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org if (result != 0) { 590179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org fprintf(stderr, "pthread %s: %s\n", label, strerror(result)); 591bd534e2d9ba35e6ada9afe854ad0dbcef3f27c4fdgrogan@chromium.org abort(); 592179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org } 593179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org } 594179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org 595179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org // BGThread() is the body of the background thread 596179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org void BGThread(); 597179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org static void* BGThreadWrapper(void* arg) { 598179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org reinterpret_cast<PosixEnv*>(arg)->BGThread(); 599179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org return NULL; 600179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org } 601179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org 602179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org size_t page_size_; 603179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org pthread_mutex_t mu_; 604179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org pthread_cond_t bgsignal_; 605179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org pthread_t bgthread_; 606179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org bool started_bgthread_; 607179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org 608179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org // Entry per Schedule() call 609179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org struct BGItem { void* arg; void (*function)(void*); }; 610179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org typedef std::deque<BGItem> BGQueue; 611179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org BGQueue queue_; 61229c68f16466b1704dc7a663cf51bf9c5579830c3dgrogan@chromium.org 61329c68f16466b1704dc7a663cf51bf9c5579830c3dgrogan@chromium.org PosixLockTable locks_; 61429c68f16466b1704dc7a663cf51bf9c5579830c3dgrogan@chromium.org MmapLimiter mmap_limit_; 615179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org}; 616179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org 617179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.orgPosixEnv::PosixEnv() : page_size_(getpagesize()), 618179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org started_bgthread_(false) { 619179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org PthreadCall("mutex_init", pthread_mutex_init(&mu_, NULL)); 620179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org PthreadCall("cvar_init", pthread_cond_init(&bgsignal_, NULL)); 621179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org} 622179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org 623179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.orgvoid PosixEnv::Schedule(void (*function)(void*), void* arg) { 624179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org PthreadCall("lock", pthread_mutex_lock(&mu_)); 625179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org 626179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org // Start background thread if necessary 627179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org if (!started_bgthread_) { 628179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org started_bgthread_ = true; 629179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org PthreadCall( 630179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org "create thread", 631179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org pthread_create(&bgthread_, NULL, &PosixEnv::BGThreadWrapper, this)); 632179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org } 633179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org 634179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org // If the queue is currently empty, the background thread may currently be 635179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org // waiting. 636179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org if (queue_.empty()) { 637179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org PthreadCall("signal", pthread_cond_signal(&bgsignal_)); 638179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org } 639179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org 640179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org // Add to priority queue 641179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org queue_.push_back(BGItem()); 642179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org queue_.back().function = function; 643179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org queue_.back().arg = arg; 644179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org 645179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org PthreadCall("unlock", pthread_mutex_unlock(&mu_)); 646179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org} 647179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org 648179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.orgvoid PosixEnv::BGThread() { 649179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org while (true) { 650179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org // Wait until there is an item that is ready to run 651179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org PthreadCall("lock", pthread_mutex_lock(&mu_)); 652179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org while (queue_.empty()) { 653179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org PthreadCall("wait", pthread_cond_wait(&bgsignal_, &mu_)); 654179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org } 655179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org 656179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org void (*function)(void*) = queue_.front().function; 657179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org void* arg = queue_.front().arg; 658179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org queue_.pop_front(); 659179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org 660179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org PthreadCall("unlock", pthread_mutex_unlock(&mu_)); 661179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org (*function)(arg); 662179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org } 663179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org} 664179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org 665179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.orgnamespace { 666179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.orgstruct StartThreadState { 667179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org void (*user_function)(void*); 668179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org void* arg; 669179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org}; 670179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org} 671179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.orgstatic void* StartThreadWrapper(void* arg) { 672179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org StartThreadState* state = reinterpret_cast<StartThreadState*>(arg); 673179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org state->user_function(state->arg); 674179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org delete state; 675179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org return NULL; 676179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org} 677179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org 678179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.orgvoid PosixEnv::StartThread(void (*function)(void* arg), void* arg) { 679179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org pthread_t t; 680179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org StartThreadState* state = new StartThreadState; 681179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org state->user_function = function; 682179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org state->arg = arg; 683179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org PthreadCall("start thread", 684179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org pthread_create(&t, NULL, &StartThreadWrapper, state)); 685179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org} 686179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org 68745b9940be332834440bd5299419f396e38085ebehans@chromium.org} // namespace 688179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org 689179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.orgstatic pthread_once_t once = PTHREAD_ONCE_INIT; 690179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.orgstatic Env* default_env; 691179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.orgstatic void InitDefaultEnv() { default_env = new PosixEnv; } 692179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org 693179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.orgEnv* Env::Default() { 694179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org pthread_once(&once, InitDefaultEnv); 695179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org return default_env; 696179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org} 697179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org 69845b9940be332834440bd5299419f396e38085ebehans@chromium.org} // namespace leveldb 699