• Skip to content
  • Skip to link menu
KDE 4.6 API Reference
  • KDE API Reference
  • kdelibs
  • KDE Home
  • Contact Us
 

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 

KDECore

Skip menu "KDECore"
  • Main Page
  • Modules
  • Namespace List
  • Class Hierarchy
  • Alphabetical List
  • Class List
  • File List
  • Namespace Members
  • Class Members
  • Related Pages

kdelibs

Skip menu "kdelibs"
  • DNSSD
  • Interfaces
  •   KHexEdit
  •   KMediaPlayer
  •   KSpeech
  •   KTextEditor
  • Kate
  • kconf_update
  • KDE3Support
  •   KUnitTest
  • KDECore
  • KDED
  • KDEsu
  • KDEUI
  • KDEWebKit
  • KDocTools
  • KFile
  • KHTML
  • KImgIO
  • KInit
  • kio
  • KIOSlave
  • KJS
  •   KJS-API
  •   WTF
  • kjsembed
  • KNewStuff
  • KParts
  • KPty
  • Kross
  • KUnitConversion
  • KUtils
  • Nepomuk
  • Plasma
  • Solid
  • Sonnet
  • ThreadWeaver
Generated for kdelibs by doxygen 1.7.3
This website is maintained by Adriaan de Groot and Allen Winter.
KDE® and the K Desktop Environment® logo are registered trademarks of KDE e.V. | Legal