introduce reference counting within temporary files
This commit is contained in:
parent
34e9c8ffb3
commit
41cfc9bace
|
@ -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();
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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 ©):
|
||||
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;
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
};
|
||||
|
||||
|
|
Loading…
Reference in New Issue