inotify-cxx.h

Go to the documentation of this file.
00001 
00003 
00026 #ifndef _INOTIFYCXX_H_
00027 #define _INOTIFYCXX_H_
00028 
00029 #include <string>
00030 #include <deque>
00031 #include <map>
00032 
00033 // Please ensure that the following headers take the right place
00034 #include <sys/syscall.h>
00035 #include <sys/inotify.h>
00036 
00037 // Use this if syscalls not defined
00038 #ifndef __NR_inotify_init
00039 #include <sys/inotify-syscalls.h>
00040 #endif // __NR_inotify_init
00041 
00043 #define INOTIFY_EVENT_SIZE (sizeof(struct inotify_event))
00044 
00046 #define INOTIFY_BUFLEN (1024 * (INOTIFY_EVENT_SIZE + 16))
00047 
00049 
00052 #define IN_EXC_MSG(msg) (std::string(__PRETTY_FUNCTION__) + ": " + msg)
00053 
00055 typedef enum
00056 {
00057   IN_MAX_EVENTS     = 0,  
00058   IN_MAX_INSTANCES  = 1,  
00059   IN_MAX_WATCHES    = 2   
00060 } InotifyCapability_t;
00061 
00063 
00081 #ifdef INOTIFY_THREAD_SAFE
00082 
00083 #include <pthread.h>
00084 
00085 #define IN_LOCK_DECL mutable pthread_rwlock_t __m_lock;
00086 
00087 #define IN_LOCK_INIT \
00088   { \
00089     pthread_rwlockattr_t attr; \
00090     int res = 0; \
00091     if ((res = pthread_rwlockattr_init(&attr)) != 0) \
00092       throw InotifyException(IN_EXC_MSG("cannot initialize lock attributes"), res, this); \
00093     if ((res = pthread_rwlockattr_setkind_np(&attr, PTHREAD_RWLOCK_PREFER_WRITER_NP)) != 0) \
00094       throw InotifyException(IN_EXC_MSG("cannot set lock kind"), res, this); \
00095     if ((res = pthread_rwlock_init(&__m_lock, &attr)) != 0) \
00096       throw InotifyException(IN_EXC_MSG("cannot initialize lock"), res, this); \
00097     pthread_rwlockattr_destroy(&attr); \
00098   }
00099  
00100 #define IN_LOCK_DONE pthread_rwlock_destroy(&__m_lock);
00101 
00102 #define IN_READ_BEGIN \
00103   { \
00104     int res = pthread_rwlock_rdlock(&__m_lock); \
00105     if (res != 0) \
00106       throw InotifyException(IN_EXC_MSG("locking for reading failed"), res, (void*) this); \
00107   }
00108   
00109 #define IN_READ_END \
00110   { \
00111     int res = pthread_rwlock_unlock(&__m_lock); \
00112     if (res != 0) \
00113       throw InotifyException(IN_EXC_MSG("unlocking failed"), res, (void*) this); \
00114   }
00115   
00116 #define IN_READ_END_NOTHROW pthread_rwlock_unlock(&__m_lock);
00117   
00118 #define IN_WRITE_BEGIN \
00119   { \
00120     int res = pthread_rwlock_wrlock(&__m_lock); \
00121     if (res != 0) \
00122       throw InotifyException(IN_EXC_MSG("locking for writing failed"), res, (void*) this); \
00123   }
00124   
00125 #define IN_WRITE_END IN_READ_END
00126 #define IN_WRITE_END_NOTHROW IN_READ_END_NOTHROW
00127 
00128 #else // INOTIFY_THREAD_SAFE
00129 
00130 #define IN_LOCK_DECL
00131 #define IN_LOCK_INIT
00132 #define IN_LOCK_DONE
00133 #define IN_READ_BEGIN
00134 #define IN_READ_END
00135 #define IN_READ_END_NOTHROW
00136 #define IN_WRITE_BEGIN
00137 #define IN_WRITE_END
00138 #define IN_WRITE_END_NOTHROW
00139 
00140 #endif // INOTIFY_THREAD_SAFE
00141 
00142 
00143 
00144 
00145 // forward declaration
00146 class InotifyWatch;
00147 class Inotify;
00148 
00149 
00151 
00159 class InotifyException
00160 {
00161 public:
00163 
00168   InotifyException(const std::string& rMsg = "", int iErr = 0, void* pSrc = NULL)
00169   : m_msg(rMsg),
00170     m_err(iErr)
00171   {
00172     m_pSrc = pSrc;
00173   }
00174   
00176 
00179   inline const std::string& GetMessage() const
00180   {
00181     return m_msg;
00182   }
00183   
00185 
00190   inline int GetErrorNumber() const
00191   {
00192     return m_err;
00193   } 
00194   
00196 
00199   inline void* GetSource() const
00200   {
00201     return m_pSrc;
00202   }
00203 
00204 protected:
00205   std::string m_msg;      
00206   int m_err;              
00207   mutable void* m_pSrc;   
00208 };
00209 
00210 
00212 
00220 class InotifyEvent
00221 {
00222 public:
00224 
00227   InotifyEvent()
00228   : m_uMask(0),
00229     m_uCookie(0)
00230   {
00231     m_pWatch = NULL;
00232   }
00233   
00235 
00242   InotifyEvent(const struct inotify_event* pEvt, InotifyWatch* pWatch)
00243   : m_uMask(0),
00244     m_uCookie(0)
00245   {
00246     if (pEvt != NULL) {
00247       m_uMask = (uint32_t) pEvt->mask;
00248       m_uCookie = (uint32_t) pEvt->cookie;
00249       if (pEvt->name != NULL) {
00250         m_name = pEvt->len > 0
00251             ? pEvt->name
00252             : "";
00253       }
00254       m_pWatch = pWatch;
00255     }
00256     else {
00257       m_pWatch = NULL;
00258     }
00259   }
00260   
00262   ~InotifyEvent() {}
00263   
00265 
00270   int32_t GetDescriptor() const;
00271   
00273 
00278   inline uint32_t GetMask() const
00279   {
00280     return m_uMask;
00281   }
00282   
00284 
00289   inline static bool IsType(uint32_t uValue, uint32_t uType)
00290   {
00291     return ((uValue & uType) != 0) && ((~uValue & uType) == 0);
00292   }
00293   
00295 
00299   inline bool IsType(uint32_t uType) const
00300   {
00301     return IsType(m_uMask, uType);
00302   }
00303   
00305 
00308   inline uint32_t GetCookie() const
00309   {
00310     return m_uCookie;
00311   }
00312   
00314 
00317   inline uint32_t GetLength() const
00318   {
00319     return (uint32_t) m_name.length();
00320   }
00321   
00323 
00326   inline const std::string& GetName() const
00327   {
00328     return m_name;
00329   }
00330   
00332 
00335   inline void GetName(std::string& rName) const
00336   {
00337     rName = GetName();
00338   }
00339   
00341 
00344   inline InotifyWatch* GetWatch()
00345   {
00346     return m_pWatch;
00347   }
00348   
00350 
00354   static uint32_t GetMaskByName(const std::string& rName);
00355   
00357 
00361   static void DumpTypes(uint32_t uValue, std::string& rStr);
00362   
00364 
00367   void DumpTypes(std::string& rStr) const;
00368   
00369 private:
00370   uint32_t m_uMask;           
00371   uint32_t m_uCookie;         
00372   std::string m_name;         
00373   InotifyWatch* m_pWatch;     
00374 };
00375 
00376 
00377 
00379 
00385 class InotifyWatch
00386 {
00387 public:
00389 
00397   InotifyWatch(const std::string& rPath, int32_t uMask, bool fEnabled = true)
00398   : m_path(rPath),
00399     m_uMask(uMask),
00400     m_wd((int32_t) -1),
00401     m_fEnabled(fEnabled)
00402   {
00403     IN_LOCK_INIT
00404   }
00405   
00407   ~InotifyWatch()
00408   {
00409     IN_LOCK_DONE
00410   }
00411   
00413 
00416   inline int32_t GetDescriptor() const
00417   {
00418     return m_wd;
00419   }
00420   
00422 
00425   inline const std::string& GetPath() const
00426   {
00427     return m_path;
00428   }
00429   
00431 
00434   inline uint32_t GetMask() const
00435   {
00436     return (uint32_t) m_uMask;
00437   }
00438   
00440 
00449   void SetMask(uint32_t uMask) throw (InotifyException);   
00450   
00452 
00455   inline Inotify* GetInotify()
00456   {
00457     return m_pInotify;
00458   }
00459   
00461 
00472   void SetEnabled(bool fEnabled) throw (InotifyException);
00473   
00475 
00478   inline bool IsEnabled() const
00479   {
00480     return m_fEnabled;
00481   }
00482   
00484 
00493   inline bool IsRecursive() const
00494   {
00495     return false;    
00496   }
00497   
00498 private:
00499   friend class Inotify;
00500 
00501   std::string m_path;   
00502   uint32_t m_uMask;     
00503   int32_t m_wd;         
00504   Inotify* m_pInotify;  
00505   bool m_fEnabled;      
00506   
00507   IN_LOCK_DECL
00508   
00510 
00515   void __Disable();
00516 };
00517 
00518 
00520 typedef std::map<int32_t, InotifyWatch*> IN_WATCH_MAP;
00521 
00523 typedef std::map<std::string, InotifyWatch*> IN_WP_MAP;
00524 
00525 
00527 
00533 class Inotify
00534 {
00535 public:
00537 
00543   Inotify() throw (InotifyException);
00544   
00546 
00549   ~Inotify();
00550   
00552   void Close();
00553     
00555 
00560   void Add(InotifyWatch* pWatch) throw (InotifyException);
00561   
00563 
00568   inline void Add(InotifyWatch& rWatch) throw (InotifyException)
00569   {
00570     Add(&rWatch);
00571   }
00572   
00574 
00581   void Remove(InotifyWatch* pWatch) throw (InotifyException);
00582   
00584 
00591   inline void Remove(InotifyWatch& rWatch) throw (InotifyException)
00592   {
00593     Remove(&rWatch);
00594   }
00595   
00597   void RemoveAll();
00598   
00600 
00608   inline size_t GetWatchCount() const
00609   {
00610     IN_READ_BEGIN
00611     size_t n = (size_t) m_paths.size();
00612     IN_READ_END
00613     return n;
00614   }
00615   
00617 
00622   inline size_t GetEnabledCount() const
00623   {
00624     IN_READ_BEGIN
00625     size_t n = (size_t) m_watches.size();
00626     IN_READ_END
00627     return n;
00628   }
00629   
00631 
00642   void WaitForEvents(bool fNoIntr = false) throw (InotifyException);
00643   
00645 
00651   inline size_t GetEventCount()
00652   {
00653     IN_READ_BEGIN
00654     size_t n = (size_t) m_events.size();
00655     IN_READ_END
00656     return n;
00657   }
00658   
00660 
00668   bool GetEvent(InotifyEvent* pEvt) throw (InotifyException);
00669   
00671 
00678   bool GetEvent(InotifyEvent& rEvt) throw (InotifyException)
00679   {
00680     return GetEvent(&rEvt);
00681   }
00682   
00684 
00692   bool PeekEvent(InotifyEvent* pEvt) throw (InotifyException);
00693   
00695 
00702   bool PeekEvent(InotifyEvent& rEvt) throw (InotifyException)
00703   {
00704     return PeekEvent(&rEvt);
00705   }
00706   
00708 
00714   InotifyWatch* FindWatch(int iDescriptor);
00715   
00717 
00727    InotifyWatch* FindWatch(const std::string& rPath);
00728   
00730 
00738   inline int GetDescriptor() const
00739   {
00740     return m_fd;
00741   }
00742   
00744 
00757   void SetNonBlock(bool fNonBlock) throw (InotifyException);
00758   
00760 
00773   void SetCloseOnExec(bool fClOnEx) throw (InotifyException);
00774   
00776 
00781   static uint32_t GetCapability(InotifyCapability_t cap) throw (InotifyException);
00782   
00784 
00792   static void SetCapability(InotifyCapability_t cap, uint32_t val) throw (InotifyException);
00793   
00795 
00799   inline static uint32_t GetMaxEvents() throw (InotifyException)
00800   {
00801     return GetCapability(IN_MAX_EVENTS);
00802   }
00803   
00805 
00813   inline static void SetMaxEvents(uint32_t val) throw (InotifyException)
00814   {
00815     SetCapability(IN_MAX_EVENTS, val);
00816   }
00817   
00819 
00826   inline static uint32_t GetMaxInstances() throw (InotifyException)
00827   {
00828     return GetCapability(IN_MAX_INSTANCES);
00829   }
00830   
00832 
00840   inline static void SetMaxInstances(uint32_t val) throw (InotifyException)
00841   {
00842     SetCapability(IN_MAX_INSTANCES, val);
00843   }
00844   
00846 
00853   inline static uint32_t GetMaxWatches() throw (InotifyException)
00854   {
00855     return GetCapability(IN_MAX_WATCHES);
00856   }
00857   
00859 
00867   inline static void SetMaxWatches(uint32_t val) throw (InotifyException)
00868   {
00869     SetCapability(IN_MAX_WATCHES, val);
00870   }
00871 
00872 private: 
00873   int m_fd;                             
00874   IN_WATCH_MAP m_watches;               
00875   IN_WP_MAP m_paths;                    
00876   unsigned char m_buf[INOTIFY_BUFLEN];  
00877   std::deque<InotifyEvent> m_events;    
00878   
00879   IN_LOCK_DECL
00880   
00881   friend class InotifyWatch;
00882   
00883   static std::string GetCapabilityPath(InotifyCapability_t cap) throw (InotifyException);
00884 };
00885 
00886 
00887 #endif //_INOTIFYCXX_H_
00888 

Generated on Wed Feb 14 15:54:33 2007 for incron by  doxygen 1.5.1