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->name;
00251       m_pWatch = pWatch;
00252     }
00253     else {
00254       m_pWatch = NULL;
00255     }
00256   }
00257   
00259   ~InotifyEvent() {}
00260   
00262 
00267   int32_t GetDescriptor() const;
00268   
00270 
00275   inline uint32_t GetMask() const
00276   {
00277     return m_uMask;
00278   }
00279   
00281 
00286   inline static bool IsType(uint32_t uValue, uint32_t uType)
00287   {
00288     return ((uValue & uType) != 0) && ((~uValue & uType) == 0);
00289   }
00290   
00292 
00296   inline bool IsType(uint32_t uType) const
00297   {
00298     return IsType(m_uMask, uType);
00299   }
00300   
00302 
00305   inline uint32_t GetCookie() const
00306   {
00307     return m_uCookie;
00308   }
00309   
00311 
00314   inline uint32_t GetLength() const
00315   {
00316     return (uint32_t) m_name.length();
00317   }
00318   
00320 
00323   inline const std::string& GetName() const
00324   {
00325     return m_name;
00326   }
00327   
00329 
00332   inline void GetName(std::string& rName) const
00333   {
00334     rName = GetName();
00335   }
00336   
00338 
00341   inline InotifyWatch* GetWatch()
00342   {
00343     return m_pWatch;
00344   }
00345   
00347 
00351   static uint32_t GetMaskByName(const std::string& rName);
00352   
00354 
00358   static void DumpTypes(uint32_t uValue, std::string& rStr);
00359   
00361 
00364   void DumpTypes(std::string& rStr) const;
00365   
00366 private:
00367   uint32_t m_uMask;           
00368   uint32_t m_uCookie;         
00369   std::string m_name;         
00370   InotifyWatch* m_pWatch;     
00371 };
00372 
00373 
00374 
00376 
00382 class InotifyWatch
00383 {
00384 public:
00386 
00394   InotifyWatch(const std::string& rPath, int32_t uMask, bool fEnabled = true)
00395   : m_path(rPath),
00396     m_uMask(uMask),
00397     m_wd((int32_t) -1),
00398     m_fEnabled(fEnabled)
00399   {
00400     IN_LOCK_INIT
00401   }
00402   
00404   ~InotifyWatch()
00405   {
00406     IN_LOCK_DONE
00407   }
00408   
00410 
00413   inline int32_t GetDescriptor() const
00414   {
00415     return m_wd;
00416   }
00417   
00419 
00422   inline const std::string& GetPath() const
00423   {
00424     return m_path;
00425   }
00426   
00428 
00431   inline uint32_t GetMask() const
00432   {
00433     return (uint32_t) m_uMask;
00434   }
00435   
00437 
00446   void SetMask(uint32_t uMask) throw (InotifyException);   
00447   
00449 
00452   inline Inotify* GetInotify()
00453   {
00454     return m_pInotify;
00455   }
00456   
00458 
00469   void SetEnabled(bool fEnabled) throw (InotifyException);
00470   
00472 
00475   inline bool IsEnabled() const
00476   {
00477     return m_fEnabled;
00478   }
00479   
00481 
00490   inline bool IsRecursive() const
00491   {
00492     return false;    
00493   }
00494   
00495 private:
00496   friend class Inotify;
00497 
00498   std::string m_path;   
00499   uint32_t m_uMask;     
00500   int32_t m_wd;         
00501   Inotify* m_pInotify;  
00502   bool m_fEnabled;      
00503   
00504   IN_LOCK_DECL
00505 };
00506 
00507 
00509 typedef std::map<int32_t, InotifyWatch*> IN_WATCH_MAP;
00510 
00512 typedef std::map<std::string, InotifyWatch*> IN_WP_MAP;
00513 
00514 
00516 
00522 class Inotify
00523 {
00524 public:
00526 
00532   Inotify() throw (InotifyException);
00533   
00535 
00538   ~Inotify();
00539   
00541   void Close();
00542     
00544 
00549   void Add(InotifyWatch* pWatch) throw (InotifyException);
00550   
00552 
00557   inline void Add(InotifyWatch& rWatch) throw (InotifyException)
00558   {
00559     Add(&rWatch);
00560   }
00561   
00563 
00570   void Remove(InotifyWatch* pWatch) throw (InotifyException);
00571   
00573 
00580   inline void Remove(InotifyWatch& rWatch) throw (InotifyException)
00581   {
00582     Remove(&rWatch);
00583   }
00584   
00586   void RemoveAll();
00587   
00589 
00597   inline size_t GetWatchCount() const
00598   {
00599     IN_READ_BEGIN
00600     size_t n = (size_t) m_paths.size();
00601     IN_READ_END
00602     return n;
00603   }
00604   
00606 
00611   inline size_t GetEnabledCount() const
00612   {
00613     IN_READ_BEGIN
00614     size_t n = (size_t) m_watches.size();
00615     IN_READ_END
00616     return n;
00617   }
00618   
00620 
00631   void WaitForEvents(bool fNoIntr = false) throw (InotifyException);
00632   
00634 
00640   inline size_t GetEventCount()
00641   {
00642     IN_READ_BEGIN
00643     size_t n = (size_t) m_events.size();
00644     IN_READ_END
00645     return n;
00646   }
00647   
00649 
00657   bool GetEvent(InotifyEvent* pEvt) throw (InotifyException);
00658   
00660 
00667   bool GetEvent(InotifyEvent& rEvt) throw (InotifyException)
00668   {
00669     return GetEvent(&rEvt);
00670   }
00671   
00673 
00681   bool PeekEvent(InotifyEvent* pEvt) throw (InotifyException);
00682   
00684 
00691   bool PeekEvent(InotifyEvent& rEvt) throw (InotifyException)
00692   {
00693     return PeekEvent(&rEvt);
00694   }
00695   
00697 
00703   InotifyWatch* FindWatch(int iDescriptor);
00704   
00706 
00716    InotifyWatch* FindWatch(const std::string& rPath);
00717   
00719 
00727   inline int GetDescriptor() const
00728   {
00729     return m_fd;
00730   }
00731   
00733 
00744   void SetNonBlock(bool fNonBlock) throw (InotifyException);
00745   
00747 
00752   static uint32_t GetCapability(InotifyCapability_t cap) throw (InotifyException);
00753   
00755 
00763   static void SetCapability(InotifyCapability_t cap, uint32_t val) throw (InotifyException);
00764   
00766 
00770   inline static uint32_t GetMaxEvents() throw (InotifyException)
00771   {
00772     return GetCapability(IN_MAX_EVENTS);
00773   }
00774   
00776 
00784   inline static void SetMaxEvents(uint32_t val) throw (InotifyException)
00785   {
00786     SetCapability(IN_MAX_EVENTS, val);
00787   }
00788   
00790 
00797   inline static uint32_t GetMaxInstances() throw (InotifyException)
00798   {
00799     return GetCapability(IN_MAX_INSTANCES);
00800   }
00801   
00803 
00811   inline static void SetMaxInstances(uint32_t val) throw (InotifyException)
00812   {
00813     SetCapability(IN_MAX_INSTANCES, val);
00814   }
00815   
00817 
00824   inline static uint32_t GetMaxWatches() throw (InotifyException)
00825   {
00826     return GetCapability(IN_MAX_WATCHES);
00827   }
00828   
00830 
00838   inline static void SetMaxWatches(uint32_t val) throw (InotifyException)
00839   {
00840     SetCapability(IN_MAX_WATCHES, val);
00841   }
00842 
00843 private: 
00844   int m_fd;                             
00845   IN_WATCH_MAP m_watches;               
00846   IN_WP_MAP m_paths;                    
00847   unsigned char m_buf[INOTIFY_BUFLEN];  
00848   std::deque<InotifyEvent> m_events;    
00849   
00850   IN_LOCK_DECL
00851   
00852   friend class InotifyWatch;
00853   
00854   static std::string GetCapabilityPath(InotifyCapability_t cap) throw (InotifyException);
00855 };
00856 
00857 
00858 #endif //_INOTIFYCXX_H_
00859 

Generated on Thu Dec 28 20:58:43 2006 for inotify-cxx by  doxygen 1.5.1