summaryrefslogtreecommitdiff
path: root/shared/inotify/inotify-cxx.h
diff options
context:
space:
mode:
authorDaniel Wilhelm <daniel@wili.li>2014-04-18 17:00:17 +0200
committerDaniel Wilhelm <daniel@wili.li>2014-04-18 17:00:17 +0200
commitfd0853d2623dd278b08288331ed42e3be59252fb (patch)
treea7645daeaef8bdbed064faf4eb88e72cee58726c /shared/inotify/inotify-cxx.h
parent2.1 (diff)
downloadFreeFileSync-fd0853d2623dd278b08288331ed42e3be59252fb.tar.gz
FreeFileSync-fd0853d2623dd278b08288331ed42e3be59252fb.tar.bz2
FreeFileSync-fd0853d2623dd278b08288331ed42e3be59252fb.zip
2.2
Diffstat (limited to 'shared/inotify/inotify-cxx.h')
-rw-r--r--shared/inotify/inotify-cxx.h889
1 files changed, 889 insertions, 0 deletions
diff --git a/shared/inotify/inotify-cxx.h b/shared/inotify/inotify-cxx.h
new file mode 100644
index 00000000..4170972f
--- /dev/null
+++ b/shared/inotify/inotify-cxx.h
@@ -0,0 +1,889 @@
+
+/// inotify C++ interface header
+/**
+ * \file inotify-cxx.h
+ *
+ * inotify C++ interface
+ *
+ * Copyright (C) 2006, 2007 Lukas Jelinek, <lukas@aiken.cz>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of one of the following licenses:
+ *
+ * \li 1. X11-style license (see LICENSE-X11)
+ * \li 2. GNU Lesser General Public License, version 2.1 (see LICENSE-LGPL)
+ * \li 3. GNU General Public License, version 2 (see LICENSE-GPL)
+ *
+ * If you want to help with choosing the best license for you,
+ * please visit http://www.gnu.org/licenses/license-list.html.
+ *
+ */
+
+
+
+
+
+#ifndef _INOTIFYCXX_H_
+#define _INOTIFYCXX_H_
+
+#include <stdint.h>
+#include <string>
+#include <deque>
+#include <map>
+
+// Please ensure that the following headers take the right place
+#include <sys/syscall.h>
+#include <sys/inotify.h>
+
+// Use this if syscalls not defined
+#ifndef __NR_inotify_init
+#include <sys/inotify-syscalls.h>
+#endif // __NR_inotify_init
+
+/// Event struct size
+#define INOTIFY_EVENT_SIZE (sizeof(struct inotify_event))
+
+/// Event buffer length
+#define INOTIFY_BUFLEN (1024 * (INOTIFY_EVENT_SIZE + 16))
+
+/// Helper macro for creating exception messages.
+/**
+ * It prepends the message by the function name.
+ */
+#define IN_EXC_MSG(msg) (std::string(__PRETTY_FUNCTION__) + ": " + msg)
+
+/// inotify capability/limit identifiers
+typedef enum
+{
+ IN_MAX_EVENTS = 0, ///< max. events in the kernel queue
+ IN_MAX_INSTANCES = 1, ///< max. inotify file descriptors per process
+ IN_MAX_WATCHES = 2 ///< max. watches per file descriptor
+} InotifyCapability_t;
+
+/// inotify-cxx thread safety
+/**
+ * If this symbol is defined you can use this interface safely
+ * threaded applications. Remember that it slightly degrades
+ * performance.
+ *
+ * Even if INOTIFY_THREAD_SAFE is defined some classes stay
+ * unsafe. If you must use them (must you?) in more than one
+ * thread concurrently you need to implement explicite locking.
+ *
+ * You need not to define INOTIFY_THREAD_SAFE in that cases
+ * where the application is multithreaded but all the inotify
+ * infrastructure will be managed only in one thread. This is
+ * the recommended way.
+ *
+ * Locking may fail (it is very rare but not impossible). In this
+ * case an exception is thrown. But if unlocking fails in case
+ * of an error it does nothing (this failure is ignored).
+ */
+#ifdef INOTIFY_THREAD_SAFE
+
+#include <pthread.h>
+
+#define IN_LOCK_DECL mutable pthread_rwlock_t __m_lock;
+
+#define IN_LOCK_INIT \
+ { \
+ pthread_rwlockattr_t attr; \
+ int res = 0; \
+ if ((res = pthread_rwlockattr_init(&attr)) != 0) \
+ throw InotifyException(IN_EXC_MSG("cannot initialize lock attributes"), res, this); \
+ if ((res = pthread_rwlockattr_setkind_np(&attr, PTHREAD_RWLOCK_PREFER_WRITER_NP)) != 0) \
+ throw InotifyException(IN_EXC_MSG("cannot set lock kind"), res, this); \
+ if ((res = pthread_rwlock_init(&__m_lock, &attr)) != 0) \
+ throw InotifyException(IN_EXC_MSG("cannot initialize lock"), res, this); \
+ pthread_rwlockattr_destroy(&attr); \
+ }
+
+#define IN_LOCK_DONE pthread_rwlock_destroy(&__m_lock);
+
+#define IN_READ_BEGIN \
+ { \
+ int res = pthread_rwlock_rdlock(&__m_lock); \
+ if (res != 0) \
+ throw InotifyException(IN_EXC_MSG("locking for reading failed"), res, (void*) this); \
+ }
+
+#define IN_READ_END \
+ { \
+ int res = pthread_rwlock_unlock(&__m_lock); \
+ if (res != 0) \
+ throw InotifyException(IN_EXC_MSG("unlocking failed"), res, (void*) this); \
+ }
+
+#define IN_READ_END_NOTHROW pthread_rwlock_unlock(&__m_lock);
+
+#define IN_WRITE_BEGIN \
+ { \
+ int res = pthread_rwlock_wrlock(&__m_lock); \
+ if (res != 0) \
+ throw InotifyException(IN_EXC_MSG("locking for writing failed"), res, (void*) this); \
+ }
+
+#define IN_WRITE_END IN_READ_END
+#define IN_WRITE_END_NOTHROW IN_READ_END_NOTHROW
+
+#else // INOTIFY_THREAD_SAFE
+
+#define IN_LOCK_DECL
+#define IN_LOCK_INIT
+#define IN_LOCK_DONE
+#define IN_READ_BEGIN
+#define IN_READ_END
+#define IN_READ_END_NOTHROW
+#define IN_WRITE_BEGIN
+#define IN_WRITE_END
+#define IN_WRITE_END_NOTHROW
+
+#endif // INOTIFY_THREAD_SAFE
+
+
+
+
+// forward declaration
+class InotifyWatch;
+class Inotify;
+
+
+/// Class for inotify exceptions
+/**
+ * This class allows to acquire information about exceptional
+ * events. It makes easier to log or display error messages
+ * and to identify problematic code locations.
+ *
+ * Although this class is basically thread-safe it is not intended
+ * to be shared between threads.
+ */
+class InotifyException
+{
+public:
+ /// Constructor
+ /**
+ * \param[in] rMsg message
+ * \param[in] iErr error number (see errno.h)
+ * \param[in] pSrc source
+ */
+ InotifyException(const std::string& rMsg = "", int iErr = 0, void* pSrc = NULL)
+ : m_msg(rMsg),
+ m_err(iErr)
+ {
+ m_pSrc = pSrc;
+ }
+
+ /// Returns the exception message.
+ /**
+ * \return message
+ */
+ inline const std::string& GetMessage() const
+ {
+ return m_msg;
+ }
+
+ /// Returns the exception error number.
+ /**
+ * If not applicable this value is 0 (zero).
+ *
+ * \return error number (standardized; see errno.h)
+ */
+ inline int GetErrorNumber() const
+ {
+ return m_err;
+ }
+
+ /// Returns the exception source.
+ /**
+ * \return source
+ */
+ inline void* GetSource() const
+ {
+ return m_pSrc;
+ }
+
+protected:
+ std::string m_msg; ///< message
+ int m_err; ///< error number
+ mutable void* m_pSrc; ///< source
+};
+
+
+/// inotify event class
+/**
+ * It holds all information about inotify event and provides
+ * access to its particular values.
+ *
+ * This class is not (and is not intended to be) thread-safe
+ * and therefore it must not be used concurrently in multiple
+ * threads.
+ */
+class InotifyEvent
+{
+public:
+ /// Constructor.
+ /**
+ * Creates a plain event.
+ */
+ InotifyEvent()
+ : m_uMask(0),
+ m_uCookie(0)
+ {
+ m_pWatch = NULL;
+ }
+
+ /// Constructor.
+ /**
+ * Creates an event based on inotify event data.
+ * For NULL pointers it works the same way as InotifyEvent().
+ *
+ * \param[in] pEvt event data
+ * \param[in] pWatch inotify watch
+ */
+ InotifyEvent(const struct inotify_event* pEvt, InotifyWatch* pWatch)
+ : m_uMask(0),
+ m_uCookie(0)
+ {
+ if (pEvt != NULL) {
+ m_uMask = (uint32_t) pEvt->mask;
+ m_uCookie = (uint32_t) pEvt->cookie;
+ if (pEvt->name != NULL) {
+ m_name = pEvt->len > 0
+ ? pEvt->name
+ : "";
+ }
+ m_pWatch = pWatch;
+ }
+ else {
+ m_pWatch = NULL;
+ }
+ }
+
+ /// Destructor.
+ ~InotifyEvent() {}
+
+ /// Returns the event watch descriptor.
+ /**
+ * \return watch descriptor
+ *
+ * \sa InotifyWatch::GetDescriptor()
+ */
+ int32_t GetDescriptor() const;
+
+ /// Returns the event mask.
+ /**
+ * \return event mask
+ *
+ * \sa InotifyWatch::GetMask()
+ */
+ inline uint32_t GetMask() const
+ {
+ return m_uMask;
+ }
+
+ /// Checks a value for the event type.
+ /**
+ * \param[in] uValue checked value
+ * \param[in] uType type which is checked for
+ * \return true = the value contains the given type, false = otherwise
+ */
+ inline static bool IsType(uint32_t uValue, uint32_t uType)
+ {
+ return ((uValue & uType) != 0) && ((~uValue & uType) == 0);
+ }
+
+ /// Checks for the event type.
+ /**
+ * \param[in] uType type which is checked for
+ * \return true = event mask contains the given type, false = otherwise
+ */
+ inline bool IsType(uint32_t uType) const
+ {
+ return IsType(m_uMask, uType);
+ }
+
+ /// Returns the event cookie.
+ /**
+ * \return event cookie
+ */
+ inline uint32_t GetCookie() const
+ {
+ return m_uCookie;
+ }
+
+ /// Returns the event name length.
+ /**
+ * \return event name length
+ */
+ inline uint32_t GetLength() const
+ {
+ return (uint32_t) m_name.length();
+ }
+
+ /// Returns the event name.
+ /**
+ * \return event name
+ */
+ inline const std::string& GetName() const
+ {
+ return m_name;
+ }
+
+ /// Extracts the event name.
+ /**
+ * \param[out] rName event name
+ */
+ inline void GetName(std::string& rName) const
+ {
+ rName = GetName();
+ }
+
+ /// Returns the source watch.
+ /**
+ * \return source watch
+ */
+ inline InotifyWatch* GetWatch()
+ {
+ return m_pWatch;
+ }
+
+ /// Finds the appropriate mask for a name.
+ /**
+ * \param[in] rName mask name
+ * \return mask for name; 0 on failure
+ */
+ static uint32_t GetMaskByName(const std::string& rName);
+
+ /// Fills the string with all types contained in an event mask value.
+ /**
+ * \param[in] uValue event mask value
+ * \param[out] rStr dumped event types
+ */
+ static void DumpTypes(uint32_t uValue, std::string& rStr);
+
+ /// Fills the string with all types contained in the event mask.
+ /**
+ * \param[out] rStr dumped event types
+ */
+ void DumpTypes(std::string& rStr) const;
+
+private:
+ uint32_t m_uMask; ///< mask
+ uint32_t m_uCookie; ///< cookie
+ std::string m_name; ///< name
+ InotifyWatch* m_pWatch; ///< source watch
+};
+
+
+
+/// inotify watch class
+/**
+ * It holds information about the inotify watch on a particular
+ * inode.
+ *
+ * If the INOTIFY_THREAD_SAFE is defined this class is thread-safe.
+ */
+class InotifyWatch
+{
+public:
+ /// Constructor.
+ /**
+ * Creates an inotify watch. Because this watch is
+ * inactive it has an invalid descriptor (-1).
+ *
+ * \param[in] rPath watched file path
+ * \param[in] uMask mask for events
+ * \param[in] fEnabled events enabled yes/no
+ */
+ InotifyWatch(const std::string& rPath, int32_t uMask, bool fEnabled = true)
+ : m_path(rPath),
+ m_uMask(uMask),
+ m_wd((int32_t) -1),
+ m_fEnabled(fEnabled)
+ {
+ IN_LOCK_INIT
+ }
+
+ /// Destructor.
+ ~InotifyWatch()
+ {
+ IN_LOCK_DONE
+ }
+
+ /// Returns the watch descriptor.
+ /**
+ * \return watch descriptor; -1 for inactive watch
+ */
+ inline int32_t GetDescriptor() const
+ {
+ return m_wd;
+ }
+
+ /// Returns the watched file path.
+ /**
+ * \return file path
+ */
+ inline const std::string& GetPath() const
+ {
+ return m_path;
+ }
+
+ /// Returns the watch event mask.
+ /**
+ * \return event mask
+ */
+ inline uint32_t GetMask() const
+ {
+ return (uint32_t) m_uMask;
+ }
+
+ /// Sets the watch event mask.
+ /**
+ * If the watch is active (added to an instance of Inotify)
+ * this method may fail due to unsuccessful re-setting
+ * the watch in the kernel.
+ *
+ * \param[in] uMask event mask
+ *
+ * \throw InotifyException thrown if changing fails
+ */
+ void SetMask(uint32_t uMask) throw (InotifyException);
+
+ /// Returns the appropriate inotify class instance.
+ /**
+ * \return inotify instance
+ */
+ inline Inotify* GetInotify()
+ {
+ return m_pInotify;
+ }
+
+ /// Enables/disables the watch.
+ /**
+ * If the watch is active (added to an instance of Inotify)
+ * this method may fail due to unsuccessful re-setting
+ * the watch in the kernel.
+ *
+ * Re-setting the current state has no effect.
+ *
+ * \param[in] fEnabled set enabled yes/no
+ *
+ * \throw InotifyException thrown if enabling/disabling fails
+ */
+ void SetEnabled(bool fEnabled) throw (InotifyException);
+
+ /// Checks whether the watch is enabled.
+ /**
+ * \return true = enables, false = disabled
+ */
+ inline bool IsEnabled() const
+ {
+ return m_fEnabled;
+ }
+
+ /// Checks whether the watch is recursive.
+ /**
+ * A recursive watch monitors a directory itself and all
+ * its subdirectories. This watch is a logical object
+ * which may have many underlying kernel watches.
+ *
+ * \return currently always false (recursive watches not yet supported)
+ * \attention Recursive watches are currently NOT supported.
+ * They are planned for future versions.
+ */
+ inline bool IsRecursive() const
+ {
+ return false;
+ }
+
+private:
+ friend class Inotify;
+
+ std::string m_path; ///< watched file path
+ uint32_t m_uMask; ///< event mask
+ int32_t m_wd; ///< watch descriptor
+ Inotify* m_pInotify; ///< inotify object
+ bool m_fEnabled; ///< events enabled yes/no
+
+ IN_LOCK_DECL
+
+ /// Disables the watch (due to removing by the kernel).
+ /**
+ * This method must be called after receiving an event.
+ * It ensures the watch object is consistent with the kernel
+ * data.
+ */
+ void __Disable();
+};
+
+
+/// Mapping from watch descriptors to watch objects.
+typedef std::map<int32_t, InotifyWatch*> IN_WATCH_MAP;
+
+/// Mapping from paths to watch objects.
+typedef std::map<std::string, InotifyWatch*> IN_WP_MAP;
+
+
+/// inotify class
+/**
+ * It holds information about the inotify device descriptor
+ * and manages the event queue.
+ *
+ * If the INOTIFY_THREAD_SAFE is defined this class is thread-safe.
+ */
+class Inotify
+{
+public:
+ /// Constructor.
+ /**
+ * Creates and initializes an instance of inotify communication
+ * object (opens the inotify device).
+ *
+ * \throw InotifyException thrown if inotify isn't available
+ */
+ Inotify() throw (InotifyException);
+
+ /// Destructor.
+ /**
+ * Calls Close() due to clean-up.
+ */
+ ~Inotify();
+
+ /// Removes all watches and closes the inotify device.
+ void Close();
+
+ /// Adds a new watch.
+ /**
+ * \param[in] pWatch inotify watch
+ *
+ * \throw InotifyException thrown if adding failed
+ */
+ void Add(InotifyWatch* pWatch) throw (InotifyException);
+
+ /// Adds a new watch.
+ /**
+ * \param[in] rWatch inotify watch
+ *
+ * \throw InotifyException thrown if adding failed
+ */
+ inline void Add(InotifyWatch& rWatch) throw (InotifyException)
+ {
+ Add(&rWatch);
+ }
+
+ /// Removes a watch.
+ /**
+ * If the given watch is not present it does nothing.
+ *
+ * \param[in] pWatch inotify watch
+ *
+ * \throw InotifyException thrown if removing failed
+ */
+ void Remove(InotifyWatch* pWatch) throw (InotifyException);
+
+ /// Removes a watch.
+ /**
+ * If the given watch is not present it does nothing.
+ *
+ * \param[in] rWatch inotify watch
+ *
+ * \throw InotifyException thrown if removing failed
+ */
+ inline void Remove(InotifyWatch& rWatch) throw (InotifyException)
+ {
+ Remove(&rWatch);
+ }
+
+ /// Removes all watches.
+ void RemoveAll();
+
+ /// Returns the count of watches.
+ /**
+ * This is the total count of all watches (regardless whether
+ * enabled or not).
+ *
+ * \return count of watches
+ *
+ * \sa GetEnabledCount()
+ */
+ inline size_t GetWatchCount() const
+ {
+ IN_READ_BEGIN
+ size_t n = (size_t) m_paths.size();
+ IN_READ_END
+ return n;
+ }
+
+ /// Returns the count of enabled watches.
+ /**
+ * \return count of enabled watches
+ *
+ * \sa GetWatchCount()
+ */
+ inline size_t GetEnabledCount() const
+ {
+ IN_READ_BEGIN
+ size_t n = (size_t) m_watches.size();
+ IN_READ_END
+ return n;
+ }
+
+ /// Waits for inotify events.
+ /**
+ * It waits until one or more events occur. When called
+ * in nonblocking mode it only retrieves occurred events
+ * to the internal queue and exits.
+ *
+ * \param[in] fNoIntr if true it re-calls the system call after a handled signal
+ *
+ * \throw InotifyException thrown if reading events failed
+ *
+ * \sa SetNonBlock()
+ */
+ void WaitForEvents(bool fNoIntr = false) throw (InotifyException);
+
+ /// Returns the count of received and queued events.
+ /**
+ * This number is related to the events in the queue inside
+ * this object, not to the events pending in the kernel.
+ *
+ * \return count of events
+ */
+ inline size_t GetEventCount()
+ {
+ IN_READ_BEGIN
+ size_t n = (size_t) m_events.size();
+ IN_READ_END
+ return n;
+ }
+
+ /// Extracts a queued inotify event.
+ /**
+ * The extracted event is removed from the queue.
+ * If the pointer is NULL it does nothing.
+ *
+ * \param[in,out] pEvt event object
+ *
+ * \throw InotifyException thrown if the provided pointer is NULL
+ */
+ bool GetEvent(InotifyEvent* pEvt) throw (InotifyException);
+
+ /// Extracts a queued inotify event.
+ /**
+ * The extracted event is removed from the queue.
+ *
+ * \param[in,out] rEvt event object
+ *
+ * \throw InotifyException thrown only in very anomalous cases
+ */
+ bool GetEvent(InotifyEvent& rEvt) throw (InotifyException)
+ {
+ return GetEvent(&rEvt);
+ }
+
+ /// Extracts a queued inotify event (without removing).
+ /**
+ * The extracted event stays in the queue.
+ * If the pointer is NULL it does nothing.
+ *
+ * \param[in,out] pEvt event object
+ *
+ * \throw InotifyException thrown if the provided pointer is NULL
+ */
+ bool PeekEvent(InotifyEvent* pEvt) throw (InotifyException);
+
+ /// Extracts a queued inotify event (without removing).
+ /**
+ * The extracted event stays in the queue.
+ *
+ * \param[in,out] rEvt event object
+ *
+ * \throw InotifyException thrown only in very anomalous cases
+ */
+ bool PeekEvent(InotifyEvent& rEvt) throw (InotifyException)
+ {
+ return PeekEvent(&rEvt);
+ }
+
+ /// Searches for a watch by a watch descriptor.
+ /**
+ * It tries to find a watch by the given descriptor.
+ *
+ * \param[in] iDescriptor watch descriptor
+ * \return pointer to a watch; NULL if no such watch exists
+ */
+ InotifyWatch* FindWatch(int iDescriptor);
+
+ /// Searches for a watch by a filesystem path.
+ /**
+ * It tries to find a watch by the given filesystem path.
+ *
+ * \param[in] rPath filesystem path
+ * \return pointer to a watch; NULL if no such watch exists
+ *
+ * \attention The path must be exactly identical to the one
+ * used for the searched watch. Be careful about
+ * absolute/relative and case-insensitive paths.
+ */
+ InotifyWatch* FindWatch(const std::string& rPath);
+
+ /// Returns the file descriptor.
+ /**
+ * The descriptor can be used in standard low-level file
+ * functions (poll(), select(), fcntl() etc.).
+ *
+ * \return valid file descriptor or -1 for inactive object
+ *
+ * \sa SetNonBlock()
+ */
+ inline int GetDescriptor() const
+ {
+ return m_fd;
+ }
+
+ /// Enables/disables non-blocking mode.
+ /**
+ * Use this mode if you want to monitor the descriptor
+ * (acquired thru GetDescriptor()) in functions such as
+ * poll(), select() etc.
+ *
+ * Non-blocking mode is disabled by default.
+ *
+ * \param[in] fNonBlock enable/disable non-blocking mode
+ *
+ * \throw InotifyException thrown if setting mode failed
+ *
+ * \sa GetDescriptor(), SetCloseOnExec()
+ */
+ void SetNonBlock(bool fNonBlock) throw (InotifyException);
+
+ /// Enables/disables closing on exec.
+ /**
+ * Enable this if you want to close the descriptor when
+ * executing another program. Otherwise, the descriptor
+ * will be inherited.
+ *
+ * Closing on exec is disabled by default.
+ *
+ * \param[in] fClOnEx enable/disable closing on exec
+ *
+ * \throw InotifyException thrown if setting failed
+ *
+ * \sa GetDescriptor(), SetNonBlock()
+ */
+ void SetCloseOnExec(bool fClOnEx) throw (InotifyException);
+
+ /// Acquires a particular inotify capability/limit.
+ /**
+ * \param[in] cap capability/limit identifier
+ * \return capability/limit value
+ * \throw InotifyException thrown if the given value cannot be acquired
+ */
+ static uint32_t GetCapability(InotifyCapability_t cap) throw (InotifyException);
+
+ /// Modifies a particular inotify capability/limit.
+ /**
+ * \param[in] cap capability/limit identifier
+ * \param[in] val new capability/limit value
+ * \throw InotifyException thrown if the given value cannot be set
+ * \attention Using this function requires root privileges.
+ * Beware of setting extensive values - it may seriously
+ * affect system performance and/or stability.
+ */
+ static void SetCapability(InotifyCapability_t cap, uint32_t val) throw (InotifyException);
+
+ /// Returns the maximum number of events in the kernel queue.
+ /**
+ * \return maximum number of events in the kernel queue
+ * \throw InotifyException thrown if the given value cannot be acquired
+ */
+ inline static uint32_t GetMaxEvents() throw (InotifyException)
+ {
+ return GetCapability(IN_MAX_EVENTS);
+ }
+
+ /// Sets the maximum number of events in the kernel queue.
+ /**
+ * \param[in] val new value
+ * \throw InotifyException thrown if the given value cannot be set
+ * \attention Using this function requires root privileges.
+ * Beware of setting extensive values - the greater value
+ * is set here the more physical memory may be used for the inotify
+ * infrastructure.
+ */
+ inline static void SetMaxEvents(uint32_t val) throw (InotifyException)
+ {
+ SetCapability(IN_MAX_EVENTS, val);
+ }
+
+ /// Returns the maximum number of inotify instances per process.
+ /**
+ * It means the maximum number of open inotify file descriptors
+ * per running process.
+ *
+ * \return maximum number of inotify instances
+ * \throw InotifyException thrown if the given value cannot be acquired
+ */
+ inline static uint32_t GetMaxInstances() throw (InotifyException)
+ {
+ return GetCapability(IN_MAX_INSTANCES);
+ }
+
+ /// Sets the maximum number of inotify instances per process.
+ /**
+ * \param[in] val new value
+ * \throw InotifyException thrown if the given value cannot be set
+ * \attention Using this function requires root privileges.
+ * Beware of setting extensive values - the greater value
+ * is set here the more physical memory may be used for the inotify
+ * infrastructure.
+ */
+ inline static void SetMaxInstances(uint32_t val) throw (InotifyException)
+ {
+ SetCapability(IN_MAX_INSTANCES, val);
+ }
+
+ /// Returns the maximum number of inotify watches per instance.
+ /**
+ * It means the maximum number of inotify watches per inotify
+ * file descriptor.
+ *
+ * \return maximum number of inotify watches
+ * \throw InotifyException thrown if the given value cannot be acquired
+ */
+ inline static uint32_t GetMaxWatches() throw (InotifyException)
+ {
+ return GetCapability(IN_MAX_WATCHES);
+ }
+
+ /// Sets the maximum number of inotify watches per instance.
+ /**
+ * \param[in] val new value
+ * \throw InotifyException thrown if the given value cannot be set
+ * \attention Using this function requires root privileges.
+ * Beware of setting extensive values - the greater value
+ * is set here the more physical memory may be used for the inotify
+ * infrastructure.
+ */
+ inline static void SetMaxWatches(uint32_t val) throw (InotifyException)
+ {
+ SetCapability(IN_MAX_WATCHES, val);
+ }
+
+private:
+ int m_fd; ///< file descriptor
+ IN_WATCH_MAP m_watches; ///< watches (by descriptors)
+ IN_WP_MAP m_paths; ///< watches (by paths)
+ unsigned char m_buf[INOTIFY_BUFLEN]; ///< buffer for events
+ std::deque<InotifyEvent> m_events; ///< event queue
+
+ IN_LOCK_DECL
+
+ friend class InotifyWatch;
+
+ static std::string GetCapabilityPath(InotifyCapability_t cap) throw (InotifyException);
+};
+
+
+#endif //_INOTIFYCXX_H_
+
bgstack15