Speed up QFile::copy on Linux file systems that support cloning
Originally inherited from Btrfs, recent Linux kernels have a system call that allows cloning the contents of a file from another one if the underlying file system supports it. Change-Id: I9df66b65faef99f3bbed8a88fb6b6009baeef32e Reviewed-by: Thiago Macieira <thiago.macieira@intel.com>
This commit is contained in:
parent
f971a0d65c
commit
d5078161aa
@ -831,6 +831,19 @@ bool QAbstractFileEngine::unmap(uchar *address)
|
||||
return extension(UnMapExtension, &options);
|
||||
}
|
||||
|
||||
/*!
|
||||
\since 5.10
|
||||
|
||||
Copies the contents from the file specified by \a sourceHandle to this file
|
||||
by cloning it.
|
||||
Returns \c true on success; otherwise, \c false is returned.
|
||||
*/
|
||||
bool QAbstractFileEngine::clone(int sourceHandle)
|
||||
{
|
||||
Q_UNUSED(sourceHandle);
|
||||
return false;
|
||||
}
|
||||
|
||||
/*!
|
||||
\since 4.3
|
||||
\class QAbstractFileEngineIterator
|
||||
|
@ -147,6 +147,7 @@ public:
|
||||
virtual QDateTime fileTime(FileTime time) const;
|
||||
virtual void setFileName(const QString &file);
|
||||
virtual int handle() const;
|
||||
virtual bool clone(int sourceHandle);
|
||||
bool atEnd() const;
|
||||
uchar *map(qint64 offset, qint64 size, QFile::MemoryMapFlags flags);
|
||||
bool unmap(uchar *ptr);
|
||||
|
@ -42,6 +42,7 @@
|
||||
#include "qfile.h"
|
||||
#include "qfsfileengine_p.h"
|
||||
#include "qtemporaryfile.h"
|
||||
#include "qtemporaryfile_p.h"
|
||||
#include "qlist.h"
|
||||
#include "qfileinfo.h"
|
||||
#include "private/qiodevice_p.h"
|
||||
@ -790,25 +791,27 @@ QFile::copy(const QString &newName)
|
||||
close();
|
||||
d->setError(QFile::CopyError, tr("Cannot open for output"));
|
||||
} else {
|
||||
char block[4096];
|
||||
qint64 totalRead = 0;
|
||||
while(!atEnd()) {
|
||||
qint64 in = read(block, sizeof(block));
|
||||
if (in <= 0)
|
||||
break;
|
||||
totalRead += in;
|
||||
if(in != out.write(block, in)) {
|
||||
close();
|
||||
d->setError(QFile::CopyError, tr("Failure to write block"));
|
||||
error = true;
|
||||
break;
|
||||
if (!out.d_func()->engine()->clone(d->engine()->handle())) {
|
||||
char block[4096];
|
||||
qint64 totalRead = 0;
|
||||
while (!atEnd()) {
|
||||
qint64 in = read(block, sizeof(block));
|
||||
if (in <= 0)
|
||||
break;
|
||||
totalRead += in;
|
||||
if (in != out.write(block, in)) {
|
||||
close();
|
||||
d->setError(QFile::CopyError, tr("Failure to write block"));
|
||||
error = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (totalRead != size()) {
|
||||
// Unable to read from the source. The error string is
|
||||
// already set from read().
|
||||
error = true;
|
||||
if (totalRead != size()) {
|
||||
// Unable to read from the source. The error string is
|
||||
// already set from read().
|
||||
error = true;
|
||||
}
|
||||
}
|
||||
if (!error && !out.rename(newName)) {
|
||||
error = true;
|
||||
|
@ -108,6 +108,7 @@ public:
|
||||
qint64 read(char *data, qint64 maxlen) Q_DECL_OVERRIDE;
|
||||
qint64 readLine(char *data, qint64 maxlen) Q_DECL_OVERRIDE;
|
||||
qint64 write(const char *data, qint64 len) Q_DECL_OVERRIDE;
|
||||
bool clone(int sourceHandle) override;
|
||||
|
||||
bool extension(Extension extension, const ExtensionOption *option = 0, ExtensionReturn *output = 0) Q_DECL_OVERRIDE;
|
||||
bool supportsExtension(Extension extension) const Q_DECL_OVERRIDE;
|
||||
|
@ -780,6 +780,23 @@ bool QFSFileEnginePrivate::unmap(uchar *ptr)
|
||||
#endif
|
||||
}
|
||||
|
||||
/*!
|
||||
\reimp
|
||||
*/
|
||||
bool QFSFileEngine::clone(int sourceHandle)
|
||||
{
|
||||
#if defined(Q_OS_LINUX)
|
||||
Q_D(QFSFileEngine);
|
||||
# if !defined FICLONE
|
||||
# define FICLONE _IOW (0x94, 9, int)
|
||||
# endif
|
||||
return ::ioctl(d->fd, FICLONE, sourceHandle) == 0;
|
||||
#else
|
||||
Q_UNUSED(sourceHandle);
|
||||
return false;
|
||||
#endif
|
||||
}
|
||||
|
||||
QT_END_NAMESPACE
|
||||
|
||||
#endif // QT_NO_FSFILEENGINE
|
||||
|
@ -984,4 +984,13 @@ bool QFSFileEnginePrivate::unmap(uchar *ptr)
|
||||
return true;
|
||||
}
|
||||
|
||||
/*!
|
||||
\reimp
|
||||
*/
|
||||
bool QFSFileEngine::clone(int sourceHandle)
|
||||
{
|
||||
Q_UNUSED(sourceHandle);
|
||||
return false;
|
||||
}
|
||||
|
||||
QT_END_NAMESPACE
|
||||
|
@ -65,7 +65,7 @@ class QTemporaryFilePrivate : public QFilePrivate
|
||||
{
|
||||
Q_DECLARE_PUBLIC(QTemporaryFile)
|
||||
|
||||
protected:
|
||||
public:
|
||||
QTemporaryFilePrivate();
|
||||
explicit QTemporaryFilePrivate(const QString &templateNameIn);
|
||||
~QTemporaryFilePrivate();
|
||||
|
Loading…
x
Reference in New Issue
Block a user