From c82cd3f8fa51c83cfdedc3557ffb7b7f5264f552 Mon Sep 17 00:00:00 2001 From: ksherlock Date: Sat, 19 Feb 2011 18:07:28 +0000 Subject: [PATCH] new branch to integrate BlockDevice, BlockCache git-svn-id: https://profuse.googlecode.com/svn/branches/profuse_interim@334 aa027e90-d47c-11dd-86d7-074df07e0730 --- File/File.cpp | 128 ++++++++++++++++++++++++++++++ File/File.h | 58 ++++++++++++++ File/MappedFile.cpp | 187 ++++++++++++++++++++++++++++++++++++++++++++ File/MappedFile.h | 53 +++++++++++++ 4 files changed, 426 insertions(+) create mode 100644 File/File.cpp create mode 100644 File/File.h create mode 100644 File/MappedFile.cpp create mode 100644 File/MappedFile.h diff --git a/File/File.cpp b/File/File.cpp new file mode 100644 index 0000000..4cc41db --- /dev/null +++ b/File/File.cpp @@ -0,0 +1,128 @@ +#include +#include + +#include +#include + + + +using ProFUSE::Exception; +using ProFUSE::POSIXException; + + +File::File() +{ + _fd = -1; +} + +File::File(int fd) +{ + _fd = fd; +} + +File::File(File& f) +{ + _fd = f._fd; + f._fd = -1; +} + +File::File(const char *name, int flags, const std::nothrow_t&) +{ + _fd = ::open(name, flags); +} + + +File::File(const char *name, int flags, mode_t mode, const std::nothrow_t&) +{ + _fd = ::open(name, flags, mode); +} + +File::File(const char *name, FileFlags flags, const std::nothrow_t&) +{ + _fd = ::open(name, flags == ReadOnly ? O_RDONLY : O_RDWR); +} + +File::File(const char *name, int flags) +{ + #undef __METHOD__ + #define __METHOD__ "File::File" + + _fd = ::open(name, flags); + if (_fd < 0) + throw POSIXException( __METHOD__ ": open", errno); +} + +File::File(const char *name, int flags, mode_t mode) +{ +#undef __METHOD__ +#define __METHOD__ "File::File" + + _fd = ::open(name, flags, mode); + if (_fd < 0) + throw POSIXException( __METHOD__ ": open", errno); +} + + +File::File(const char *name, FileFlags flags) +{ +#undef __METHOD__ +#define __METHOD__ "File::File" + + _fd = ::open(name, flags == ReadOnly ? O_RDONLY : O_RDWR); + if (_fd < 0) + throw POSIXException( __METHOD__ ": open", errno); +} + + +File::~File() +{ + close(); +} + +int File::release() +{ + int tmp = _fd; + _fd = -1; + return tmp; +} + +void File::close() +{ + #undef __METHOD__ + #define __METHOD__ "File::close" + + if (_fd >= 0) + { + ::close(_fd); + _fd = -1; + + // destructor shouldn't throw. + /* + if (::close(fd) != 0) + throw POSIXException(__METHOD__ ": close", errno); + */ + } +} + + +void File::adopt(File &f) +{ + if (&f == this) return; + + close(); + _fd = f._fd; + f._fd = -1; +} + +void File::adopt(int fd) +{ + if (fd == _fd) return; + close(); + _fd = fd; +} + + +void File::swap(File &f) +{ + std::swap(_fd, f._fd); +} diff --git a/File/File.h b/File/File.h new file mode 100644 index 0000000..c926c3a --- /dev/null +++ b/File/File.h @@ -0,0 +1,58 @@ +#ifndef __FILE_H__ +#define __FILE_H__ + +#include + +#include +#include +#include + + + +class File { + + public: + + enum FileFlags { + ReadOnly = 1, + ReadWrite = 2 + }; + + File(); + File(File &); + File(int fd); + + File(const char *name, int flags); + File(const char *name, int flags, mode_t mode); + File(const char *name, FileFlags flags); + + File(const char *name, int flags, const std::nothrow_t &); + File(const char *name, int flags, mode_t mode, const std::nothrow_t &); + File(const char *name, FileFlags flags, const std::nothrow_t &); + + ~File(); + + bool isValid() const + { + return _fd >= 0; + } + + int fd() const { return _fd; } + + int release(); + + void close(); + + void adopt(File &f); + void adopt(int fd); + + void swap(File &f); + + private: + + // could call dup() or something. + File& operator=(const File &f); + int _fd; +}; + +#endif diff --git a/File/MappedFile.cpp b/File/MappedFile.cpp new file mode 100644 index 0000000..2b8eb91 --- /dev/null +++ b/File/MappedFile.cpp @@ -0,0 +1,187 @@ +#include +#include + +#include + +#include +#include + + +using ProFUSE::POSIXException; + +MappedFile::MappedFile() +{ + _length = -1; + _address = MAP_FAILED; + _readOnly = true; +} + +MappedFile::MappedFile(MappedFile &mf) +{ + _address = mf._address; + _length = mf._length; + _readOnly = mf._readOnly; + + mf._address = MAP_FAILED; + mf._length = -1; + mf._readOnly = true; +} + +MappedFile::MappedFile(const File &f, File::FileFlags flags, size_t size) +{ + _length = -1; + _address = MAP_FAILED; + _readOnly = true; + + init(f, flags == File::ReadOnly, size); +} + + +MappedFile::MappedFile(const char *name, File::FileFlags flags) +{ + File f(name, flags); + + _length = -1; + _address = MAP_FAILED; + _readOnly = true; + + init(f, flags == File::ReadOnly, 0); + +} + + +MappedFile::MappedFile(const char *name, File::FileFlags flags, const std::nothrow_t ¬hrow) +{ + File f(name, flags, nothrow); + + _length = -1; + _address = MAP_FAILED; + _readOnly = true; + + if (f.isValid()) + init(f, flags == File::ReadOnly, 0); +} + + +MappedFile::~MappedFile() +{ + close(); +} + + + +void MappedFile::init(const File &f, bool readOnly, size_t size) +{ +#undef __METHOD__ +#define __METHOD__ "MappedFile::init" + + struct stat st; + int prot = readOnly ? PROT_READ : PROT_READ | PROT_WRITE; + int flags = MAP_FILE | MAP_SHARED; + + // close enough + if (f.fd() < 0) + throw POSIXException( __METHOD__, EBADF); + + + if (!size) + { + if (::fstat(f.fd(), &st) != 0) + throw POSIXException(__METHOD__ ": fstat", errno); + + if (!S_ISREG(st.st_mode)) + throw POSIXException(__METHOD__, ENODEV); + + size = st.st_size; + } + + _length = size; + _address = ::mmap(0, _length, prot, flags, f.fd(), 0); + + if (_address == MAP_FAILED) + throw POSIXException(__METHOD__ ": mmap", errno); + + _readOnly = readOnly; +} + + + +void MappedFile::close() +{ + #undef __METHOD__ + #define __METHOD__ "MappedFile::close" + + if (_address != MAP_FAILED) + { + /* + void *address = _address; + size_t length = _length; + */ + + ::munmap(_address, _length); + + _address = MAP_FAILED; + _length = -1; + _readOnly = true; + + // destructor shouldn't throw. + /* + if (::munmap(address, length) != 0) + throw POSIXException(__METHOD__ ": munmap", errno); + */ + } +} + +void MappedFile::sync() +{ + #undef __METHOD__ + #define __METHOD__ "MappedFile::sync" + + if (_address != MAP_FAILED) + { + if (::msync(_address, _length, MS_SYNC) != 0) + throw POSIXException(__METHOD__ ": msync", errno); + } +} + +void MappedFile::adopt(MappedFile &mf) +{ + close(); + _address = mf._address; + _length = mf._length; + _readOnly = mf._readOnly; + + mf._address = MAP_FAILED; + mf._length = -1; + mf._readOnly = true; +} + +void MappedFile::swap(MappedFile &mf) +{ + std::swap(_address, mf._address); + std::swap(_length, mf._length); + std::swap(_readOnly, mf._readOnly); +} + + +MappedFile *MappedFile::Create(const char *name, size_t size) +{ +#undef __METHOD__ +#define __METHOD__ "MappedFile::Create" + + File fd(::open(name, O_CREAT | O_TRUNC | O_RDWR, 0644)); + + if (!fd.isValid()) + { + throw POSIXException(__METHOD__ ": Unable to create file.", errno); + } + + // TODO -- is ftruncate portable? + if (::ftruncate(fd.fd(), size) < 0) + { + // TODO -- unlink? + throw POSIXException(__METHOD__ ": Unable to truncate file.", errno); + } + + return new MappedFile(fd, File::ReadWrite, size); +} \ No newline at end of file diff --git a/File/MappedFile.h b/File/MappedFile.h new file mode 100644 index 0000000..cec519d --- /dev/null +++ b/File/MappedFile.h @@ -0,0 +1,53 @@ +#ifndef __MAPPED_FILE_H__ +#define __MAPPED_FILE_H__ + + +#include +#include + +#include + +class File; + +class MappedFile { + public: + + MappedFile(); + MappedFile(MappedFile&); + MappedFile(const File &f, File::FileFlags flags, size_t size = -1); + MappedFile(const char *name, File::FileFlags flags); + MappedFile(const char *name, File::FileFlags flags, const std::nothrow_t ¬hrow); + + ~MappedFile(); + + + static MappedFile *Create(const char *name, size_t size); + + bool isValid() const + { + return _address != MAP_FAILED; + } + + void sync(); + void close(); + + void *address() const { return _address; } + size_t length() const { return _length; } + bool readOnly() const { return _readOnly; } + + void swap(MappedFile &); + void adopt(MappedFile &); + + private: + + MappedFile& operator=(MappedFile &); + + void init(const File &f, bool readOnly, size_t size); + + void *_address; + size_t _length; + bool _readOnly; +}; + + +#endif \ No newline at end of file