summaryrefslogtreecommitdiff
path: root/util/env_posix.cc
diff options
context:
space:
mode:
authorSanjay Ghemawat <sanjay@google.com>2012-03-15 09:14:00 -0700
committerSanjay Ghemawat <sanjay@google.com>2012-03-15 09:14:00 -0700
commit9013f13b1512f6ab8c04518e8f036e58be271eba (patch)
treee5c2bed9104f74183981e1ff254074b362f6a856 /util/env_posix.cc
parent583f1499c00ff40f332149021f583cf6ee78dd7e (diff)
downloadleveldb-9013f13b1512f6ab8c04518e8f036e58be271eba.tar.gz
use mmap on 64-bit machines to speed-up reads; small build fixes
Diffstat (limited to 'util/env_posix.cc')
-rw-r--r--util/env_posix.cc50
1 files changed, 46 insertions, 4 deletions
diff --git a/util/env_posix.cc b/util/env_posix.cc
index cc73348..cb1f6fc 100644
--- a/util/env_posix.cc
+++ b/util/env_posix.cc
@@ -66,6 +66,7 @@ class PosixSequentialFile: public SequentialFile {
}
};
+// pread() based random-access
class PosixRandomAccessFile: public RandomAccessFile {
private:
std::string filename_;
@@ -89,6 +90,32 @@ class PosixRandomAccessFile: public RandomAccessFile {
}
};
+// mmap() based random-access
+class PosixMmapReadableFile: public RandomAccessFile {
+ private:
+ std::string filename_;
+ void* mmapped_region_;
+ size_t length_;
+
+ public:
+ // base[0,length-1] contains the mmapped contents of the file.
+ PosixMmapReadableFile(const std::string& fname, void* base, size_t length)
+ : filename_(fname), mmapped_region_(base), length_(length) { }
+ virtual ~PosixMmapReadableFile() { munmap(mmapped_region_, length_); }
+
+ virtual Status Read(uint64_t offset, size_t n, Slice* result,
+ char* scratch) const {
+ Status s;
+ if (offset + n > length_) {
+ *result = Slice();
+ s = IOError(filename_, EINVAL);
+ } else {
+ *result = Slice(reinterpret_cast<char*>(mmapped_region_) + offset, n);
+ }
+ return s;
+ }
+};
+
// We preallocate up to an extra megabyte and use memcpy to append new
// data to the file. This is safe since we either properly close the
// file before reading from it, or for log files, the reading code
@@ -297,13 +324,28 @@ class PosixEnv : public Env {
virtual Status NewRandomAccessFile(const std::string& fname,
RandomAccessFile** result) {
+ *result = NULL;
+ Status s;
int fd = open(fname.c_str(), O_RDONLY);
if (fd < 0) {
- *result = NULL;
- return IOError(fname, errno);
+ s = IOError(fname, errno);
+ } else if (sizeof(void*) >= 8) {
+ // Use mmap when virtual address-space is plentiful.
+ uint64_t size;
+ s = GetFileSize(fname, &size);
+ if (s.ok()) {
+ void* base = mmap(NULL, size, PROT_READ, MAP_SHARED, fd, 0);
+ if (base != MAP_FAILED) {
+ *result = new PosixMmapReadableFile(fname, base, size);
+ } else {
+ s = IOError(fname, errno);
+ }
+ }
+ close(fd);
+ } else {
+ *result = new PosixRandomAccessFile(fname, fd);
}
- *result = new PosixRandomAccessFile(fname, fd);
- return Status::OK();
+ return s;
}
virtual Status NewWritableFile(const std::string& fname,