From 41cfc9bacee9d9dd1874c94df0420e8de2e46d97 Mon Sep 17 00:00:00 2001 From: Peter Hatina Date: Tue, 26 Nov 2013 21:14:41 +0100 Subject: [PATCH] introduce reference counting within temporary files --- src/simple-mtpfs-fuse.cpp | 49 +++++++++++++++++++++-------- src/simple-mtpfs-tmp-files-pool.cpp | 8 ++--- src/simple-mtpfs-tmp-files-pool.h | 5 +-- src/simple-mtpfs-type-tmp-file.cpp | 29 +++++++++++++---- src/simple-mtpfs-type-tmp-file.h | 30 +++++++++++------- 5 files changed, 84 insertions(+), 37 deletions(-) diff --git a/src/simple-mtpfs-fuse.cpp b/src/simple-mtpfs-fuse.cpp index 1d4c583..c6a9516 100644 --- a/src/simple-mtpfs-fuse.cpp +++ b/src/simple-mtpfs-fuse.cpp @@ -597,17 +597,34 @@ int SMTPFileSystem::open(const char *path, struct fuse_file_info *file_info) if (file_info->flags & O_WRONLY) file_info->flags |= O_TRUNC; - std::string tmp_file = m_tmp_files_pool.makeTmpPath(std::string(path)); - int rval = m_device.filePull(std::string(path), tmp_file); - if (rval != 0) - return -rval; + const std::string std_path(path); - int fd = ::open(tmp_file.c_str(), file_info->flags); - if (fd < 0) + TypeTmpFile *tmp_file = const_cast( + m_tmp_files_pool.getFile(std_path)); + + std::string tmp_path; + if (tmp_file) { + tmp_path = tmp_file->pathTmp(); + } else { + tmp_path = m_tmp_files_pool.makeTmpPath(std_path); + + int rval = m_device.filePull(std_path, tmp_path); + if (rval != 0) + return -rval; + } + + int fd = ::open(tmp_path.c_str(), file_info->flags); + if (fd < 0) { + ::unlink(tmp_path.c_str()); return -errno; + } file_info->fh = fd; - m_tmp_files_pool.addFile(TypeTmpFile(std::string(path), tmp_file, fd)); + + if (tmp_file) + tmp_file->addFileDescriptor(fd); + else + m_tmp_files_pool.addFile(TypeTmpFile(std_path, tmp_path, fd)); return 0; } @@ -624,7 +641,7 @@ int SMTPFileSystem::read(const char *path, char *buf, size_t size, int SMTPFileSystem::write(const char *path, const char *buf, size_t size, off_t offset, struct fuse_file_info *file_info) { - const TypeTmpFile *tmp_file = m_tmp_files_pool.getFile(static_cast(file_info->fh)); + const TypeTmpFile *tmp_file = m_tmp_files_pool.getFile(std::string(path)); if (!tmp_file) return -EINVAL; @@ -642,15 +659,21 @@ int SMTPFileSystem::release(const char *path, struct fuse_file_info *file_info) if (rval < 0) return -errno; - if (std::string(path) == std::string("-")) + const std::string std_path(path); + if (std_path == std::string("-")) + return 0; + + TypeTmpFile *tmp_file = const_cast( + m_tmp_files_pool.getFile(std_path)); + tmp_file->removeFileDescriptor(file_info->fh); + if (tmp_file->refcnt() != 0) return 0; - const TypeTmpFile *tmp_file = m_tmp_files_pool.getFile(static_cast(file_info->fh)); const bool modif = tmp_file->isModified(); const std::string tmp_path = tmp_file->pathTmp(); - m_tmp_files_pool.removeFile(tmp_file->fileDescriptor()); + m_tmp_files_pool.removeFile(std_path); if (modif) { - int rval = m_device.filePush(tmp_path, std::string(path)); + rval = m_device.filePush(tmp_path, std_path); if (rval != 0) { ::unlink(tmp_path.c_str()); return -rval; @@ -747,7 +770,7 @@ int SMTPFileSystem::fsyncdir(const char *path, int datasync, int SMTPFileSystem::ftruncate(const char *path, off_t offset, struct fuse_file_info *file_info) { - const TypeTmpFile *tmp_file = m_tmp_files_pool.getFile(file_info->fh); + const TypeTmpFile *tmp_file = m_tmp_files_pool.getFile(std::string(path)); if (::ftruncate(file_info->fh, offset) != 0) return -errno; const_cast(tmp_file)->setModified(); diff --git a/src/simple-mtpfs-tmp-files-pool.cpp b/src/simple-mtpfs-tmp-files-pool.cpp index 3d391bd..bb179c9 100644 --- a/src/simple-mtpfs-tmp-files-pool.cpp +++ b/src/simple-mtpfs-tmp-files-pool.cpp @@ -32,17 +32,17 @@ TmpFilesPool::~TmpFilesPool() { } -void TmpFilesPool::removeFile(int desc) +void TmpFilesPool::removeFile(const std::string &path) { - auto it = std::find(m_pool.begin(), m_pool.end(), desc); + auto it = std::find(m_pool.begin(), m_pool.end(), path); if (it == m_pool.end()) return; m_pool.erase(it); } -const TypeTmpFile *TmpFilesPool::getFile(int desc) const +const TypeTmpFile *TmpFilesPool::getFile(const std::string &path) const { - auto it = std::find(m_pool.begin(), m_pool.end(), desc); + auto it = std::find(m_pool.begin(), m_pool.end(), path); if (it == m_pool.end()) return nullptr; return static_cast(&*it); diff --git a/src/simple-mtpfs-tmp-files-pool.h b/src/simple-mtpfs-tmp-files-pool.h index f880208..a6ae4a2 100644 --- a/src/simple-mtpfs-tmp-files-pool.h +++ b/src/simple-mtpfs-tmp-files-pool.h @@ -32,9 +32,10 @@ public: void setTmpDir(const std::string &tmp_dir) { m_tmp_dir = tmp_dir; } void addFile(const TypeTmpFile &tmp) { m_pool.insert(tmp); } - void removeFile(int desc); + void removeFile(const std::string &path); bool empty() const { return m_pool.size(); } - const TypeTmpFile *getFile(int desc) const; + + const TypeTmpFile *getFile(const std::string &path) const; std::string makeTmpPath(const std::string &path_device) const; bool createTmpDir(); diff --git a/src/simple-mtpfs-type-tmp-file.cpp b/src/simple-mtpfs-type-tmp-file.cpp index faa1764..8509055 100644 --- a/src/simple-mtpfs-type-tmp-file.cpp +++ b/src/simple-mtpfs-type-tmp-file.cpp @@ -16,39 +16,56 @@ * ***** END LICENSE BLOCK ***** */ #include +#include #include "simple-mtpfs-type-tmp-file.h" TypeTmpFile::TypeTmpFile(): m_path_device(), m_path_tmp(), - m_file_desc(0), + m_file_descriptors(), m_modified(false) { } TypeTmpFile::TypeTmpFile(const std::string &path_device, - const std::string &path_tmp, int file_desc, - bool modified): + const std::string &path_tmp, int file_desc, + bool modified): m_path_device(path_device), m_path_tmp(path_tmp), - m_file_desc(file_desc), m_modified(modified) { + m_file_descriptors.insert(file_desc); } TypeTmpFile::TypeTmpFile(const TypeTmpFile ©): m_path_device(copy.m_path_device), m_path_tmp(copy.m_path_tmp), - m_file_desc(copy.m_file_desc), + m_file_descriptors(copy.m_file_descriptors), m_modified(copy.m_modified) { } +bool TypeTmpFile::hasFileDescriptor(int fd) +{ + auto it = std::find(m_file_descriptors.begin(), + m_file_descriptors.end(), fd); + return it != m_file_descriptors.end(); +} + +void TypeTmpFile::removeFileDescriptor(int fd) +{ + auto it = std::find(m_file_descriptors.begin(), + m_file_descriptors.end(), fd); + if (it == m_file_descriptors.end()) + return; + m_file_descriptors.erase(it); +} + TypeTmpFile &TypeTmpFile::operator =(const TypeTmpFile &rhs) { m_path_device = rhs.m_path_device; m_path_tmp = rhs.m_path_tmp; - m_file_desc = rhs.m_file_desc; + m_file_descriptors = rhs.m_file_descriptors; m_modified = rhs.m_modified; return *this; } diff --git a/src/simple-mtpfs-type-tmp-file.h b/src/simple-mtpfs-type-tmp-file.h index 2ee2dc1..dded18a 100644 --- a/src/simple-mtpfs-type-tmp-file.h +++ b/src/simple-mtpfs-type-tmp-file.h @@ -18,6 +18,7 @@ #ifndef SMTPFS_TYPE_TMP_FILE_H #define SMTPFS_TYPE_TMP_FILE_H +#include #include #include "simple-mtpfs-type-file.h" #include "simple-mtpfs-log.h" @@ -30,36 +31,41 @@ public: TypeTmpFile(const std::string &path_device, const std::string &path_tmp, int file_desc, bool modified = false); - const std::string pathDevice() const { return m_path_device; } - const std::string pathTmp() const { return m_path_tmp; } - int fileDescriptor() const { return m_file_desc; } - bool isModified() const { return m_modified; } + std::string pathDevice() const { return m_path_device; } + std::string pathTmp() const { return m_path_tmp; } + bool isModified() const { return m_modified; } void setModified(bool modified = true) { m_modified = modified; } + std::set fileDescriptors() const { return m_file_descriptors; } + void addFileDescriptor(int fd) { m_file_descriptors.insert(fd); } + bool hasFileDescriptor(int fd); + void removeFileDescriptor(int fd); + int refcnt() const { return m_file_descriptors.size(); } + TypeTmpFile &operator =(const TypeTmpFile &rhs); + bool operator ==(const TypeTmpFile &rhs) const { - return m_file_desc == rhs.m_file_desc; + return m_path_device == rhs.m_path_device; } - bool operator ==(int desc) const + bool operator ==(const std::string &path) const { - return m_file_desc == desc; + return m_path_device == path; } bool operator <(const TypeTmpFile &rhs) const { - return m_file_desc < rhs.m_file_desc; + return m_path_device < rhs.m_path_device; } - bool operator <(int desc) const + bool operator <(const std::string &path) const { - return m_file_desc < desc; + return m_path_device < path; } - private: std::string m_path_device; std::string m_path_tmp; - int m_file_desc; + std::set m_file_descriptors; bool m_modified; };