Added support for get/sendPartialObject
If the caps flags are enabled for both get and send of partial object this method is used instead of file push and pull. This makes many file operations much faster and is widely supported throughout mobile devices. We still use the tmp file, not for storing data but to keep a unique file handler for all the fuse file operations. No caching happens at the moment, we could cache in the tmp file and keep a table of offsets and sizes of the file that we already cached, however, using the kernel file system cache is much better.
This commit is contained in:
parent
e121556851
commit
2bcc4551e9
|
@ -596,11 +596,19 @@ int SMTPFileSystem::open(const char *path, struct fuse_file_info *file_info)
|
|||
} else {
|
||||
tmp_path = m_tmp_files_pool.makeTmpPath(std_path);
|
||||
|
||||
int rval = m_device.filePull(std_path, tmp_path);
|
||||
if (rval != 0)
|
||||
return -rval;
|
||||
// only copy the file if needed
|
||||
if (!hasPartialObjectSupport()) {
|
||||
int rval = m_device.filePull(std_path, tmp_path);
|
||||
if (rval != 0)
|
||||
return -rval;
|
||||
} else {
|
||||
int fd = ::creat(tmp_path.c_str(), S_IRUSR | S_IWUSR);
|
||||
::close(fd);
|
||||
}
|
||||
}
|
||||
|
||||
// we create the tmp file even if we can use partial get/send to
|
||||
// have a valid file descriptor
|
||||
int fd = ::open(tmp_path.c_str(), file_info->flags);
|
||||
if (fd < 0) {
|
||||
::unlink(tmp_path.c_str());
|
||||
|
@ -620,24 +628,38 @@ int SMTPFileSystem::open(const char *path, struct fuse_file_info *file_info)
|
|||
int SMTPFileSystem::read(const char *path, char *buf, size_t size,
|
||||
off_t offset, struct fuse_file_info *file_info)
|
||||
{
|
||||
int rval = ::pread(file_info->fh, buf, size, offset);
|
||||
if (rval < 0)
|
||||
return -errno;
|
||||
int rval = 0;
|
||||
if (hasPartialObjectSupport()) {
|
||||
const std::string std_path(path);
|
||||
rval = m_device.fileRead(std_path, buf, size, offset);
|
||||
} else {
|
||||
rval = ::pread(file_info->fh, buf, size, offset);
|
||||
if (rval < 0)
|
||||
return -errno;
|
||||
}
|
||||
|
||||
return rval;
|
||||
}
|
||||
|
||||
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(std::string(path));
|
||||
if (!tmp_file)
|
||||
return -EINVAL;
|
||||
int rval = 0;
|
||||
if (hasPartialObjectSupport()) {
|
||||
const std::string std_path(path);
|
||||
rval = m_device.fileWrite(std_path, buf, size, offset);
|
||||
} else {
|
||||
const TypeTmpFile *tmp_file = m_tmp_files_pool.getFile(std::string(path));
|
||||
if (!tmp_file)
|
||||
return -EINVAL;
|
||||
|
||||
int rval = ::pwrite(file_info->fh, buf, size, offset);
|
||||
if (rval < 0)
|
||||
return -errno;
|
||||
rval = ::pwrite(file_info->fh, buf, size, offset);
|
||||
if (rval < 0)
|
||||
return -errno;
|
||||
|
||||
const_cast<TypeTmpFile*>(tmp_file)->setModified();
|
||||
}
|
||||
|
||||
const_cast<TypeTmpFile*>(tmp_file)->setModified();
|
||||
return rval;
|
||||
}
|
||||
|
||||
|
@ -764,3 +786,9 @@ int SMTPFileSystem::ftruncate(const char *path, off_t offset,
|
|||
const_cast<TypeTmpFile*>(tmp_file)->setModified();
|
||||
return 0;
|
||||
}
|
||||
|
||||
bool SMTPFileSystem::hasPartialObjectSupport()
|
||||
{
|
||||
MTPDevice::Capabilities caps = m_device.getCapabilities();
|
||||
return (caps.canGetPartialObject() && caps.canSendPartialObject());
|
||||
}
|
||||
|
|
|
@ -104,6 +104,7 @@ public:
|
|||
int create(const char *path, mode_t mode, fuse_file_info *file_info);
|
||||
|
||||
private:
|
||||
bool hasPartialObjectSupport();
|
||||
|
||||
static std::unique_ptr<SMTPFileSystem> s_instance;
|
||||
struct fuse_args m_args;
|
||||
|
|
|
@ -467,6 +467,64 @@ int MTPDevice::rename(const std::string &oldpath, const std::string &newpath)
|
|||
#endif
|
||||
}
|
||||
|
||||
int MTPDevice::fileRead(const std::string &path, char *buf, size_t size,
|
||||
off_t offset)
|
||||
{
|
||||
const std::string path_basename(smtpfs_basename(path));
|
||||
const std::string path_dirname(smtpfs_dirname(path));
|
||||
const TypeDir *dir_parent = dirFetchContent(path_dirname);
|
||||
const TypeFile *file_to_fetch = dir_parent ?
|
||||
dir_parent->file(path_basename) : nullptr;
|
||||
if (!dir_parent) {
|
||||
logerr("Can not fetch '", path, "'.\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
if (!file_to_fetch) {
|
||||
logerr("No such file '", path, "'.\n");
|
||||
return -ENOENT;
|
||||
}
|
||||
|
||||
// all systems clear
|
||||
unsigned char *tmp_buf;
|
||||
unsigned int tmp_size;
|
||||
int rval = LIBMTP_GetPartialObject(m_device, file_to_fetch->id(),
|
||||
offset, size, &tmp_buf, &tmp_size);
|
||||
if (tmp_size > 0) {
|
||||
memcpy(buf, tmp_buf, tmp_size);
|
||||
free(tmp_buf);
|
||||
}
|
||||
|
||||
if (rval != 0)
|
||||
return -EIO;
|
||||
return tmp_size;
|
||||
}
|
||||
|
||||
int MTPDevice::fileWrite(const std::string &path, const char *buf, size_t size,
|
||||
off_t offset)
|
||||
{
|
||||
const std::string path_basename(smtpfs_basename(path));
|
||||
const std::string path_dirname(smtpfs_dirname(path));
|
||||
const TypeDir *dir_parent = dirFetchContent(path_dirname);
|
||||
const TypeFile *file_to_fetch = dir_parent ?
|
||||
dir_parent->file(path_basename) : nullptr;
|
||||
if (!dir_parent) {
|
||||
logerr("Can not fetch '", path, "'.\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
if (!file_to_fetch) {
|
||||
logerr("No such file '", path, "'.\n");
|
||||
return -ENOENT;
|
||||
}
|
||||
|
||||
// all systems clear
|
||||
int rval = LIBMTP_SendPartialObject(m_device, file_to_fetch->id(),
|
||||
offset, (unsigned char *) buf, size);
|
||||
|
||||
if (rval < 0)
|
||||
return -EIO;
|
||||
return size;
|
||||
}
|
||||
|
||||
int MTPDevice::filePull(const std::string &src, const std::string &dst)
|
||||
{
|
||||
const std::string src_basename(smtpfs_basename(src));
|
||||
|
|
|
@ -78,6 +78,8 @@ public:
|
|||
|
||||
int rename(const std::string &oldpath, const std::string &newpath);
|
||||
|
||||
int fileRead(const std::string &path, char *buf, size_t size, off_t offset);
|
||||
int fileWrite(const std::string &path, const char *buf, size_t size, off_t offset);
|
||||
int filePull(const std::string &src, const std::string &dst);
|
||||
int filePush(const std::string &src, const std::string &dst);
|
||||
int fileRemove(const std::string &path);
|
||||
|
|
Loading…
Reference in New Issue