Main Page | Class List | File List | Class Members | 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 <string>
00030 #include <deque>
00031 #include <map>
00032 
00033 // Please ensure that the following headers take the right place
00034 #include <sys/inotify.h>
00035 
00036 // Use this if syscalls not defined
00037 #ifndef __NR_inotify_init
00038 #include <sys/inotify-syscalls.h>
00039 #endif // __NR_inotify_init
00040 
00042 #define INOTIFY_EVENT_SIZE (sizeof(struct inotify_event))
00043 
00045 #define INOTIFY_BUFLEN (1024 * (INOTIFY_EVENT_SIZE + 16))
00046 
00048 
00051 #define IN_EXC_MSG(msg) (std::string(__PRETTY_FUNCTION__) + ": " + msg)
00052 
00054 
00072 #ifdef INOTIFY_THREAD_SAFE
00073 
00074 #include <pthread.h>
00075 
00076 #define IN_LOCK_DECL mutable pthread_rwlock_t __m_lock;
00077 
00078 #define IN_LOCK_INIT \
00079   { \
00080     pthread_rwlockattr_t attr; \
00081     int res = 0; \
00082     if ((res = pthread_rwlockattr_init(&attr)) != 0) \
00083       throw InotifyException(IN_EXC_MSG("cannot initialize lock attributes"), res, this); \
00084     if ((res = pthread_rwlockattr_setkind_np(&attr, PTHREAD_RWLOCK_PREFER_WRITER_NP)) != 0) \
00085       throw InotifyException(IN_EXC_MSG("cannot set lock kind"), res, this); \
00086     if ((res = pthread_rwlock_init(&__m_lock, &attr)) != 0) \
00087       throw InotifyException(IN_EXC_MSG("cannot initialize lock"), res, this); \
00088     pthread_rwlockattr_destroy(&attr); \
00089   }
00090  
00091 #define IN_LOCK_DONE pthread_rwlock_destroy(&__m_lock);
00092 
00093 #define IN_READ_BEGIN \
00094   { \
00095     int res = pthread_rwlock_rdlock(&__m_lock); \
00096     if (res != 0) \
00097       throw InotifyException(IN_EXC_MSG("locking for reading failed"), res, (void*) this); \
00098   }
00099   
00100 #define IN_READ_END \
00101   { \
00102     int res = pthread_rwlock_unlock(&__m_lock); \
00103     if (res != 0) \
00104       throw InotifyException(IN_EXC_MSG("unlocking failed"), res, (void*) this); \
00105   }
00106   
00107 #define IN_READ_END_NOTHROW pthread_rwlock_unlock(&__m_lock);
00108   
00109 #define IN_WRITE_BEGIN \
00110   { \
00111     int res = pthread_rwlock_wrlock(&__m_lock); \
00112     if (res != 0) \
00113       throw InotifyException(IN_EXC_MSG("locking for writing failed"), res, (void*) this); \
00114   }
00115   
00116 #define IN_WRITE_END IN_READ_END
00117 #define IN_WRITE_END_NOTHROW IN_READ_END_NOTHROW
00118 
00119 #else // INOTIFY_THREAD_SAFE
00120 
00121 #define IN_LOCK_DECL
00122 #define IN_LOCK_INIT
00123 #define IN_LOCK_DONE
00124 #define IN_READ_BEGIN
00125 #define IN_READ_END
00126 #define IN_READ_END_NOTHROW
00127 #define IN_WRITE_BEGIN
00128 #define IN_WRITE_END
00129 #define IN_WRITE_END_NOTHROW
00130 
00131 #endif // INOTIFY_THREAD_SAFE
00132 
00133 
00134 
00135 
00136 // forward declaration
00137 class InotifyWatch;
00138 class Inotify;
00139 
00140 
00142 
00150 class InotifyException
00151 {
00152 public:
00154 
00159   InotifyException(const std::string& rMsg = "", int iErr = 0, void* pSrc = NULL)
00160   : m_msg(rMsg),
00161     m_err(iErr)
00162   {
00163     m_pSrc = pSrc;
00164   }
00165   
00167 
00170   inline const std::string& GetMessage() const
00171   {
00172     return m_msg;
00173   }
00174   
00176 
00181   inline int GetErrorNumber() const
00182   {
00183     return m_err;
00184   } 
00185   
00187 
00190   inline void* GetSource() const
00191   {
00192     return m_pSrc;
00193   }
00194 
00195 protected:
00196   std::string m_msg;      
00197   int m_err;              
00198   mutable void* m_pSrc;   
00199 };
00200 
00201 
00203 
00211 class InotifyEvent
00212 {
00213 public:
00215 
00218   InotifyEvent()
00219   : m_uMask(0),
00220     m_uCookie(0)
00221   {
00222     m_pWatch = NULL;
00223   }
00224   
00226 
00233   InotifyEvent(const struct inotify_event* pEvt, InotifyWatch* pWatch)
00234   : m_uMask(0),
00235     m_uCookie(0)
00236   {
00237     if (pEvt != NULL) {
00238       m_uMask = (uint32_t) pEvt->mask;
00239       m_uCookie = (uint32_t) pEvt->cookie;
00240       if (pEvt->name != NULL)
00241         m_name = pEvt->name;
00242       m_pWatch = pWatch;
00243     }
00244     else {
00245       m_pWatch = NULL;
00246     }
00247   }
00248   
00250   ~InotifyEvent() {}
00251   
00253 
00258   int32_t GetDescriptor() const;
00259   
00261 
00266   inline uint32_t GetMask() const
00267   {
00268     return m_uMask;
00269   }
00270   
00272 
00277   inline static bool IsType(uint32_t uValue, uint32_t uType)
00278   {
00279     return ((uValue & uType) != 0) && ((~uValue & uType) == 0);
00280   }
00281   
00283 
00287   inline bool IsType(uint32_t uType) const
00288   {
00289     return IsType(m_uMask, uType);
00290   }
00291   
00293 
00296   inline uint32_t GetCookie() const
00297   {
00298     return m_uCookie;
00299   }
00300   
00302 
00305   inline uint32_t GetLength() const
00306   {
00307     return (uint32_t) m_name.length();
00308   }
00309   
00311 
00314   inline const std::string& GetName() const
00315   {
00316     return m_name;
00317   }
00318   
00320 
00323   inline void GetName(std::string& rName) const
00324   {
00325     rName = GetName();
00326   }
00327   
00329 
00332   inline InotifyWatch* GetWatch()
00333   {
00334     return m_pWatch;
00335   }
00336   
00338 
00342   static uint32_t GetMaskByName(const std::string& rName);
00343   
00345 
00349   static void DumpTypes(uint32_t uValue, std::string& rStr);
00350   
00352 
00355   void DumpTypes(std::string& rStr) const;
00356   
00357 private:
00358   uint32_t m_uMask;           
00359   uint32_t m_uCookie;         
00360   std::string m_name;         
00361   InotifyWatch* m_pWatch;     
00362 };
00363 
00364 
00365 
00367 
00373 class InotifyWatch
00374 {
00375 public:
00377 
00385   InotifyWatch(const std::string& rPath, int32_t uMask, bool fEnabled = true)
00386   : m_path(rPath),
00387     m_uMask(uMask),
00388     m_wd((int32_t) -1),
00389     m_fEnabled(fEnabled)
00390   {
00391     IN_LOCK_INIT
00392   }
00393   
00395   ~InotifyWatch()
00396   {
00397     IN_LOCK_DONE
00398   }
00399   
00401 
00404   inline int32_t GetDescriptor() const
00405   {
00406     return m_wd;
00407   }
00408   
00410 
00413   inline const std::string& GetPath() const
00414   {
00415     return m_path;
00416   }
00417   
00419 
00422   inline uint32_t GetMask() const
00423   {
00424     return (uint32_t) m_uMask;
00425   }
00426   
00428 
00437   void SetMask(uint32_t uMask) throw (InotifyException);   
00438   
00440 
00443   inline Inotify* GetInotify()
00444   {
00445     return m_pInotify;
00446   }
00447   
00449 
00460   void SetEnabled(bool fEnabled) throw (InotifyException);
00461   
00463 
00466   inline bool IsEnabled() const
00467   {
00468     return m_fEnabled;
00469   }
00470   
00471 private:
00472   friend class Inotify;
00473 
00474   std::string m_path;   
00475   uint32_t m_uMask;     
00476   int32_t m_wd;         
00477   Inotify* m_pInotify;  
00478   bool m_fEnabled;      
00479   
00480   IN_LOCK_DECL
00481 };
00482 
00483 
00485 typedef std::map<int32_t, InotifyWatch*> IN_WATCH_MAP;
00486 
00488 typedef std::map<std::string, InotifyWatch*> IN_WP_MAP;
00489 
00490 
00492 
00498 class Inotify
00499 {
00500 public:
00502 
00508   Inotify() throw (InotifyException);
00509   
00511 
00514   ~Inotify();
00515   
00517   void Close();
00518     
00520 
00525   void Add(InotifyWatch* pWatch) throw (InotifyException);
00526   
00528 
00533   inline void Add(InotifyWatch& rWatch) throw (InotifyException)
00534   {
00535     Add(&rWatch);
00536   }
00537   
00539 
00546   void Remove(InotifyWatch* pWatch) throw (InotifyException);
00547   
00549 
00556   inline void Remove(InotifyWatch& rWatch) throw (InotifyException)
00557   {
00558     Remove(&rWatch);
00559   }
00560   
00562   void RemoveAll();
00563   
00565 
00573   inline size_t GetWatchCount() const
00574   {
00575     IN_READ_BEGIN
00576     size_t n = (size_t) m_paths.size();
00577     IN_READ_END
00578     return n;
00579   }
00580   
00582 
00587   inline size_t GetEnabledCount() const
00588   {
00589     IN_READ_BEGIN
00590     size_t n = (size_t) m_watches.size();
00591     IN_READ_END
00592     return n;
00593   }
00594   
00596 
00607   void WaitForEvents(bool fNoIntr = false) throw (InotifyException);
00608   
00610 
00616   inline size_t GetEventCount()
00617   {
00618     IN_READ_BEGIN
00619     size_t n = (size_t) m_events.size();
00620     IN_READ_END
00621     return n;
00622   }
00623   
00625 
00633   bool GetEvent(InotifyEvent* pEvt) throw (InotifyException);
00634   
00636 
00643   bool GetEvent(InotifyEvent& rEvt) throw (InotifyException)
00644   {
00645     return GetEvent(&rEvt);
00646   }
00647   
00649 
00657   bool PeekEvent(InotifyEvent* pEvt) throw (InotifyException);
00658   
00660 
00667   bool PeekEvent(InotifyEvent& rEvt) throw (InotifyException)
00668   {
00669     return PeekEvent(&rEvt);
00670   }
00671   
00673 
00679   InotifyWatch* FindWatch(int iDescriptor);
00680   
00682 
00692    InotifyWatch* FindWatch(const std::string& rPath);
00693   
00695 
00703   inline int GetDescriptor() const
00704   {
00705     return m_fd;
00706   }
00707   
00709 
00720   void SetNonBlock(bool fNonBlock) throw (InotifyException);
00721 
00722 private: 
00723   int m_fd;                             
00724   IN_WATCH_MAP m_watches;               
00725   IN_WP_MAP m_paths;                    
00726   unsigned char m_buf[INOTIFY_BUFLEN];  
00727   std::deque<InotifyEvent> m_events;    
00728   
00729   IN_LOCK_DECL
00730   
00731   friend class InotifyWatch;
00732 };
00733 
00734 
00735 #endif //_INOTIFYCXX_H_
00736 

Generated on Sun Oct 29 16:45:49 2006 for inotify-cxx by  doxygen 1.4.4