Changeset 794


Ignore:
Timestamp:
Oct 14, 2010, 6:12:21 PM (15 years ago)
Author:
Dmitry A. Kuminov
Message:

Significantly improve the performance of directory iterators walking through directories with thousands of files on slow file systems with inefficient cache policies (closes #176) [based on patch by rudi].

Location:
trunk/src/corelib/io
Files:
3 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/corelib/io/qfsfileengine_iterator.cpp

    r651 r794  
    7272}
    7373
     74#ifndef Q_OS_OS2
    7475QFileInfo QFSFileEngineIterator::currentFileInfo() const
    7576{
    7677    return QAbstractFileEngineIterator::currentFileInfo();
    7778}
     79#endif
    7880
    7981QT_END_NAMESPACE
  • trunk/src/corelib/io/qfsfileengine_iterator_os2.cpp

    r716 r794  
    4242****************************************************************************/
    4343
     44// temporary, until struct dirent in kLIBC gets creation and access time fields
     45#define QT_OS2_USE_DOSFINDFIRST
     46
    4447#include "qplatformdefs.h"
    4548#include "qfsfileengine_iterator_p.h"
     
    4952#include <QtCore/qvariant.h>
    5053
     54#ifndef QT_OS2_USE_DOSFINDFIRST
    5155#include <dirent.h>
    5256#include <unistd.h>
     57#else
     58#include <QtCore/qdatetime.h>
     59#include "qfsfileengine.h"
     60#include "qfileinfo_p.h"
     61#endif
    5362
    5463#ifndef QT_NO_FSFILEENGINE
    5564
    5665QT_BEGIN_NAMESPACE
     66
     67#ifndef QT_OS2_USE_DOSFINDFIRST
    5768
    5869class QFSFileEngineIteratorPlatformSpecificData
     
    7687};
    7788
     89#else // !QT_OS2_USE_DOSFINDFIRST
     90
     91class QFSFileEngineIteratorPlatformSpecificData : public QFileInfo
     92{
     93public:
     94    inline QFSFileEngineIteratorPlatformSpecificData()
     95        : done(false), hdir(HDIR_CREATE)
     96    {
     97        memset(&findBuf, 0, sizeof(findBuf));
     98    }
     99
     100    static QDateTime convertFileDateTime(FDATE fdate, FTIME ftime);
     101    void updateFileInfo(const QString &path, FILEFINDBUF3L *ffb);
     102    void resetFileInfo() { d_ptr->reset(); }
     103
     104    bool done;
     105    HDIR hdir;
     106    FILEFINDBUF3L findBuf;
     107};
     108
     109#endif // !QT_OS2_USE_DOSFINDFIRST
     110
    78111void QFSFileEngineIterator::advance()
    79112{
     113#ifndef QT_OS2_USE_DOSFINDFIRST
     114
    80115    currentEntry = platform->dirEntry ? QFile::decodeName(QByteArray(platform->dirEntry->d_name)) : QString();
    81116
     
    99134#endif
    100135    }
     136
     137#else // !QT_OS2_USE_DOSFINDFIRST
     138
     139    if (platform->hdir == HDIR_CREATE) {
     140        platform->resetFileInfo();
     141        currentEntry.clear();
     142        return;
     143    }
     144
     145    // set QFileInfo from find buffer
     146    platform->updateFileInfo(path(), &platform->findBuf);
     147    currentEntry = platform->fileName();
     148
     149    ULONG count = 1;
     150    if (DosFindNext(platform->hdir, &platform->findBuf,
     151                    sizeof(platform->findBuf), &count) != NO_ERROR) {
     152        DosFindClose(platform->hdir);
     153        platform->hdir = HDIR_CREATE;
     154        platform->done = true;
     155    }
     156
     157#endif // !QT_OS2_USE_DOSFINDFIRST
    101158}
    102159
     
    108165void QFSFileEngineIterator::deletePlatformSpecifics()
    109166{
     167#ifndef QT_OS2_USE_DOSFINDFIRST
     168
    110169    if (platform->dir) {
    111170        ::closedir(platform->dir);
     
    115174#endif
    116175    }
     176
     177#else // !QT_OS2_USE_DOSFINDFIRST
     178
     179    if (platform->hdir != HDIR_CREATE)
     180        DosFindClose(platform->hdir);
     181
     182#endif // !QT_OS2_USE_DOSFINDFIRST
     183
    117184    delete platform;
    118185    platform = 0;
     
    121188bool QFSFileEngineIterator::hasNext() const
    122189{
     190#ifndef QT_OS2_USE_DOSFINDFIRST
    123191    if (!platform->done && !platform->dir) {
     192#else
     193    if (!platform->done && platform->hdir == HDIR_CREATE) {
     194#endif
    124195        QFSFileEngineIterator *that = const_cast<QFSFileEngineIterator *>(this);
    125196        QString path = that->path();
     
    149220            }
    150221        }
     222
    151223        if (arc == ERROR_NOT_READY || arc == ERROR_DISK_CHANGE ||
    152224            arc == ERROR_SECTOR_NOT_FOUND || arc == ERROR_INVALID_DRIVE) {
    153             that->platform->dir = 0;
    154225            that->platform->done = true;
     226#ifndef QT_OS2_USE_DOSFINDFIRST
    155227        } else if ((that->platform->dir = ::opendir(QFile::encodeName(path).data())) == 0) {
    156228            that->platform->done = true;
     
    163235            that->platform->mt_file = (dirent *)new char[maxPathName];
    164236#endif
    165 
    166237            that->advance();
     238#else // !QT_OS2_USE_DOSFINDFIRST
     239        } else {
     240            ULONG count = 1;
     241            if (DosFindFirst(QFile::encodeName(path).append('*').constData(),
     242                             &that->platform->hdir,
     243                             FILE_NORMAL | FILE_READONLY | FILE_HIDDEN |
     244                             FILE_SYSTEM | FILE_DIRECTORY | FILE_ARCHIVED,
     245                             &that->platform->findBuf, sizeof(that->platform->findBuf),
     246                             &count, FIL_STANDARDL) != NO_ERROR) {
     247                that->platform->done = true;
     248            } else {
     249                that->platform->resetFileInfo();
     250                that->currentEntry.clear();
     251            }
     252#endif // !QT_OS2_USE_DOSFINDFIRST
    167253        }
    168254    }
     255
    169256    return !platform->done;
    170257}
    171258
     259QFileInfo QFSFileEngineIterator::currentFileInfo() const
     260{
     261#ifndef QT_OS2_USE_DOSFINDFIRST
     262    return QAbstractFileEngineIterator::currentFileInfo();
     263#else
     264    // return a copy of our cached file info
     265    return *platform;
     266#endif
     267}
     268
     269#ifdef QT_OS2_USE_DOSFINDFIRST
     270
     271//static
     272QDateTime QFSFileEngineIteratorPlatformSpecificData::convertFileDateTime(FDATE fdate,
     273                                                                         FTIME ftime)
     274{
     275    QDateTime dt;
     276
     277    dt.setDate(QDate(fdate.year + 1980, fdate.month, fdate.day));
     278    dt.setTime(QTime(ftime.hours, ftime.minutes, ftime.twosecs * 2));
     279
     280    return dt;
     281}
     282
     283void QFSFileEngineIteratorPlatformSpecificData::updateFileInfo(const QString &path,
     284                                                               FILEFINDBUF3L *ffb)
     285{
     286    QString fileName = path;
     287    if (!fileName.endsWith(QLatin1Char('/')))
     288        fileName.append(QLatin1Char('/'));
     289    fileName.append(QFile::decodeName(QByteArray(ffb->achName)));
     290    d_ptr->initFileEngine(fileName);
     291
     292    d_ptr->data->fileFlags = QAbstractFileEngine::ExistsFlag    |
     293                             QAbstractFileEngine::LocalDiskFlag |
     294                             QAbstractFileEngine::ReadOwnerPerm |
     295                             QAbstractFileEngine::ReadUserPerm  |
     296                             QAbstractFileEngine::ReadGroupPerm |
     297                             QAbstractFileEngine::ReadOtherPerm;
     298
     299    if ((ffb->attrFile & FILE_READONLY) == 0) {
     300        d_ptr->data->fileFlags |= QAbstractFileEngine::WriteOwnerPerm |
     301                                  QAbstractFileEngine::WriteUserPerm  |
     302                                  QAbstractFileEngine::WriteGroupPerm |
     303                                  QAbstractFileEngine::WriteOtherPerm;
     304    }
     305
     306    if (ffb->attrFile & FILE_DIRECTORY)
     307        d_ptr->data->fileFlags |= QAbstractFileEngine::DirectoryType;
     308    else
     309        d_ptr->data->fileFlags |= QAbstractFileEngine::FileType;
     310
     311    if (ffb->attrFile & FILE_HIDDEN)
     312        d_ptr->data->fileFlags |= QAbstractFileEngine::HiddenFlag;
     313
     314    d_ptr->data->fileTimes[QAbstractFileEngine::CreationTime] =
     315            convertFileDateTime(ffb->fdateCreation, ffb->ftimeCreation);
     316
     317    d_ptr->data->fileTimes[QAbstractFileEngine::ModificationTime] =
     318            convertFileDateTime(ffb->fdateLastWrite, ffb->ftimeLastWrite);
     319
     320    d_ptr->data->fileTimes[QAbstractFileEngine::AccessTime] =
     321            convertFileDateTime(ffb->fdateLastAccess, ffb->ftimeLastAccess);
     322
     323    d_ptr->data->fileSize = ffb->cbFile;
     324
     325    // mark fields as "cached" and "present"
     326    d_ptr->data->cachedFlags  = QFileInfoPrivate::CachedSize |
     327                                QFileInfoPrivate::CachedFileFlags |
     328                                QFileInfoPrivate::CachedLinkTypeFlag |
     329                                QFileInfoPrivate::CachedBundleTypeFlag |
     330                                QFileInfoPrivate::CachedMTime |
     331                                QFileInfoPrivate::CachedCTime |
     332                                QFileInfoPrivate::CachedATime;
     333    d_ptr->data->cache_enabled = 1;
     334}
     335
     336#endif // QT_OS2_USE_DOSFINDFIRST
     337
    172338QT_END_NAMESPACE
    173339
  • trunk/src/corelib/io/qfsfileengine_os2.cpp

    r793 r794  
    4242****************************************************************************/
    4343
     44// temporary, until struct dirent in kLIBC gets creation and access time fields
     45#define QT_OS2_USE_DOSFINDFIRST
     46
    4447#include "qplatformdefs.h"
    4548#include "qabstractfileengine.h"
     
    661664            is_link = false;        // drive/share names are never symlinks
    662665        } else {
     666#ifdef QT_OS2_USE_DOSFINDFIRST
     667            is_link = false;
     668#else
    663669            QT_STATBUF st;          // don't clobber our main one
    664670            that->is_link = (QT_LSTAT(nativeFilePath.constData(), &st) == 0) ?
    665671                            S_ISLNK(st.st_mode) : false;
     672#endif
    666673        }
    667674    }
Note: See TracChangeset for help on using the changeset viewer.