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/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 
00073 #ifdef INOTIFY_THREAD_SAFE
00074 
00075 #include <pthread.h>
00076 
00077 #define IN_LOCK_DECL mutable pthread_rwlock_t __m_lock;
00078 
00079 #define IN_LOCK_INIT \
00080   { \
00081     pthread_rwlockattr_t attr; \
00082     int res = 0; \
00083     if ((res = pthread_rwlockattr_init(&attr)) != 0) \
00084       throw InotifyException(IN_EXC_MSG("cannot initialize lock attributes"), res, this); \
00085     if ((res = pthread_rwlockattr_setkind_np(&attr, PTHREAD_RWLOCK_PREFER_WRITER_NP)) != 0) \
00086       throw InotifyException(IN_EXC_MSG("cannot set lock kind"), res, this); \
00087     if ((res = pthread_rwlock_init(&__m_lock, &attr)) != 0) \
00088       throw InotifyException(IN_EXC_MSG("cannot initialize lock"), res, this); \
00089     pthread_rwlockattr_destroy(&attr); \
00090   }
00091  
00092 #define IN_LOCK_DONE pthread_rwlock_destroy(&__m_lock);
00093 
00094 #define IN_READ_BEGIN \
00095   { \
00096     int res = pthread_rwlock_rdlock(&__m_lock); \
00097     if (res != 0) \
00098       throw InotifyException(IN_EXC_MSG("locking for reading failed"), res, (void*) this); \
00099   }
00100   
00101 #define IN_READ_END \
00102   { \
00103     int res = pthread_rwlock_unlock(&__m_lock); \
00104     if (res != 0) \
00105       throw InotifyException(IN_EXC_MSG("unlocking failed"), res, (void*) this); \
00106   }
00107   
00108 #define IN_READ_END_NOTHROW pthread_rwlock_unlock(&__m_lock);
00109   
00110 #define IN_WRITE_BEGIN \
00111   { \
00112     int res = pthread_rwlock_wrlock(&__m_lock); \
00113     if (res != 0) \
00114       throw InotifyException(IN_EXC_MSG("locking for writing failed"), res, (void*) this); \
00115   }
00116   
00117 #define IN_WRITE_END IN_READ_END
00118 #define IN_WRITE_END_NOTHROW IN_READ_END_NOTHROW
00119 
00120 #else // INOTIFY_THREAD_SAFE
00121 
00122 #define IN_LOCK_DECL
00123 #define IN_LOCK_INIT
00124 #define IN_LOCK_DONE
00125 #define IN_READ_BEGIN
00126 #define IN_READ_END
00127 #define IN_READ_END_NOTHROW
00128 #define IN_WRITE_BEGIN
00129 #define IN_WRITE_END
00130 #define IN_WRITE_END_NOTHROW
00131 
00132 #endif // INOTIFY_THREAD_SAFE
00133 
00134 
00135 
00136 
00137 // forward declaration
00138 class InotifyWatch;
00139 class Inotify;
00140 
00141 
00143 
00151 class InotifyException
00152 {
00153 public:
00155 
00160   InotifyException(const std::string& rMsg = "", int iErr = 0, void* pSrc = NULL)
00161   : m_msg(rMsg),
00162     m_err(iErr)
00163   {
00164     m_pSrc = pSrc;
00165   }
00166   
00168 
00171   inline const std::string& GetMessage() const
00172   {
00173     return m_msg;
00174   }
00175   
00177 
00182   inline int GetErrorNumber() const
00183   {
00184     return m_err;
00185   } 
00186   
00188 
00191   inline void* GetSource() const
00192   {
00193     return m_pSrc;
00194   }
00195 
00196 protected:
00197   std::string m_msg;      
00198   int m_err;              
00199   mutable void* m_pSrc;   
00200 };
00201 
00202 
00204 
00212 class InotifyEvent
00213 {
00214 public:
00216 
00219   InotifyEvent()
00220   : m_uMask(0),
00221     m_uCookie(0)
00222   {
00223     m_pWatch = NULL;
00224   }
00225   
00227 
00234   InotifyEvent(const struct inotify_event* pEvt, InotifyWatch* pWatch)
00235   : m_uMask(0),
00236     m_uCookie(0)
00237   {
00238     if (pEvt != NULL) {
00239       m_uMask = (uint32_t) pEvt->mask;
00240       m_uCookie = (uint32_t) pEvt->cookie;
00241       if (pEvt->name != NULL)
00242         m_name = pEvt->name;
00243       m_pWatch = pWatch;
00244     }
00245     else {
00246       m_pWatch = NULL;
00247     }
00248   }
00249   
00251   ~InotifyEvent() {}
00252   
00254 
00259   int32_t GetDescriptor() const;
00260   
00262 
00267   inline uint32_t GetMask() const
00268   {
00269     return m_uMask;
00270   }
00271   
00273 
00278   inline static bool IsType(uint32_t uValue, uint32_t uType)
00279   {
00280     return ((uValue & uType) != 0) && ((~uValue & uType) == 0);
00281   }
00282   
00284 
00288   inline bool IsType(uint32_t uType) const
00289   {
00290     return IsType(m_uMask, uType);
00291   }
00292   
00294 
00297   inline uint32_t GetCookie() const
00298   {
00299     return m_uCookie;
00300   }
00301   
00303 
00306   inline uint32_t GetLength() const
00307   {
00308     return (uint32_t) m_name.length();
00309   }
00310   
00312 
00315   inline const std::string& GetName() const
00316   {
00317     return m_name;
00318   }
00319   
00321 
00324   inline void GetName(std::string& rName) const
00325   {
00326     rName = GetName();
00327   }
00328   
00330 
00333   inline InotifyWatch* GetWatch()
00334   {
00335     return m_pWatch;
00336   }
00337   
00339 
00343   static uint32_t GetMaskByName(const std::string& rName);
00344   
00346 
00350   static void DumpTypes(uint32_t uValue, std::string& rStr);
00351   
00353 
00356   void DumpTypes(std::string& rStr) const;
00357   
00358 private:
00359   uint32_t m_uMask;           
00360   uint32_t m_uCookie;         
00361   std::string m_name;         
00362   InotifyWatch* m_pWatch;     
00363 };
00364 
00365 
00366 
00368 
00374 class InotifyWatch
00375 {
00376 public:
00378 
00386   InotifyWatch(const std::string& rPath, int32_t uMask, bool fEnabled = true)
00387   : m_path(rPath),
00388     m_uMask(uMask),
00389     m_wd((int32_t) -1),
00390     m_fEnabled(fEnabled)
00391   {
00392     IN_LOCK_INIT
00393   }
00394   
00396   ~InotifyWatch()
00397   {
00398     IN_LOCK_DONE
00399   }
00400   
00402 
00405   inline int32_t GetDescriptor() const
00406   {
00407     return m_wd;
00408   }
00409   
00411 
00414   inline const std::string& GetPath() const
00415   {
00416     return m_path;
00417   }
00418   
00420 
00423   inline uint32_t GetMask() const
00424   {
00425     return (uint32_t) m_uMask;
00426   }
00427   
00429 
00438   void SetMask(uint32_t uMask) throw (InotifyException);   
00439   
00441 
00444   inline Inotify* GetInotify()
00445   {
00446     return m_pInotify;
00447   }
00448   
00450 
00461   void SetEnabled(bool fEnabled) throw (InotifyException);
00462   
00464 
00467   inline bool IsEnabled() const
00468   {
00469     return m_fEnabled;
00470   }
00471   
00472 private:
00473   friend class Inotify;
00474 
00475   std::string m_path;   
00476   uint32_t m_uMask;     
00477   int32_t m_wd;         
00478   Inotify* m_pInotify;  
00479   bool m_fEnabled;      
00480   
00481   IN_LOCK_DECL
00482 };
00483 
00484 
00486 typedef std::map<int32_t, InotifyWatch*> IN_WATCH_MAP;
00487 
00489 typedef std::map<std::string, InotifyWatch*> IN_WP_MAP;
00490 
00491 
00493 
00499 class Inotify
00500 {
00501 public:
00503 
00509   Inotify() throw (InotifyException);
00510   
00512 
00515   ~Inotify();
00516   
00518   void Close();
00519     
00521 
00526   void Add(InotifyWatch* pWatch) throw (InotifyException);
00527   
00529 
00534   inline void Add(InotifyWatch& rWatch) throw (InotifyException)
00535   {
00536     Add(&rWatch);
00537   }
00538   
00540 
00547   void Remove(InotifyWatch* pWatch) throw (InotifyException);
00548   
00550 
00557   inline void Remove(InotifyWatch& rWatch) throw (InotifyException)
00558   {
00559     Remove(&rWatch);
00560   }
00561   
00563   void RemoveAll();
00564   
00566 
00574   inline size_t GetWatchCount() const
00575   {
00576     IN_READ_BEGIN
00577     size_t n = (size_t) m_paths.size();
00578     IN_READ_END
00579     return n;
00580   }
00581   
00583 
00588   inline size_t GetEnabledCount() const
00589   {
00590     IN_READ_BEGIN
00591     size_t n = (size_t) m_watches.size();
00592     IN_READ_END
00593     return n;
00594   }
00595   
00597 
00608   void WaitForEvents(bool fNoIntr = false) throw (InotifyException);
00609   
00611 
00617   inline size_t GetEventCount()
00618   {
00619     IN_READ_BEGIN
00620     size_t n = (size_t) m_events.size();
00621     IN_READ_END
00622     return n;
00623   }
00624   
00626 
00634   bool GetEvent(InotifyEvent* pEvt) throw (InotifyException);
00635   
00637 
00644   bool GetEvent(InotifyEvent& rEvt) throw (InotifyException)
00645   {
00646     return GetEvent(&rEvt);
00647   }
00648   
00650 
00658   bool PeekEvent(InotifyEvent* pEvt) throw (InotifyException);
00659   
00661 
00668   bool PeekEvent(InotifyEvent& rEvt) throw (InotifyException)
00669   {
00670     return PeekEvent(&rEvt);
00671   }
00672   
00674 
00680   InotifyWatch* FindWatch(int iDescriptor);
00681   
00683 
00693    InotifyWatch* FindWatch(const std::string& rPath);
00694   
00696 
00704   inline int GetDescriptor() const
00705   {
00706     return m_fd;
00707   }
00708   
00710 
00721   void SetNonBlock(bool fNonBlock) throw (InotifyException);
00722 
00723 private: 
00724   int m_fd;                             
00725   IN_WATCH_MAP m_watches;               
00726   IN_WP_MAP m_paths;                    
00727   unsigned char m_buf[INOTIFY_BUFLEN];  
00728   std::deque<InotifyEvent> m_events;    
00729   
00730   IN_LOCK_DECL
00731   
00732   friend class InotifyWatch;
00733 };
00734 
00735 
00736 #endif //_INOTIFYCXX_H_
00737 

Generated on Sat Dec 2 18:30:25 2006 for incron by  doxygen 1.4.4