KDECore
kdirwatch_p.h
Go to the documentation of this file.
00001 /* Private Header for class of KDirWatchPrivate 00002 * 00003 * this separate header file is needed for MOC processing 00004 * because KDirWatchPrivate has signals and slots 00005 * 00006 * This file is part of the KDE libraries 00007 * Copyright (C) 1998 Sven Radej <sven@lisa.exp.univie.ac.at> 00008 * Copyright (C) 2006 Dirk Mueller <mueller@kde.org> 00009 * Copyright (C) 2007 Flavio Castelli <flavio.castelli@gmail.com> 00010 * Copyright (C) 2008 Jarosław Staniek <staniek@kde.org> 00011 * 00012 * This library is free software; you can redistribute it and/or 00013 * modify it under the terms of the GNU Library General Public 00014 * License version 2 as published by the Free Software Foundation. 00015 * 00016 * This library is distributed in the hope that it will be useful, 00017 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00018 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 00019 * Library General Public License for more details. 00020 * 00021 * You should have received a copy of the GNU Library General Public License 00022 * along with this library; see the file COPYING.LIB. If not, write to 00023 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, 00024 * Boston, MA 02110-1301, USA. 00025 */ 00026 00027 #ifndef KDIRWATCH_P_H 00028 #define KDIRWATCH_P_H 00029 00030 #include "io/config-kdirwatch.h" 00031 #include "kdirwatch.h" 00032 00033 #ifndef QT_NO_FILESYSTEMWATCHER 00034 #define HAVE_QFILESYSTEMWATCHER 00035 #endif 00036 00037 #include <QtCore/QList> 00038 #include <QtCore/QSet> 00039 #include <QtCore/QMap> 00040 #include <QtCore/QObject> 00041 #include <QtCore/QString> 00042 #include <QtCore/QTimer> 00043 class QFileSystemWatcher; 00044 class QSocketNotifier; 00045 00046 #ifdef HAVE_FAM 00047 #include <limits.h> 00048 #include <fam.h> 00049 #endif 00050 00051 #ifdef HAVE_SYS_INOTIFY_H 00052 #include <unistd.h> 00053 #include <fcntl.h> 00054 #include <sys/inotify.h> 00055 00056 #ifndef IN_DONT_FOLLOW 00057 #define IN_DONT_FOLLOW 0x02000000 00058 #endif 00059 00060 #ifndef IN_ONLYDIR 00061 #define IN_ONLYDIR 0x01000000 00062 #endif 00063 00064 #endif 00065 00066 #include <sys/time.h> 00067 #include <sys/param.h> // ino_t 00068 #include <ctime> 00069 00070 00071 #define invalid_ctime ((time_t)-1) 00072 00073 #ifdef HAVE_QFILESYSTEMWATCHER 00074 #include <QtCore/QFileSystemWatcher> 00075 00076 #if defined Q_WS_WIN 00077 /* Helper implemented as a workaround for limitation on Windows: 00078 * the maximum number of object handles is MAXIMUM_WAIT_OBJECTS (64) per thread. 00079 * 00080 * From http://msdn.microsoft.com/en-us/library/ms687025(VS.85).aspx 00081 * "To wait on more than MAXIMUM_WAIT_OBJECTS handles, create a thread to wait 00082 * on MAXIMUM_WAIT_OBJECTS handles, then wait on that thread plus the other handles. 00083 * Use this technique to break the handles into groups of MAXIMUM_WAIT_OBJECTS." 00084 * 00085 * QFileSystemWatcher is implemented as thread, so KFileSystemWatcher 00086 * allocates more QFileSystemWatcher instances on demand (and deallocates them later). 00087 */ 00088 class KFileSystemWatcher : public QObject 00089 { 00090 Q_OBJECT 00091 public: 00092 KFileSystemWatcher(); 00093 ~KFileSystemWatcher(); 00094 void addPath(const QString &file); 00095 void removePath(const QString &file); 00096 00097 Q_SIGNALS: 00098 void fileChanged(const QString &path); 00099 void directoryChanged(const QString &path); 00100 00101 private: 00102 QFileSystemWatcher* availableWatcher(); 00103 QFileSystemWatcher* m_recentWatcher; 00104 QList<QFileSystemWatcher*> m_watchers; 00105 QHash<QFileSystemWatcher*, uint> m_usedObjects; 00106 QHash<QString,QFileSystemWatcher*> m_paths; 00107 }; 00108 #else 00109 typedef QFileSystemWatcher KFileSystemWatcher; 00110 #endif 00111 #endif 00112 00113 /* KDirWatchPrivate is a singleton and does the watching 00114 * for every KDirWatch instance in the application. 00115 */ 00116 class KDirWatchPrivate : public QObject 00117 { 00118 Q_OBJECT 00119 public: 00120 00121 enum entryStatus { Normal = 0, NonExistent }; 00122 enum entryMode { UnknownMode = 0, StatMode, DNotifyMode, INotifyMode, FAMMode, QFSWatchMode }; 00123 enum { NoChange=0, Changed=1, Created=2, Deleted=4 }; 00124 00125 00126 struct Client { 00127 KDirWatch* instance; 00128 int count; 00129 // did the instance stop watching 00130 bool watchingStopped; 00131 // events blocked when stopped 00132 int pending; 00133 KDirWatch::WatchModes m_watchModes; 00134 }; 00135 00136 class Entry 00137 { 00138 public: 00139 // the last observed modification time 00140 time_t m_ctime; 00141 // the last observed link count 00142 int m_nlink; 00143 // last observed inode 00144 ino_t m_ino; 00145 entryStatus m_status; 00146 entryMode m_mode; 00147 bool isDir; 00148 // instances interested in events 00149 QList<Client *> m_clients; 00150 // nonexistent entries of this directory 00151 QList<Entry *> m_entries; 00152 QString path; 00153 00154 int msecLeft, freq; 00155 00156 QString parentDirectory() const; 00157 void addClient(KDirWatch*, KDirWatch::WatchModes); 00158 void removeClient(KDirWatch*); 00159 int clientCount() const; 00160 bool isValid() { return m_clients.count() || m_entries.count(); } 00161 00162 Entry* findSubEntry(const QString& path) const { 00163 Q_FOREACH(Entry* sub_entry, m_entries) { 00164 if (sub_entry->path == path) 00165 return sub_entry; 00166 } 00167 return 0; 00168 } 00169 00170 bool dirty; 00171 void propagate_dirty(); 00172 00173 QList<Client *> clientsForFileOrDir(const QString& tpath, bool* isDir) const; 00174 00175 #ifdef HAVE_FAM 00176 FAMRequest fr; 00177 #endif 00178 00179 #ifdef HAVE_SYS_INOTIFY_H 00180 int wd; 00181 // Creation and Deletion of files happens infrequently, so 00182 // can safely be reported as they occur. File changes i.e. those that emity "dirty()" can 00183 // happen many times per second, though, so maintain a list of files in this directory 00184 // that can be emitted and flushed at the next slotRescan(...). 00185 // This will be unused if the Entry is not a directory. 00186 QList<QString> m_pendingFileChanges; 00187 #endif 00188 }; 00189 00190 typedef QMap<QString,Entry> EntryMap; 00191 00192 KDirWatchPrivate(); 00193 ~KDirWatchPrivate(); 00194 00195 void resetList (KDirWatch*,bool); 00196 void useFreq(Entry* e, int newFreq); 00197 void addEntry(KDirWatch* instance,const QString& _path, Entry* sub_entry, 00198 bool isDir, KDirWatch::WatchModes watchModes = KDirWatch::WatchDirOnly); 00199 void removeEntry(KDirWatch*,const QString&, Entry* sub_entry); 00200 void removeEntry(KDirWatch*,Entry* e, Entry* sub_entry); 00201 bool stopEntryScan(KDirWatch*, Entry*); 00202 bool restartEntryScan(KDirWatch*, Entry*, bool ); 00203 void stopScan(KDirWatch*); 00204 void startScan(KDirWatch*, bool, bool); 00205 00206 void removeEntries(KDirWatch*); 00207 void statistics(); 00208 00209 void addWatch(Entry* entry); 00210 void removeWatch(Entry* entry); 00211 Entry* entry(const QString&); 00212 int scanEntry(Entry* e); 00213 void emitEvent(const Entry* e, int event, const QString &fileName = QString()); 00214 00215 // Memory management - delete when last KDirWatch gets deleted 00216 void ref() { m_ref++; } 00217 bool deref() { return ( --m_ref == 0 ); } 00218 00219 static bool isNoisyFile( const char *filename ); 00220 00221 public Q_SLOTS: 00222 void slotRescan(); 00223 void famEventReceived(); // for FAM 00224 void inotifyEventReceived(); // for inotify 00225 void slotRemoveDelayed(); 00226 void fswEventReceived(const QString &path); // for QFileSystemWatcher 00227 00228 public: 00229 QTimer timer; 00230 EntryMap m_mapEntries; 00231 00232 KDirWatch::Method m_preferredMethod, m_nfsPreferredMethod; 00233 int freq; 00234 int statEntries; 00235 int m_nfsPollInterval, m_PollInterval; 00236 int m_ref; 00237 bool useStat(Entry*); 00238 00239 // removeList is allowed to contain any entry at most once 00240 QSet<Entry *> removeList; 00241 bool delayRemove; 00242 00243 bool rescan_all; 00244 QTimer rescan_timer; 00245 00246 #ifdef HAVE_FAM 00247 QSocketNotifier *sn; 00248 FAMConnection fc; 00249 bool use_fam; 00250 00251 void checkFAMEvent(FAMEvent*); 00252 bool useFAM(Entry*); 00253 #endif 00254 00255 #ifdef HAVE_SYS_INOTIFY_H 00256 QSocketNotifier *mSn; 00257 bool supports_inotify; 00258 int m_inotify_fd; 00259 00260 bool useINotify(Entry*); 00261 #endif 00262 #ifdef HAVE_QFILESYSTEMWATCHER 00263 KFileSystemWatcher *fsWatcher; 00264 bool useQFSWatch(Entry* e); 00265 #endif 00266 00267 bool _isStopped; 00268 }; 00269 00270 QDebug operator<<(QDebug debug, const KDirWatchPrivate::Entry &entry); 00271 00272 #endif // KDIRWATCH_P_H 00273
KDE 4.6 API Reference