incron  0.5.10
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