incron 0.5.10

- Main Page
- Classes
- Files

- File List
- File Members

inotify-cxx.h
Go to the documentation of this file.

    00001
    00003
    00026 #ifndef _INOTIFYCXX_H_
    00027 #define _INOTIFYCXX_H_
    00028
    00029 #include <stdint.h>
    00030 #include <string>
    00031 #include <deque>
    00032 #include <map>
    00033
    00034 // Please ensure that the following headers take the right place
    00035 #include <sys/syscall.h>
    00036 #include <sys/inotify.h>
    00037
    00038 // Use this if syscalls not defined
    00039 #ifndef __NR_inotify_init
    00040 #include <sys/inotify-syscalls.h>
    00041 #endif // __NR_inotify_init
    00042
    00044 #define INOTIFY_EVENT_SIZE (sizeof(struct inotify_event))
    00045
    00047 #define INOTIFY_BUFLEN (1024 * (INOTIFY_EVENT_SIZE + 16))
    00048
    00050
    00053 #define IN_EXC_MSG(msg) (std::string(__PRETTY_FUNCTION__) + ": " + msg)
    00054
    00056 typedef enum
    00057 {
    00058   IN_MAX_EVENTS     = 0,
    00059   IN_MAX_INSTANCES  = 1,
    00060   IN_MAX_WATCHES    = 2
    00061 } InotifyCapability_t;
    00062
    00064
    00082 #ifdef INOTIFY_THREAD_SAFE
    00083
    00084 #include <pthread.h>
    00085
    00086 #define IN_LOCK_DECL mutable pthread_rwlock_t __m_lock;
    00087
    00088 #define IN_LOCK_INIT \
    00089   { \
    00090     pthread_rwlockattr_t attr; \
    00091     int res = 0; \
    00092     if ((res = pthread_rwlockattr_init(&attr)) != 0) \
    00093       throw InotifyException(IN_EXC_MSG("cannot initialize lock attributes"), res, this); \
    00094     if ((res = pthread_rwlockattr_setkind_np(&attr, PTHREAD_RWLOCK_PREFER_WRITER_NP)) != 0) \
    00095       throw InotifyException(IN_EXC_MSG("cannot set lock kind"), res, this); \
    00096     if ((res = pthread_rwlock_init(&__m_lock, &attr)) != 0) \
    00097       throw InotifyException(IN_EXC_MSG("cannot initialize lock"), res, this); \
    00098     pthread_rwlockattr_destroy(&attr); \
    00099   }
    00100
    00101 #define IN_LOCK_DONE pthread_rwlock_destroy(&__m_lock);
    00102
    00103 #define IN_READ_BEGIN \
    00104   { \
    00105     int res = pthread_rwlock_rdlock(&__m_lock); \
    00106     if (res != 0) \
    00107       throw InotifyException(IN_EXC_MSG("locking for reading failed"), res, (void*) this); \
    00108   }
    00109
    00110 #define IN_READ_END \
    00111   { \
    00112     int res = pthread_rwlock_unlock(&__m_lock); \
    00113     if (res != 0) \
    00114       throw InotifyException(IN_EXC_MSG("unlocking failed"), res, (void*) this); \
    00115   }
    00116
    00117 #define IN_READ_END_NOTHROW pthread_rwlock_unlock(&__m_lock);
    00118
    00119 #define IN_WRITE_BEGIN \
    00120   { \
    00121     int res = pthread_rwlock_wrlock(&__m_lock); \
    00122     if (res != 0) \
    00123       throw InotifyException(IN_EXC_MSG("locking for writing failed"), res, (void*) this); \
    00124   }
    00125
    00126 #define IN_WRITE_END IN_READ_END
    00127 #define IN_WRITE_END_NOTHROW IN_READ_END_NOTHROW
    00128
    00129 #else // INOTIFY_THREAD_SAFE
    00130
    00131 #define IN_LOCK_DECL
    00132 #define IN_LOCK_INIT
    00133 #define IN_LOCK_DONE
    00134 #define IN_READ_BEGIN
    00135 #define IN_READ_END
    00136 #define IN_READ_END_NOTHROW
    00137 #define IN_WRITE_BEGIN
    00138 #define IN_WRITE_END
    00139 #define IN_WRITE_END_NOTHROW
    00140
    00141 #endif // INOTIFY_THREAD_SAFE
    00142
    00143
    00144
    00145
    00146 // forward declaration
    00147 class InotifyWatch;
    00148 class Inotify;
    00149
    00150
    00152
    00160 class InotifyException
    00161 {
    00162 public:
    00164
    00169   InotifyException(const std::string& rMsg = "", int iErr = 0, void* pSrc = NULL)
    00170   : m_msg(rMsg),
    00171     m_err(iErr)
    00172   {
    00173     m_pSrc = pSrc;
    00174   }
    00175
    00177
    00180   inline const std::string& GetMessage() const
    00181   {
    00182     return m_msg;
    00183   }
    00184
    00186
    00191   inline int GetErrorNumber() const
    00192   {
    00193     return m_err;
    00194   }
    00195
    00197
    00200   inline void* GetSource() const
    00201   {
    00202     return m_pSrc;
    00203   }
    00204
    00205 protected:
    00206   std::string m_msg;
    00207   int m_err;
    00208   mutable void* m_pSrc;
    00209 };
    00210
    00211
    00213
    00221 class InotifyEvent
    00222 {
    00223 public:
    00225
    00228   InotifyEvent()
    00229   : m_uMask(0),
    00230     m_uCookie(0)
    00231   {
    00232     m_pWatch = NULL;
    00233   }
    00234
    00236
    00243   InotifyEvent(const struct inotify_event* pEvt, InotifyWatch* pWatch)
    00244   : m_uMask(0),
    00245     m_uCookie(0)
    00246   {
    00247     if (pEvt != NULL) {
    00248       m_uMask = (uint32_t) pEvt->mask;
    00249       m_uCookie = (uint32_t) pEvt->cookie;
    00250       if (pEvt->name != NULL) {
    00251         m_name = pEvt->len > 0
    00252             ? pEvt->name
    00253             : "";
    00254       }
    00255       m_pWatch = pWatch;
    00256     }
    00257     else {
    00258       m_pWatch = NULL;
    00259     }
    00260   }
    00261
    00263   ~InotifyEvent() {}
    00264
    00266
    00271   int32_t GetDescriptor() const;
    00272
    00274
    00279   inline uint32_t GetMask() const
    00280   {
    00281     return m_uMask;
    00282   }
    00283
    00285
    00290   inline static bool IsType(uint32_t uValue, uint32_t uType)
    00291   {
    00292     return ((uValue & uType) != 0) && ((~uValue & uType) == 0);
    00293   }
    00294
    00296
    00300   inline bool IsType(uint32_t uType) const
    00301   {
    00302     return IsType(m_uMask, uType);
    00303   }
    00304
    00306
    00309   inline uint32_t GetCookie() const
    00310   {
    00311     return m_uCookie;
    00312   }
    00313
    00315
    00318   inline uint32_t GetLength() const
    00319   {
    00320     return (uint32_t) m_name.length();
    00321   }
    00322
    00324
    00327   inline const std::string& GetName() const
    00328   {
    00329     return m_name;
    00330   }
    00331
    00333
    00336   inline void GetName(std::string& rName) const
    00337   {
    00338     rName = GetName();
    00339   }
    00340
    00342
    00345   inline InotifyWatch* GetWatch()
    00346   {
    00347     return m_pWatch;
    00348   }
    00349
    00351
    00355   static uint32_t GetMaskByName(const std::string& rName);
    00356
    00358
    00362   static void DumpTypes(uint32_t uValue, std::string& rStr);
    00363
    00365
    00368   void DumpTypes(std::string& rStr) const;
    00369
    00370 private:
    00371   uint32_t m_uMask;
    00372   uint32_t m_uCookie;
    00373   std::string m_name;
    00374   InotifyWatch* m_pWatch;
    00375 };
    00376
    00377
    00378
    00380
    00386 class InotifyWatch
    00387 {
    00388 public:
    00390
    00398   InotifyWatch(const std::string& rPath, int32_t uMask, bool fEnabled = true)
    00399   : m_path(rPath),
    00400     m_uMask(uMask),
    00401     m_wd((int32_t) -1),
    00402     m_fEnabled(fEnabled)
    00403   {
    00404     IN_LOCK_INIT
    00405   }
    00406
    00408   ~InotifyWatch()
    00409   {
    00410     IN_LOCK_DONE
    00411   }
    00412
    00414
    00417   inline int32_t GetDescriptor() const
    00418   {
    00419     return m_wd;
    00420   }
    00421
    00423
    00426   inline const std::string& GetPath() const
    00427   {
    00428     return m_path;
    00429   }
    00430
    00432
    00435   inline uint32_t GetMask() const
    00436   {
    00437     return (uint32_t) m_uMask;
    00438   }
    00439
    00441
    00450   void SetMask(uint32_t uMask) throw (InotifyException);
    00451
    00453
    00456   inline Inotify* GetInotify()
    00457   {
    00458     return m_pInotify;
    00459   }
    00460
    00462
    00473   void SetEnabled(bool fEnabled) throw (InotifyException);
    00474
    00476
    00479   inline bool IsEnabled() const
    00480   {
    00481     return m_fEnabled;
    00482   }
    00483
    00485
    00494   inline bool IsRecursive() const
    00495   {
    00496     return false;
    00497   }
    00498
    00499 private:
    00500   friend class Inotify;
    00501
    00502   std::string m_path;
    00503   uint32_t m_uMask;
    00504   int32_t m_wd;
    00505   Inotify* m_pInotify;
    00506   bool m_fEnabled;
    00507
    00508   IN_LOCK_DECL
    00509
    00511
    00516   void __Disable();
    00517 };
    00518
    00519
    00521 typedef std::map<int32_t, InotifyWatch*> IN_WATCH_MAP;
    00522
    00524 typedef std::map<std::string, InotifyWatch*> IN_WP_MAP;
    00525
    00526
    00528
    00534 class Inotify
    00535 {
    00536 public:
    00538
    00544   Inotify() throw (InotifyException);
    00545
    00547
    00550   ~Inotify();
    00551
    00553   void Close();
    00554
    00556
    00561   void Add(InotifyWatch* pWatch) throw (InotifyException);
    00562
    00564
    00569   inline void Add(InotifyWatch& rWatch) throw (InotifyException)
    00570   {
    00571     Add(&rWatch);
    00572   }
    00573
    00575
    00582   void Remove(InotifyWatch* pWatch) throw (InotifyException);
    00583
    00585
    00592   inline void Remove(InotifyWatch& rWatch) throw (InotifyException)
    00593   {
    00594     Remove(&rWatch);
    00595   }
    00596
    00598   void RemoveAll();
    00599
    00601
    00609   inline size_t GetWatchCount() const
    00610   {
    00611     IN_READ_BEGIN
    00612     size_t n = (size_t) m_paths.size();
    00613     IN_READ_END
    00614     return n;
    00615   }
    00616
    00618
    00623   inline size_t GetEnabledCount() const
    00624   {
    00625     IN_READ_BEGIN
    00626     size_t n = (size_t) m_watches.size();
    00627     IN_READ_END
    00628     return n;
    00629   }
    00630
    00632
    00643   void WaitForEvents(bool fNoIntr = false) throw (InotifyException);
    00644
    00646
    00652   inline size_t GetEventCount()
    00653   {
    00654     IN_READ_BEGIN
    00655     size_t n = (size_t) m_events.size();
    00656     IN_READ_END
    00657     return n;
    00658   }
    00659
    00661
    00669   bool GetEvent(InotifyEvent* pEvt) throw (InotifyException);
    00670
    00672
    00679   bool GetEvent(InotifyEvent& rEvt) throw (InotifyException)
    00680   {
    00681     return GetEvent(&rEvt);
    00682   }
    00683
    00685
    00693   bool PeekEvent(InotifyEvent* pEvt) throw (InotifyException);
    00694
    00696
    00703   bool PeekEvent(InotifyEvent& rEvt) throw (InotifyException)
    00704   {
    00705     return PeekEvent(&rEvt);
    00706   }
    00707
    00709
    00715   InotifyWatch* FindWatch(int iDescriptor);
    00716
    00718
    00728    InotifyWatch* FindWatch(const std::string& rPath);
    00729
    00731
    00739   inline int GetDescriptor() const
    00740   {
    00741     return m_fd;
    00742   }
    00743
    00745
    00758   void SetNonBlock(bool fNonBlock) throw (InotifyException);
    00759
    00761
    00774   void SetCloseOnExec(bool fClOnEx) throw (InotifyException);
    00775
    00777
    00782   static uint32_t GetCapability(InotifyCapability_t cap) throw (InotifyException);
    00783
    00785
    00793   static void SetCapability(InotifyCapability_t cap, uint32_t val) throw (InotifyException);
    00794
    00796
    00800   inline static uint32_t GetMaxEvents() throw (InotifyException)
    00801   {
    00802     return GetCapability(IN_MAX_EVENTS);
    00803   }
    00804
    00806
    00814   inline static void SetMaxEvents(uint32_t val) throw (InotifyException)
    00815   {
    00816     SetCapability(IN_MAX_EVENTS, val);
    00817   }
    00818
    00820
    00827   inline static uint32_t GetMaxInstances() throw (InotifyException)
    00828   {
    00829     return GetCapability(IN_MAX_INSTANCES);
    00830   }
    00831
    00833
    00841   inline static void SetMaxInstances(uint32_t val) throw (InotifyException)
    00842   {
    00843     SetCapability(IN_MAX_INSTANCES, val);
    00844   }
    00845
    00847
    00854   inline static uint32_t GetMaxWatches() throw (InotifyException)
    00855   {
    00856     return GetCapability(IN_MAX_WATCHES);
    00857   }
    00858
    00860
    00868   inline static void SetMaxWatches(uint32_t val) throw (InotifyException)
    00869   {
    00870     SetCapability(IN_MAX_WATCHES, val);
    00871   }
    00872
    00873 private:
    00874   int m_fd;
    00875   IN_WATCH_MAP m_watches;
    00876   IN_WP_MAP m_paths;
    00877   unsigned char m_buf[INOTIFY_BUFLEN];
    00878   std::deque<InotifyEvent> m_events;
    00879
    00880   IN_LOCK_DECL
    00881
    00882   friend class InotifyWatch;
    00883
    00884   static std::string GetCapabilityPath(InotifyCapability_t cap) throw (InotifyException);
    00885 };
    00886
    00887
    00888 #endif //_INOTIFYCXX_H_
    00889