/* Private Header for class of KDirWatchPrivate * * this separate header file is needed for MOC processing * because KDirWatchPrivate has signals and slots * * This file is part of the KDE libraries * Copyright (C) 1998 Sven Radej * Copyright (C) 2006 Dirk Mueller * Copyright (C) 2007 Flavio Castelli * Copyright (C) 2008 Jarosław Staniek * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public * License version 2 as published by the Free Software Foundation. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Library General Public License for more details. * * You should have received a copy of the GNU Library General Public License * along with this library; see the file COPYING.LIB. If not, write to * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * Boston, MA 02110-1301, USA. */ #ifndef KDIRWATCH_P_H #define KDIRWATCH_P_H #include #include "kdirwatch.h" #ifndef QT_NO_FILESYSTEMWATCHER #define HAVE_QFILESYSTEMWATCHER #endif #include #include #include #include #include #include class QFileSystemWatcher; class QSocketNotifier; #ifdef HAVE_FAM #include #include #endif #ifdef HAVE_SYS_INOTIFY_H #include #include #include #ifndef IN_DONT_FOLLOW #define IN_DONT_FOLLOW 0x02000000 #endif #ifndef IN_ONLYDIR #define IN_ONLYDIR 0x01000000 #endif #endif #include #include // ino_t #include #define invalid_ctime ((time_t)-1) #ifdef HAVE_QFILESYSTEMWATCHER #include typedef QFileSystemWatcher KFileSystemWatcher; #endif /* KDirWatchPrivate is a singleton and does the watching * for every KDirWatch instance in the application. */ class KDirWatchPrivate : public QObject { Q_OBJECT public: enum entryStatus { Normal = 0, NonExistent }; enum entryMode { UnknownMode = 0, StatMode, DNotifyMode, INotifyMode, FAMMode, QFSWatchMode }; enum { NoChange=0, Changed=1, Created=2, Deleted=4 }; struct Client { KDirWatch* instance; int count; // did the instance stop watching bool watchingStopped; // events blocked when stopped int pending; KDirWatch::WatchModes m_watchModes; }; class Entry { public: // the last observed modification time time_t m_ctime; // the last observed link count int m_nlink; // last observed inode ino_t m_ino; entryStatus m_status; entryMode m_mode; bool isDir; // instances interested in events QList m_clients; // nonexistent entries of this directory QList m_entries; QString path; int msecLeft, freq; QString parentDirectory() const; void addClient(KDirWatch*, KDirWatch::WatchModes); void removeClient(KDirWatch*); int clientCount() const; bool isValid() { return m_clients.count() || m_entries.count(); } Entry* findSubEntry(const QString& path) const { Q_FOREACH(Entry* sub_entry, m_entries) { if (sub_entry->path == path) return sub_entry; } return 0; } bool dirty; void propagate_dirty(); QList clientsForFileOrDir(const QString& tpath, bool* isDir) const; QList inotifyClientsForFileOrDir(bool isDir) const; #ifdef HAVE_FAM FAMRequest fr; #endif #ifdef HAVE_SYS_INOTIFY_H int wd; // Creation and Deletion of files happens infrequently, so // can safely be reported as they occur. File changes i.e. those that emity "dirty()" can // happen many times per second, though, so maintain a list of files in this directory // that can be emitted and flushed at the next slotRescan(...). // This will be unused if the Entry is not a directory. QList m_pendingFileChanges; #endif }; typedef QMap EntryMap; KDirWatchPrivate(); ~KDirWatchPrivate(); void resetList (KDirWatch*,bool); void useFreq(Entry* e, int newFreq); void addEntry(KDirWatch* instance,const QString& _path, Entry* sub_entry, bool isDir, KDirWatch::WatchModes watchModes = KDirWatch::WatchDirOnly); bool removeEntry(KDirWatch*,const QString&, Entry* sub_entry); void removeEntry(KDirWatch*,Entry* e, Entry* sub_entry); bool stopEntryScan(KDirWatch*, Entry*); bool restartEntryScan(KDirWatch*, Entry*, bool ); void stopScan(KDirWatch*); void startScan(KDirWatch*, bool, bool); void removeEntries(KDirWatch*); void statistics(); void addWatch(Entry* entry); void removeWatch(Entry* entry); Entry* entry(const QString&); int scanEntry(Entry* e); void emitEvent(const Entry* e, int event, const QString &fileName = QString()); // Memory management - delete when last KDirWatch gets deleted void ref() { m_ref++; } bool deref() { return ( --m_ref == 0 ); } static bool isNoisyFile( const char *filename ); public Q_SLOTS: void slotRescan(); void famEventReceived(); // for FAM void inotifyEventReceived(); // for inotify void slotRemoveDelayed(); void fswEventReceived(const QString &path); // for QFileSystemWatcher public: QTimer timer; EntryMap m_mapEntries; KDirWatch::Method m_preferredMethod, m_nfsPreferredMethod; int freq; int statEntries; int m_nfsPollInterval, m_PollInterval; int m_ref; bool useStat(Entry*); // removeList is allowed to contain any entry at most once QSet removeList; bool delayRemove; bool rescan_all; QTimer rescan_timer; #ifdef HAVE_FAM QSocketNotifier *sn; FAMConnection fc; bool use_fam; void checkFAMEvent(FAMEvent*); bool useFAM(Entry*); #endif #ifdef HAVE_SYS_INOTIFY_H QSocketNotifier *mSn; bool supports_inotify; int m_inotify_fd; bool useINotify(Entry*); #endif #ifdef HAVE_QFILESYSTEMWATCHER KFileSystemWatcher *fsWatcher; bool useQFSWatch(Entry* e); #endif bool _isStopped; }; QDebug operator<<(QDebug debug, const KDirWatchPrivate::Entry &entry); #endif // KDIRWATCH_P_H