Feathercoin  0.5.0
P2P Digital Currency
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros
env_posix.cc
Go to the documentation of this file.
1 // Copyright (c) 2011 The LevelDB Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. See the AUTHORS file for names of contributors.
4 #if !defined(LEVELDB_PLATFORM_WINDOWS)
5 
6 #include <deque>
7 #include <set>
8 #include <dirent.h>
9 #include <errno.h>
10 #include <fcntl.h>
11 #include <pthread.h>
12 #include <stdio.h>
13 #include <stdlib.h>
14 #include <string.h>
15 #include <sys/mman.h>
16 #include <sys/stat.h>
17 #include <sys/time.h>
18 #include <sys/types.h>
19 #include <time.h>
20 #include <unistd.h>
21 #if defined(LEVELDB_PLATFORM_ANDROID)
22 #include <sys/stat.h>
23 #endif
24 #include "leveldb/env.h"
25 #include "leveldb/slice.h"
26 #include "port/port.h"
27 #include "util/logging.h"
28 #include "util/mutexlock.h"
29 #include "util/posix_logger.h"
30 
31 namespace leveldb {
32 
33 namespace {
34 
35 static Status IOError(const std::string& context, int err_number) {
36  return Status::IOError(context, strerror(err_number));
37 }
38 
39 class PosixSequentialFile: public SequentialFile {
40  private:
41  std::string filename_;
42  FILE* file_;
43 
44  public:
45  PosixSequentialFile(const std::string& fname, FILE* f)
46  : filename_(fname), file_(f) { }
47  virtual ~PosixSequentialFile() { fclose(file_); }
48 
49  virtual Status Read(size_t n, Slice* result, char* scratch) {
50  Status s;
51  size_t r = fread_unlocked(scratch, 1, n, file_);
52  *result = Slice(scratch, r);
53  if (r < n) {
54  if (feof(file_)) {
55  // We leave status as ok if we hit the end of the file
56  } else {
57  // A partial read with an error: return a non-ok status
58  s = IOError(filename_, errno);
59  }
60  }
61  return s;
62  }
63 
64  virtual Status Skip(uint64_t n) {
65  if (fseek(file_, n, SEEK_CUR)) {
66  return IOError(filename_, errno);
67  }
68  return Status::OK();
69  }
70 };
71 
72 // pread() based random-access
73 class PosixRandomAccessFile: public RandomAccessFile {
74  private:
75  std::string filename_;
76  int fd_;
77 
78  public:
79  PosixRandomAccessFile(const std::string& fname, int fd)
80  : filename_(fname), fd_(fd) { }
81  virtual ~PosixRandomAccessFile() { close(fd_); }
82 
83  virtual Status Read(uint64_t offset, size_t n, Slice* result,
84  char* scratch) const {
85  Status s;
86  ssize_t r = pread(fd_, scratch, n, static_cast<off_t>(offset));
87  *result = Slice(scratch, (r < 0) ? 0 : r);
88  if (r < 0) {
89  // An error: return a non-ok status
90  s = IOError(filename_, errno);
91  }
92  return s;
93  }
94 };
95 
96 // Helper class to limit mmap file usage so that we do not end up
97 // running out virtual memory or running into kernel performance
98 // problems for very large databases.
99 class MmapLimiter {
100  public:
101  // Up to 1000 mmaps for 64-bit binaries; none for smaller pointer sizes.
102  MmapLimiter() {
103  SetAllowed(sizeof(void*) >= 8 ? 1000 : 0);
104  }
105 
106  // If another mmap slot is available, acquire it and return true.
107  // Else return false.
108  bool Acquire() {
109  if (GetAllowed() <= 0) {
110  return false;
111  }
112  MutexLock l(&mu_);
113  intptr_t x = GetAllowed();
114  if (x <= 0) {
115  return false;
116  } else {
117  SetAllowed(x - 1);
118  return true;
119  }
120  }
121 
122  // Release a slot acquired by a previous call to Acquire() that returned true.
123  void Release() {
124  MutexLock l(&mu_);
125  SetAllowed(GetAllowed() + 1);
126  }
127 
128  private:
129  port::Mutex mu_;
130  port::AtomicPointer allowed_;
131 
132  intptr_t GetAllowed() const {
133  return reinterpret_cast<intptr_t>(allowed_.Acquire_Load());
134  }
135 
136  // REQUIRES: mu_ must be held
137  void SetAllowed(intptr_t v) {
138  allowed_.Release_Store(reinterpret_cast<void*>(v));
139  }
140 
141  MmapLimiter(const MmapLimiter&);
142  void operator=(const MmapLimiter&);
143 };
144 
145 // mmap() based random-access
146 class PosixMmapReadableFile: public RandomAccessFile {
147  private:
148  std::string filename_;
150  size_t length_;
151  MmapLimiter* limiter_;
152 
153  public:
154  // base[0,length-1] contains the mmapped contents of the file.
155  PosixMmapReadableFile(const std::string& fname, void* base, size_t length,
156  MmapLimiter* limiter)
157  : filename_(fname), mmapped_region_(base), length_(length),
158  limiter_(limiter) {
159  }
160 
161  virtual ~PosixMmapReadableFile() {
162  munmap(mmapped_region_, length_);
163  limiter_->Release();
164  }
165 
166  virtual Status Read(uint64_t offset, size_t n, Slice* result,
167  char* scratch) const {
168  Status s;
169  if (offset + n > length_) {
170  *result = Slice();
171  s = IOError(filename_, EINVAL);
172  } else {
173  *result = Slice(reinterpret_cast<char*>(mmapped_region_) + offset, n);
174  }
175  return s;
176  }
177 };
178 
179 // We preallocate up to an extra megabyte and use memcpy to append new
180 // data to the file. This is safe since we either properly close the
181 // file before reading from it, or for log files, the reading code
182 // knows enough to skip zero suffixes.
183 class PosixMmapFile : public WritableFile {
184  private:
185  std::string filename_;
186  int fd_;
187  size_t page_size_;
188  size_t map_size_; // How much extra memory to map at a time
189  char* base_; // The mapped region
190  char* limit_; // Limit of the mapped region
191  char* dst_; // Where to write next (in range [base_,limit_])
192  char* last_sync_; // Where have we synced up to
193  uint64_t file_offset_; // Offset of base_ in file
194 
195  // Have we done an munmap of unsynced data?
197 
198  // Roundup x to a multiple of y
199  static size_t Roundup(size_t x, size_t y) {
200  return ((x + y - 1) / y) * y;
201  }
202 
203  size_t TruncateToPageBoundary(size_t s) {
204  s -= (s & (page_size_ - 1));
205  assert((s % page_size_) == 0);
206  return s;
207  }
208 
209  bool UnmapCurrentRegion() {
210  bool result = true;
211  if (base_ != NULL) {
212 #if defined(OS_MACOSX)
213  if (msync(base_, limit_ - base_, MS_SYNC) != 0) {
214  result = false;
215  }
216 #endif
217  if (last_sync_ < limit_) {
218  // Defer syncing this data until next Sync() call, if any
219  pending_sync_ = true;
220  }
221  if (munmap(base_, limit_ - base_) != 0) {
222  result = false;
223  }
224  file_offset_ += limit_ - base_;
225  base_ = NULL;
226  limit_ = NULL;
227  last_sync_ = NULL;
228  dst_ = NULL;
229 
230  // Increase the amount we map the next time, but capped at 1MB
231  if (map_size_ < (1<<20)) {
232  map_size_ *= 2;
233  }
234  }
235  return result;
236  }
237 
238  bool MapNewRegion() {
239  assert(base_ == NULL);
240  if (ftruncate(fd_, file_offset_ + map_size_) < 0) {
241  return false;
242  }
243  void* ptr = mmap(NULL, map_size_, PROT_READ | PROT_WRITE, MAP_SHARED,
244  fd_, file_offset_);
245  if (ptr == MAP_FAILED) {
246  return false;
247  }
248  base_ = reinterpret_cast<char*>(ptr);
249  limit_ = base_ + map_size_;
250  dst_ = base_;
251  last_sync_ = base_;
252  return true;
253  }
254 
255  public:
256  PosixMmapFile(const std::string& fname, int fd, size_t page_size)
257  : filename_(fname),
258  fd_(fd),
259  page_size_(page_size),
260  map_size_(Roundup(65536, page_size)),
261  base_(NULL),
262  limit_(NULL),
263  dst_(NULL),
264  last_sync_(NULL),
265  file_offset_(0),
266  pending_sync_(false) {
267  assert((page_size & (page_size - 1)) == 0);
268  }
269 
270 
271  ~PosixMmapFile() {
272  if (fd_ >= 0) {
273  PosixMmapFile::Close();
274  }
275  }
276 
277  virtual Status Append(const Slice& data) {
278  const char* src = data.data();
279  size_t left = data.size();
280  while (left > 0) {
281  assert(base_ <= dst_);
282  assert(dst_ <= limit_);
283  size_t avail = limit_ - dst_;
284  if (avail == 0) {
285  if (!UnmapCurrentRegion() ||
286  !MapNewRegion()) {
287  return IOError(filename_, errno);
288  }
289  }
290 
291  size_t n = (left <= avail) ? left : avail;
292  memcpy(dst_, src, n);
293  dst_ += n;
294  src += n;
295  left -= n;
296  }
297  return Status::OK();
298  }
299 
300  virtual Status Close() {
301  Status s;
302  size_t unused = limit_ - dst_;
303  if (!UnmapCurrentRegion()) {
304  s = IOError(filename_, errno);
305  } else if (unused > 0) {
306  // Trim the extra space at the end of the file
307  if (ftruncate(fd_, file_offset_ - unused) < 0) {
308  s = IOError(filename_, errno);
309  }
310  }
311 
312  if (close(fd_) < 0) {
313  if (s.ok()) {
314  s = IOError(filename_, errno);
315  }
316  }
317 
318  fd_ = -1;
319  base_ = NULL;
320  limit_ = NULL;
321  return s;
322  }
323 
324  virtual Status Flush() {
325  return Status::OK();
326  }
327 
328  Status SyncDirIfManifest() {
329  const char* f = filename_.c_str();
330  const char* sep = strrchr(f, '/');
331  Slice basename;
332  std::string dir;
333  if (sep == NULL) {
334  dir = ".";
335  basename = f;
336  } else {
337  dir = std::string(f, sep - f);
338  basename = sep + 1;
339  }
340  Status s;
341  if (basename.starts_with("MANIFEST")) {
342  int fd = open(dir.c_str(), O_RDONLY);
343  if (fd < 0) {
344  s = IOError(dir, errno);
345  } else {
346  if (fsync(fd) < 0) {
347  s = IOError(dir, errno);
348  }
349  close(fd);
350  }
351  }
352  return s;
353  }
354 
355  virtual Status Sync() {
356  // Ensure new files referred to by the manifest are in the filesystem.
357  Status s = SyncDirIfManifest();
358  if (!s.ok()) {
359  return s;
360  }
361 
362  if (pending_sync_) {
363  // Some unmapped data was not synced
364  pending_sync_ = false;
365  if (fdatasync(fd_) < 0) {
366  s = IOError(filename_, errno);
367  }
368  }
369 
370  if (dst_ > last_sync_) {
371  // Find the beginnings of the pages that contain the first and last
372  // bytes to be synced.
373  size_t p1 = TruncateToPageBoundary(last_sync_ - base_);
374  size_t p2 = TruncateToPageBoundary(dst_ - base_ - 1);
375  last_sync_ = dst_;
376  if (msync(base_ + p1, p2 - p1 + page_size_, MS_SYNC) < 0) {
377  s = IOError(filename_, errno);
378  }
379  }
380 
381  return s;
382  }
383 };
384 
385 class PosixWriteableFile : public WritableFile {
386  private:
387  std::string filename_;
388  int fd_;
389  public:
390  PosixWriteableFile(const std::string& fname, int fd)
391  : filename_(fname),
392  fd_(fd)
393  { }
394 
395 
396  ~PosixWriteableFile() {
397  if (fd_ >= 0) {
398  PosixWriteableFile::Close();
399  }
400  }
401 
402  virtual Status Append(const Slice& data) {
403  Status s;
404  int ret;
405  ret = write(fd_, data.data(), data.size());
406  if (ret < 0) {
407  s = IOError(filename_, errno);
408  } else if (ret < data.size()) {
409  s = Status::IOError(filename_, "short write");
410  }
411 
412  return s;
413  }
414 
415  virtual Status Close() {
416  Status s;
417  if (close(fd_) < 0) {
418  s = IOError(filename_, errno);
419  }
420  fd_ = -1;
421  return s;
422  }
423 
424  virtual Status Flush() {
425  return Status::OK();
426  }
427 
428  Status SyncDirIfManifest() {
429  const char* f = filename_.c_str();
430  const char* sep = strrchr(f, '/');
431  Slice basename;
432  std::string dir;
433  if (sep == NULL) {
434  dir = ".";
435  basename = f;
436  } else {
437  dir = std::string(f, sep - f);
438  basename = sep + 1;
439  }
440  Status s;
441  if (basename.starts_with("MANIFEST")) {
442  int fd = open(dir.c_str(), O_RDONLY);
443  if (fd < 0) {
444  s = IOError(dir, errno);
445  } else {
446  if (fsync(fd) < 0) {
447  s = IOError(dir, errno);
448  }
449  close(fd);
450  }
451  }
452  return s;
453  }
454 
455  virtual Status Sync() {
456  // Ensure new files referred to by the manifest are in the filesystem.
457  Status s = SyncDirIfManifest();
458  if (!s.ok()) {
459  return s;
460  }
461 
462  if (fdatasync(fd_) < 0) {
463  s = IOError(filename_, errno);
464  }
465 
466  return s;
467  }
468 };
469 
470 static int LockOrUnlock(int fd, bool lock) {
471  errno = 0;
472  struct flock f;
473  memset(&f, 0, sizeof(f));
474  f.l_type = (lock ? F_WRLCK : F_UNLCK);
475  f.l_whence = SEEK_SET;
476  f.l_start = 0;
477  f.l_len = 0; // Lock/unlock entire file
478  return fcntl(fd, F_SETLK, &f);
479 }
480 
481 class PosixFileLock : public FileLock {
482  public:
483  int fd_;
484  std::string name_;
485 };
486 
487 // Set of locked files. We keep a separate set instead of just
488 // relying on fcntrl(F_SETLK) since fcntl(F_SETLK) does not provide
489 // any protection against multiple uses from the same process.
490 class PosixLockTable {
491  private:
492  port::Mutex mu_;
493  std::set<std::string> locked_files_;
494  public:
495  bool Insert(const std::string& fname) {
496  MutexLock l(&mu_);
497  return locked_files_.insert(fname).second;
498  }
499  void Remove(const std::string& fname) {
500  MutexLock l(&mu_);
501  locked_files_.erase(fname);
502  }
503 };
504 
505 class PosixEnv : public Env {
506  public:
507  PosixEnv();
508  virtual ~PosixEnv() {
509  fprintf(stderr, "Destroying Env::Default()\n");
510  abort();
511  }
512 
513  virtual Status NewSequentialFile(const std::string& fname,
514  SequentialFile** result) {
515  FILE* f = fopen(fname.c_str(), "r");
516  if (f == NULL) {
517  *result = NULL;
518  return IOError(fname, errno);
519  } else {
520  *result = new PosixSequentialFile(fname, f);
521  return Status::OK();
522  }
523  }
524 
525  virtual Status NewRandomAccessFile(const std::string& fname,
526  RandomAccessFile** result) {
527  *result = NULL;
528  Status s;
529  int fd = open(fname.c_str(), O_RDONLY);
530  if (fd < 0) {
531  s = IOError(fname, errno);
532  } else {
533  *result = new PosixRandomAccessFile(fname, fd);
534  }
535  return s;
536  }
537 
538  virtual Status NewWritableFile(const std::string& fname,
539  WritableFile** result) {
540  Status s;
541  const int fd = open(fname.c_str(), O_CREAT | O_RDWR | O_TRUNC, 0644);
542  if (fd < 0) {
543  *result = NULL;
544  s = IOError(fname, errno);
545  } else {
546  *result = new PosixWriteableFile(fname, fd);
547  }
548  return s;
549  }
550 
551  virtual bool FileExists(const std::string& fname) {
552  return access(fname.c_str(), F_OK) == 0;
553  }
554 
555  virtual Status GetChildren(const std::string& dir,
556  std::vector<std::string>* result) {
557  result->clear();
558  DIR* d = opendir(dir.c_str());
559  if (d == NULL) {
560  return IOError(dir, errno);
561  }
562  struct dirent* entry;
563  while ((entry = readdir(d)) != NULL) {
564  result->push_back(entry->d_name);
565  }
566  closedir(d);
567  return Status::OK();
568  }
569 
570  virtual Status DeleteFile(const std::string& fname) {
571  Status result;
572  if (unlink(fname.c_str()) != 0) {
573  result = IOError(fname, errno);
574  }
575  return result;
576  }
577 
578  virtual Status CreateDir(const std::string& name) {
579  Status result;
580  if (mkdir(name.c_str(), 0755) != 0) {
581  result = IOError(name, errno);
582  }
583  return result;
584  }
585 
586  virtual Status DeleteDir(const std::string& name) {
587  Status result;
588  if (rmdir(name.c_str()) != 0) {
589  result = IOError(name, errno);
590  }
591  return result;
592  }
593 
594  virtual Status GetFileSize(const std::string& fname, uint64_t* size) {
595  Status s;
596  struct stat sbuf;
597  if (stat(fname.c_str(), &sbuf) != 0) {
598  *size = 0;
599  s = IOError(fname, errno);
600  } else {
601  *size = sbuf.st_size;
602  }
603  return s;
604  }
605 
606  virtual Status RenameFile(const std::string& src, const std::string& target) {
607  Status result;
608  if (rename(src.c_str(), target.c_str()) != 0) {
609  result = IOError(src, errno);
610  }
611  return result;
612  }
613 
614  virtual Status LockFile(const std::string& fname, FileLock** lock) {
615  *lock = NULL;
616  Status result;
617  int fd = open(fname.c_str(), O_RDWR | O_CREAT, 0644);
618  if (fd < 0) {
619  result = IOError(fname, errno);
620  } else if (!locks_.Insert(fname)) {
621  close(fd);
622  result = Status::IOError("lock " + fname, "already held by process");
623  } else if (LockOrUnlock(fd, true) == -1) {
624  result = IOError("lock " + fname, errno);
625  close(fd);
626  locks_.Remove(fname);
627  } else {
628  PosixFileLock* my_lock = new PosixFileLock;
629  my_lock->fd_ = fd;
630  my_lock->name_ = fname;
631  *lock = my_lock;
632  }
633  return result;
634  }
635 
636  virtual Status UnlockFile(FileLock* lock) {
637  PosixFileLock* my_lock = reinterpret_cast<PosixFileLock*>(lock);
638  Status result;
639  if (LockOrUnlock(my_lock->fd_, false) == -1) {
640  result = IOError("unlock", errno);
641  }
642  locks_.Remove(my_lock->name_);
643  close(my_lock->fd_);
644  delete my_lock;
645  return result;
646  }
647 
648  virtual void Schedule(void (*function)(void*), void* arg);
649 
650  virtual void StartThread(void (*function)(void* arg), void* arg);
651 
652  virtual Status GetTestDirectory(std::string* result) {
653  const char* env = getenv("TEST_TMPDIR");
654  if (env && env[0] != '\0') {
655  *result = env;
656  } else {
657  char buf[100];
658  snprintf(buf, sizeof(buf), "/tmp/leveldbtest-%d", int(geteuid()));
659  *result = buf;
660  }
661  // Directory may already exist
662  CreateDir(*result);
663  return Status::OK();
664  }
665 
666  static uint64_t gettid() {
667  pthread_t tid = pthread_self();
668  uint64_t thread_id = 0;
669  memcpy(&thread_id, &tid, std::min(sizeof(thread_id), sizeof(tid)));
670  return thread_id;
671  }
672 
673  virtual Status NewLogger(const std::string& fname, Logger** result) {
674  FILE* f = fopen(fname.c_str(), "w");
675  if (f == NULL) {
676  *result = NULL;
677  return IOError(fname, errno);
678  } else {
679  *result = new PosixLogger(f, &PosixEnv::gettid);
680  return Status::OK();
681  }
682  }
683 
684  virtual uint64_t NowMicros() {
685  struct timeval tv;
686  gettimeofday(&tv, NULL);
687  return static_cast<uint64_t>(tv.tv_sec) * 1000000 + tv.tv_usec;
688  }
689 
690  virtual void SleepForMicroseconds(int micros) {
691  usleep(micros);
692  }
693 
694  private:
695  void PthreadCall(const char* label, int result) {
696  if (result != 0) {
697  fprintf(stderr, "pthread %s: %s\n", label, strerror(result));
698  abort();
699  }
700  }
701 
702  // BGThread() is the body of the background thread
703  void BGThread();
704  static void* BGThreadWrapper(void* arg) {
705  reinterpret_cast<PosixEnv*>(arg)->BGThread();
706  return NULL;
707  }
708 
709  size_t page_size_;
710  pthread_mutex_t mu_;
711  pthread_cond_t bgsignal_;
712  pthread_t bgthread_;
714 
715  // Entry per Schedule() call
716  struct BGItem { void* arg; void (*function)(void*); };
717  typedef std::deque<BGItem> BGQueue;
718  BGQueue queue_;
719 
720  PosixLockTable locks_;
721  MmapLimiter mmap_limit_;
722 };
723 
724 PosixEnv::PosixEnv() : page_size_(getpagesize()),
725  started_bgthread_(false) {
726  PthreadCall("mutex_init", pthread_mutex_init(&mu_, NULL));
727  PthreadCall("cvar_init", pthread_cond_init(&bgsignal_, NULL));
728 }
729 
730 void PosixEnv::Schedule(void (*function)(void*), void* arg) {
731  PthreadCall("lock", pthread_mutex_lock(&mu_));
732 
733  // Start background thread if necessary
734  if (!started_bgthread_) {
735  started_bgthread_ = true;
736  PthreadCall(
737  "create thread",
738  pthread_create(&bgthread_, NULL, &PosixEnv::BGThreadWrapper, this));
739  }
740 
741  // If the queue is currently empty, the background thread may currently be
742  // waiting.
743  if (queue_.empty()) {
744  PthreadCall("signal", pthread_cond_signal(&bgsignal_));
745  }
746 
747  // Add to priority queue
748  queue_.push_back(BGItem());
749  queue_.back().function = function;
750  queue_.back().arg = arg;
751 
752  PthreadCall("unlock", pthread_mutex_unlock(&mu_));
753 }
754 
755 void PosixEnv::BGThread() {
756  while (true) {
757  // Wait until there is an item that is ready to run
758  PthreadCall("lock", pthread_mutex_lock(&mu_));
759  while (queue_.empty()) {
760  PthreadCall("wait", pthread_cond_wait(&bgsignal_, &mu_));
761  }
762 
763  void (*function)(void*) = queue_.front().function;
764  void* arg = queue_.front().arg;
765  queue_.pop_front();
766 
767  PthreadCall("unlock", pthread_mutex_unlock(&mu_));
768  (*function)(arg);
769  }
770 }
771 
772 namespace {
773 struct StartThreadState {
774  void (*user_function)(void*);
775  void* arg;
776 };
777 }
778 static void* StartThreadWrapper(void* arg) {
779  StartThreadState* state = reinterpret_cast<StartThreadState*>(arg);
780  state->user_function(state->arg);
781  delete state;
782  return NULL;
783 }
784 
785 void PosixEnv::StartThread(void (*function)(void* arg), void* arg) {
786  pthread_t t;
787  StartThreadState* state = new StartThreadState;
788  state->user_function = function;
789  state->arg = arg;
790  PthreadCall("start thread",
791  pthread_create(&t, NULL, &StartThreadWrapper, state));
792 }
793 
794 } // namespace
795 
796 static pthread_once_t once = PTHREAD_ONCE_INIT;
797 static Env* default_env;
798 static void InitDefaultEnv() { default_env = new PosixEnv; }
799 
800 Env* Env::Default() {
801  pthread_once(&once, InitDefaultEnv);
802  return default_env;
803 }
804 
805 } // namespace leveldb
806 
807 #endif
std::string name_
Definition: env_posix.cc:484
MmapLimiter mmap_limit_
Definition: env_posix.cc:721
int tid
Definition: db_bench.cc:289
char * dst_
Definition: env_posix.cc:191
int fd_
Definition: env_posix.cc:76
static Status OK()
Definition: status.h:32
port::Mutex mu_
Definition: env_posix.cc:129
void(* user_function)(void *)
Definition: env_posix.cc:774
std::set< std::string > locked_files_
Definition: env_posix.cc:493
port::AtomicPointer allowed_
Definition: env_posix.cc:130
char * base_
Definition: env_posix.cc:189
unsigned long long uint64_t
Definition: stdint.h:22
size_t length_
Definition: env_posix.cc:150
MmapLimiter * limiter_
Definition: env_posix.cc:151
MTState * state
Definition: db_test.cc:1708
void write(const Value &value, std::ostream &os)
uint64_t file_offset_
Definition: env_posix.cc:193
bool started_bgthread_
Definition: env_posix.cc:713
FILE * file_
Definition: env_posix.cc:42
void * mmapped_region_
Definition: env_posix.cc:149
BGQueue queue_
Definition: env_posix.cc:718
const char * base
Definition: testharness.cc:17
pthread_t bgthread_
Definition: env_posix.cc:712
pthread_cond_t bgsignal_
Definition: env_posix.cc:711
PosixLockTable locks_
Definition: env_posix.cc:720
bool pending_sync_
Definition: env_posix.cc:196
std::string filename_
Definition: env_posix.cc:41
size_t map_size_
Definition: env_posix.cc:188
char * limit_
Definition: env_posix.cc:190
size_t page_size_
Definition: env_posix.cc:187
char * last_sync_
Definition: env_posix.cc:192
void * arg
Definition: env_posix.cc:716
static Status IOError(const Slice &msg, const Slice &msg2=Slice())
Definition: status.h:47
const char * name
Definition: testharness.cc:18