introduce reference counting within temporary files

This commit is contained in:
Peter Hatina 2013-11-26 21:14:41 +01:00
parent 34e9c8ffb3
commit 41cfc9bace
5 changed files with 84 additions and 37 deletions

View File

@ -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<TypeTmpFile*>(
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<int>(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<TypeTmpFile*>(
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<int>(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<TypeTmpFile*>(tmp_file)->setModified();

View File

@ -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<const TypeTmpFile*>(&*it);

View File

@ -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();

View File

@ -16,39 +16,56 @@
* ***** END LICENSE BLOCK ***** */
#include <config.h>
#include <algorithm>
#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 &copy):
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;
}

View File

@ -18,6 +18,7 @@
#ifndef SMTPFS_TYPE_TMP_FILE_H
#define SMTPFS_TYPE_TMP_FILE_H
#include <set>
#include <string>
#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<int> 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<int> m_file_descriptors;
bool m_modified;
};