Rev 29 | Rev 35 | Go to most recent revision | Only display areas with differences | Ignore whitespace | Details | Blame | Last modification | View Log | RSS feed
Rev 29 | Rev 33 | ||
---|---|---|---|
1 | 1 | ||
2 | /// inotify C++ interface header
|
2 | /// inotify C++ interface header
|
3 | /**
|
3 | /**
|
4 | * \file inotify-cxx.h
|
4 | * \file inotify-cxx.h
|
5 | *
|
5 | *
|
6 | * inotify C++ interface
|
6 | * inotify C++ interface
|
7 | *
|
7 | *
|
8 | * Copyright (C) 2006 Lukas Jelinek, <lukas@aiken.cz>
|
8 | * Copyright (C) 2006 Lukas Jelinek, <lukas@aiken.cz>
|
9 | *
|
9 | *
|
10 | * This program is free software; you can redistribute it and/or
|
10 | * This program is free software; you can redistribute it and/or
|
11 | * modify it under the terms of one of the following licenses:
|
11 | * modify it under the terms of one of the following licenses:
|
12 | *
|
12 | *
|
13 | * \li 1. X11-style license (see LICENSE-X11)
|
13 | * \li 1. X11-style license (see LICENSE-X11)
|
14 | * \li 2. GNU Lesser General Public License, version 2.1 (see LICENSE-LGPL)
|
14 | * \li 2. GNU Lesser General Public License, version 2.1 (see LICENSE-LGPL)
|
15 | * \li 3. GNU General Public License, version 2 (see LICENSE-GPL)
|
15 | * \li 3. GNU General Public License, version 2 (see LICENSE-GPL)
|
16 | *
|
16 | *
|
17 | * If you want to help with choosing the best license for you,
|
17 | * If you want to help with choosing the best license for you,
|
18 | * please visit http://www.gnu.org/licenses/license-list.html.
|
18 | * please visit http://www.gnu.org/licenses/license-list.html.
|
19 | *
|
19 | *
|
20 | */
|
20 | */
|
21 | 21 | ||
22 | 22 | ||
23 | 23 | ||
24 | 24 | ||
25 | 25 | ||
26 | #ifndef _INOTIFYCXX_H_
|
26 | #ifndef _INOTIFYCXX_H_
|
27 | #define _INOTIFYCXX_H_
|
27 | #define _INOTIFYCXX_H_
|
28 | 28 | ||
29 | #include <string>
|
29 | #include <string>
|
30 | #include <deque>
|
30 | #include <deque>
|
31 | #include <map>
|
31 | #include <map>
|
32 | 32 | ||
33 | // Please ensure that the following headers take the right place
|
33 | // Please ensure that the following headers take the right place
|
34 | #include <sys/syscall.h>
|
34 | #include <sys/syscall.h>
|
35 | #include <sys/inotify.h>
|
35 | #include <sys/inotify.h>
|
36 | 36 | ||
37 | // Use this if syscalls not defined
|
37 | // Use this if syscalls not defined
|
38 | #ifndef __NR_inotify_init
|
38 | #ifndef __NR_inotify_init
|
39 | #include <sys/inotify-syscalls.h>
|
39 | #include <sys/inotify-syscalls.h>
|
40 | #endif // __NR_inotify_init
|
40 | #endif // __NR_inotify_init
|
41 | 41 | ||
42 | /// Event struct size
|
42 | /// Event struct size
|
43 | #define INOTIFY_EVENT_SIZE (sizeof(struct inotify_event))
|
43 | #define INOTIFY_EVENT_SIZE (sizeof(struct inotify_event))
|
44 | 44 | ||
45 | /// Event buffer length
|
45 | /// Event buffer length
|
46 | #define INOTIFY_BUFLEN (1024 * (INOTIFY_EVENT_SIZE + 16))
|
46 | #define INOTIFY_BUFLEN (1024 * (INOTIFY_EVENT_SIZE + 16))
|
47 | 47 | ||
48 | /// Helper macro for creating exception messages.
|
48 | /// Helper macro for creating exception messages.
|
49 | /**
|
49 | /**
|
50 | * It prepends the message by the function name.
|
50 | * It prepends the message by the function name.
|
51 | */
|
51 | */
|
52 | #define IN_EXC_MSG(msg) (std::string(__PRETTY_FUNCTION__) + ": " + msg)
|
52 | #define IN_EXC_MSG(msg) (std::string(__PRETTY_FUNCTION__) + ": " + msg)
|
53 | 53 | ||
54 | /// inotify capability/limit identifiers
|
54 | /// inotify capability/limit identifiers
|
55 | typedef enum |
55 | typedef enum |
56 | {
|
56 | {
|
57 | IN_MAX_EVENTS = 0, ///< max. events in the kernel queue |
57 | IN_MAX_EVENTS = 0, ///< max. events in the kernel queue |
58 | IN_MAX_INSTANCES = 1, ///< max. inotify file descriptors per process |
58 | IN_MAX_INSTANCES = 1, ///< max. inotify file descriptors per process |
59 | IN_MAX_WATCHES = 2 ///< max. watches per file descriptor |
59 | IN_MAX_WATCHES = 2 ///< max. watches per file descriptor |
60 | } InotifyCapability_t; |
60 | } InotifyCapability_t; |
61 | 61 | ||
62 | /// inotify-cxx thread safety
|
62 | /// inotify-cxx thread safety
|
63 | /**
|
63 | /**
|
64 | * If this symbol is defined you can use this interface safely
|
64 | * If this symbol is defined you can use this interface safely
|
65 | * threaded applications. Remember that it slightly degrades
|
65 | * threaded applications. Remember that it slightly degrades
|
66 | * performance.
|
66 | * performance.
|
67 | *
|
67 | *
|
68 | * Even if INOTIFY_THREAD_SAFE is defined some classes stay
|
68 | * Even if INOTIFY_THREAD_SAFE is defined some classes stay
|
69 | * unsafe. If you must use them (must you?) in more than one
|
69 | * unsafe. If you must use them (must you?) in more than one
|
70 | * thread concurrently you need to implement explicite locking.
|
70 | * thread concurrently you need to implement explicite locking.
|
71 | *
|
71 | *
|
72 | * You need not to define INOTIFY_THREAD_SAFE in that cases
|
72 | * You need not to define INOTIFY_THREAD_SAFE in that cases
|
73 | * where the application is multithreaded but all the inotify
|
73 | * where the application is multithreaded but all the inotify
|
74 | * infrastructure will be managed only in one thread. This is
|
74 | * infrastructure will be managed only in one thread. This is
|
75 | * the recommended way.
|
75 | * the recommended way.
|
76 | *
|
76 | *
|
77 | * Locking may fail (it is very rare but not impossible). In this
|
77 | * Locking may fail (it is very rare but not impossible). In this
|
78 | * case an exception is thrown. But if unlocking fails in case
|
78 | * case an exception is thrown. But if unlocking fails in case
|
79 | * of an error it does nothing (this failure is ignored).
|
79 | * of an error it does nothing (this failure is ignored).
|
80 | */
|
80 | */
|
81 | #ifdef INOTIFY_THREAD_SAFE
|
81 | #ifdef INOTIFY_THREAD_SAFE
|
82 | 82 | ||
83 | #include <pthread.h>
|
83 | #include <pthread.h>
|
84 | 84 | ||
85 | #define IN_LOCK_DECL mutable pthread_rwlock_t __m_lock;
|
85 | #define IN_LOCK_DECL mutable pthread_rwlock_t __m_lock;
|
86 | 86 | ||
87 | #define IN_LOCK_INIT \
|
87 | #define IN_LOCK_INIT \
|
88 | { \
|
88 | { \
|
89 | pthread_rwlockattr_t attr; \
|
89 | pthread_rwlockattr_t attr; \
|
90 | int res = 0; \
|
90 | int res = 0; \
|
91 | if ((res = pthread_rwlockattr_init(&attr)) != 0) \
|
91 | if ((res = pthread_rwlockattr_init(&attr)) != 0) \
|
92 | throw InotifyException(IN_EXC_MSG("cannot initialize lock attributes"), res, this); \
|
92 | throw InotifyException(IN_EXC_MSG("cannot initialize lock attributes"), res, this); \
|
93 | if ((res = pthread_rwlockattr_setkind_np(&attr, PTHREAD_RWLOCK_PREFER_WRITER_NP)) != 0) \
|
93 | if ((res = pthread_rwlockattr_setkind_np(&attr, PTHREAD_RWLOCK_PREFER_WRITER_NP)) != 0) \
|
94 | throw InotifyException(IN_EXC_MSG("cannot set lock kind"), res, this); \
|
94 | throw InotifyException(IN_EXC_MSG("cannot set lock kind"), res, this); \
|
95 | if ((res = pthread_rwlock_init(&__m_lock, &attr)) != 0) \
|
95 | if ((res = pthread_rwlock_init(&__m_lock, &attr)) != 0) \
|
96 | throw InotifyException(IN_EXC_MSG("cannot initialize lock"), res, this); \
|
96 | throw InotifyException(IN_EXC_MSG("cannot initialize lock"), res, this); \
|
97 | pthread_rwlockattr_destroy(&attr); \
|
97 | pthread_rwlockattr_destroy(&attr); \
|
98 | }
|
98 | }
|
99 | 99 | ||
100 | #define IN_LOCK_DONE pthread_rwlock_destroy(&__m_lock);
|
100 | #define IN_LOCK_DONE pthread_rwlock_destroy(&__m_lock);
|
101 | 101 | ||
102 | #define IN_READ_BEGIN \
|
102 | #define IN_READ_BEGIN \
|
103 | { \
|
103 | { \
|
104 | int res = pthread_rwlock_rdlock(&__m_lock); \
|
104 | int res = pthread_rwlock_rdlock(&__m_lock); \
|
105 | if (res != 0) \
|
105 | if (res != 0) \
|
106 | throw InotifyException(IN_EXC_MSG("locking for reading failed"), res, (void*) this); \
|
106 | throw InotifyException(IN_EXC_MSG("locking for reading failed"), res, (void*) this); \
|
107 | }
|
107 | }
|
108 | 108 | ||
109 | #define IN_READ_END \
|
109 | #define IN_READ_END \
|
110 | { \
|
110 | { \
|
111 | int res = pthread_rwlock_unlock(&__m_lock); \
|
111 | int res = pthread_rwlock_unlock(&__m_lock); \
|
112 | if (res != 0) \
|
112 | if (res != 0) \
|
113 | throw InotifyException(IN_EXC_MSG("unlocking failed"), res, (void*) this); \
|
113 | throw InotifyException(IN_EXC_MSG("unlocking failed"), res, (void*) this); \
|
114 | }
|
114 | }
|
115 | 115 | ||
116 | #define IN_READ_END_NOTHROW pthread_rwlock_unlock(&__m_lock);
|
116 | #define IN_READ_END_NOTHROW pthread_rwlock_unlock(&__m_lock);
|
117 | 117 | ||
118 | #define IN_WRITE_BEGIN \
|
118 | #define IN_WRITE_BEGIN \
|
119 | { \
|
119 | { \
|
120 | int res = pthread_rwlock_wrlock(&__m_lock); \
|
120 | int res = pthread_rwlock_wrlock(&__m_lock); \
|
121 | if (res != 0) \
|
121 | if (res != 0) \
|
122 | throw InotifyException(IN_EXC_MSG("locking for writing failed"), res, (void*) this); \
|
122 | throw InotifyException(IN_EXC_MSG("locking for writing failed"), res, (void*) this); \
|
123 | }
|
123 | }
|
124 | 124 | ||
125 | #define IN_WRITE_END IN_READ_END
|
125 | #define IN_WRITE_END IN_READ_END
|
126 | #define IN_WRITE_END_NOTHROW IN_READ_END_NOTHROW
|
126 | #define IN_WRITE_END_NOTHROW IN_READ_END_NOTHROW
|
127 | 127 | ||
128 | #else // INOTIFY_THREAD_SAFE
|
128 | #else // INOTIFY_THREAD_SAFE
|
129 | 129 | ||
130 | #define IN_LOCK_DECL
|
130 | #define IN_LOCK_DECL
|
131 | #define IN_LOCK_INIT
|
131 | #define IN_LOCK_INIT
|
132 | #define IN_LOCK_DONE
|
132 | #define IN_LOCK_DONE
|
133 | #define IN_READ_BEGIN
|
133 | #define IN_READ_BEGIN
|
134 | #define IN_READ_END
|
134 | #define IN_READ_END
|
135 | #define IN_READ_END_NOTHROW
|
135 | #define IN_READ_END_NOTHROW
|
136 | #define IN_WRITE_BEGIN
|
136 | #define IN_WRITE_BEGIN
|
137 | #define IN_WRITE_END
|
137 | #define IN_WRITE_END
|
138 | #define IN_WRITE_END_NOTHROW
|
138 | #define IN_WRITE_END_NOTHROW
|
139 | 139 | ||
140 | #endif // INOTIFY_THREAD_SAFE
|
140 | #endif // INOTIFY_THREAD_SAFE
|
141 | 141 | ||
142 | 142 | ||
143 | 143 | ||
144 | 144 | ||
145 | // forward declaration
|
145 | // forward declaration
|
146 | class InotifyWatch; |
146 | class InotifyWatch; |
147 | class Inotify; |
147 | class Inotify; |
148 | 148 | ||
149 | 149 | ||
150 | /// Class for inotify exceptions
|
150 | /// Class for inotify exceptions
|
151 | /**
|
151 | /**
|
152 | * This class allows to acquire information about exceptional
|
152 | * This class allows to acquire information about exceptional
|
153 | * events. It makes easier to log or display error messages
|
153 | * events. It makes easier to log or display error messages
|
154 | * and to identify problematic code locations.
|
154 | * and to identify problematic code locations.
|
155 | *
|
155 | *
|
156 | * Although this class is basically thread-safe it is not intended
|
156 | * Although this class is basically thread-safe it is not intended
|
157 | * to be shared between threads.
|
157 | * to be shared between threads.
|
158 | */
|
158 | */
|
159 | class InotifyException
|
159 | class InotifyException
|
160 | {
|
160 | {
|
161 | public: |
161 | public: |
162 | /// Constructor
|
162 | /// Constructor
|
163 | /**
|
163 | /**
|
164 | * \param[in] rMsg message
|
164 | * \param[in] rMsg message
|
165 | * \param[in] iErr error number (see errno.h)
|
165 | * \param[in] iErr error number (see errno.h)
|
166 | * \param[in] pSrc source
|
166 | * \param[in] pSrc source
|
167 | */
|
167 | */
|
168 | InotifyException(const std::string& rMsg = "", int iErr = 0, void* pSrc = NULL) |
168 | InotifyException(const std::string& rMsg = "", int iErr = 0, void* pSrc = NULL) |
169 | : m_msg(rMsg), |
169 | : m_msg(rMsg), |
170 | m_err(iErr) |
170 | m_err(iErr) |
171 | {
|
171 | {
|
172 | m_pSrc = pSrc; |
172 | m_pSrc = pSrc; |
173 | }
|
173 | }
|
174 | 174 | ||
175 | /// Returns the exception message.
|
175 | /// Returns the exception message.
|
176 | /**
|
176 | /**
|
177 | * \return message
|
177 | * \return message
|
178 | */
|
178 | */
|
179 | inline const std::string& GetMessage() const |
179 | inline const std::string& GetMessage() const |
180 | {
|
180 | {
|
181 | return m_msg; |
181 | return m_msg; |
182 | }
|
182 | }
|
183 | 183 | ||
184 | /// Returns the exception error number.
|
184 | /// Returns the exception error number.
|
185 | /**
|
185 | /**
|
186 | * If not applicable this value is 0 (zero).
|
186 | * If not applicable this value is 0 (zero).
|
187 | *
|
187 | *
|
188 | * \return error number (standardized; see errno.h)
|
188 | * \return error number (standardized; see errno.h)
|
189 | */
|
189 | */
|
190 | inline int GetErrorNumber() const |
190 | inline int GetErrorNumber() const |
191 | {
|
191 | {
|
192 | return m_err; |
192 | return m_err; |
193 | }
|
193 | }
|
194 | 194 | ||
195 | /// Returns the exception source.
|
195 | /// Returns the exception source.
|
196 | /**
|
196 | /**
|
197 | * \return source
|
197 | * \return source
|
198 | */
|
198 | */
|
199 | inline void* GetSource() const |
199 | inline void* GetSource() const |
200 | {
|
200 | {
|
201 | return m_pSrc; |
201 | return m_pSrc; |
202 | }
|
202 | }
|
203 | 203 | ||
204 | protected: |
204 | protected: |
205 | std::string m_msg; ///< message |
205 | std::string m_msg; ///< message |
206 | int m_err; ///< error number |
206 | int m_err; ///< error number |
207 | mutable void* m_pSrc; ///< source |
207 | mutable void* m_pSrc; ///< source |
208 | }; |
208 | }; |
209 | 209 | ||
210 | 210 | ||
211 | /// inotify event class
|
211 | /// inotify event class
|
212 | /**
|
212 | /**
|
213 | * It holds all information about inotify event and provides
|
213 | * It holds all information about inotify event and provides
|
214 | * access to its particular values.
|
214 | * access to its particular values.
|
215 | *
|
215 | *
|
216 | * This class is not (and is not intended to be) thread-safe
|
216 | * This class is not (and is not intended to be) thread-safe
|
217 | * and therefore it must not be used concurrently in multiple
|
217 | * and therefore it must not be used concurrently in multiple
|
218 | * threads.
|
218 | * threads.
|
219 | */
|
219 | */
|
220 | class InotifyEvent
|
220 | class InotifyEvent
|
221 | {
|
221 | {
|
222 | public: |
222 | public: |
223 | /// Constructor.
|
223 | /// Constructor.
|
224 | /**
|
224 | /**
|
225 | * Creates a plain event.
|
225 | * Creates a plain event.
|
226 | */
|
226 | */
|
227 | InotifyEvent() |
227 | InotifyEvent() |
228 | : m_uMask(0), |
228 | : m_uMask(0), |
229 | m_uCookie(0) |
229 | m_uCookie(0) |
230 | {
|
230 | {
|
231 | m_pWatch = NULL; |
231 | m_pWatch = NULL; |
232 | }
|
232 | }
|
233 | 233 | ||
234 | /// Constructor.
|
234 | /// Constructor.
|
235 | /**
|
235 | /**
|
236 | * Creates an event based on inotify event data.
|
236 | * Creates an event based on inotify event data.
|
237 | * For NULL pointers it works the same way as InotifyEvent().
|
237 | * For NULL pointers it works the same way as InotifyEvent().
|
238 | *
|
238 | *
|
239 | * \param[in] pEvt event data
|
239 | * \param[in] pEvt event data
|
240 | * \param[in] pWatch inotify watch
|
240 | * \param[in] pWatch inotify watch
|
241 | */
|
241 | */
|
242 | InotifyEvent(const struct inotify_event* pEvt, InotifyWatch* pWatch) |
242 | InotifyEvent(const struct inotify_event* pEvt, InotifyWatch* pWatch) |
243 | : m_uMask(0), |
243 | : m_uMask(0), |
244 | m_uCookie(0) |
244 | m_uCookie(0) |
245 | {
|
245 | {
|
246 | if (pEvt != NULL) { |
246 | if (pEvt != NULL) { |
247 | m_uMask = (uint32_t) pEvt->mask; |
247 | m_uMask = (uint32_t) pEvt->mask; |
248 | m_uCookie = (uint32_t) pEvt->cookie; |
248 | m_uCookie = (uint32_t) pEvt->cookie; |
249 | if (pEvt->name != NULL) |
249 | if (pEvt->name != NULL) |
250 | m_name = pEvt->name; |
250 | m_name = pEvt->name; |
251 | m_pWatch = pWatch; |
251 | m_pWatch = pWatch; |
252 | }
|
252 | }
|
253 | else { |
253 | else { |
254 | m_pWatch = NULL; |
254 | m_pWatch = NULL; |
255 | }
|
255 | }
|
256 | }
|
256 | }
|
257 | 257 | ||
258 | /// Destructor.
|
258 | /// Destructor.
|
259 | ~InotifyEvent() {} |
259 | ~InotifyEvent() {} |
260 | 260 | ||
261 | /// Returns the event watch descriptor.
|
261 | /// Returns the event watch descriptor.
|
262 | /**
|
262 | /**
|
263 | * \return watch descriptor
|
263 | * \return watch descriptor
|
264 | *
|
264 | *
|
265 | * \sa InotifyWatch::GetDescriptor()
|
265 | * \sa InotifyWatch::GetDescriptor()
|
266 | */
|
266 | */
|
267 | int32_t GetDescriptor() const; |
267 | int32_t GetDescriptor() const; |
268 | 268 | ||
269 | /// Returns the event mask.
|
269 | /// Returns the event mask.
|
270 | /**
|
270 | /**
|
271 | * \return event mask
|
271 | * \return event mask
|
272 | *
|
272 | *
|
273 | * \sa InotifyWatch::GetMask()
|
273 | * \sa InotifyWatch::GetMask()
|
274 | */
|
274 | */
|
275 | inline uint32_t GetMask() const |
275 | inline uint32_t GetMask() const |
276 | {
|
276 | {
|
277 | return m_uMask; |
277 | return m_uMask; |
278 | }
|
278 | }
|
279 | 279 | ||
280 | /// Checks a value for the event type.
|
280 | /// Checks a value for the event type.
|
281 | /**
|
281 | /**
|
282 | * \param[in] uValue checked value
|
282 | * \param[in] uValue checked value
|
283 | * \param[in] uType type which is checked for
|
283 | * \param[in] uType type which is checked for
|
284 | * \return true = the value contains the given type, false = otherwise
|
284 | * \return true = the value contains the given type, false = otherwise
|
285 | */
|
285 | */
|
286 | inline static bool IsType(uint32_t uValue, uint32_t uType) |
286 | inline static bool IsType(uint32_t uValue, uint32_t uType) |
287 | {
|
287 | {
|
288 | return ((uValue & uType) != 0) && ((~uValue & uType) == 0); |
288 | return ((uValue & uType) != 0) && ((~uValue & uType) == 0); |
289 | }
|
289 | }
|
290 | 290 | ||
291 | /// Checks for the event type.
|
291 | /// Checks for the event type.
|
292 | /**
|
292 | /**
|
293 | * \param[in] uType type which is checked for
|
293 | * \param[in] uType type which is checked for
|
294 | * \return true = event mask contains the given type, false = otherwise
|
294 | * \return true = event mask contains the given type, false = otherwise
|
295 | */
|
295 | */
|
296 | inline bool IsType(uint32_t uType) const |
296 | inline bool IsType(uint32_t uType) const |
297 | {
|
297 | {
|
298 | return IsType(m_uMask, uType); |
298 | return IsType(m_uMask, uType); |
299 | }
|
299 | }
|
300 | 300 | ||
301 | /// Returns the event cookie.
|
301 | /// Returns the event cookie.
|
302 | /**
|
302 | /**
|
303 | * \return event cookie
|
303 | * \return event cookie
|
304 | */
|
304 | */
|
305 | inline uint32_t GetCookie() const |
305 | inline uint32_t GetCookie() const |
306 | {
|
306 | {
|
307 | return m_uCookie; |
307 | return m_uCookie; |
308 | }
|
308 | }
|
309 | 309 | ||
310 | /// Returns the event name length.
|
310 | /// Returns the event name length.
|
311 | /**
|
311 | /**
|
312 | * \return event name length
|
312 | * \return event name length
|
313 | */
|
313 | */
|
314 | inline uint32_t GetLength() const |
314 | inline uint32_t GetLength() const |
315 | {
|
315 | {
|
316 | return (uint32_t) m_name.length(); |
316 | return (uint32_t) m_name.length(); |
317 | }
|
317 | }
|
318 | 318 | ||
319 | /// Returns the event name.
|
319 | /// Returns the event name.
|
320 | /**
|
320 | /**
|
321 | * \return event name
|
321 | * \return event name
|
322 | */
|
322 | */
|
323 | inline const std::string& GetName() const |
323 | inline const std::string& GetName() const |
324 | {
|
324 | {
|
325 | return m_name; |
325 | return m_name; |
326 | }
|
326 | }
|
327 | 327 | ||
328 | /// Extracts the event name.
|
328 | /// Extracts the event name.
|
329 | /**
|
329 | /**
|
330 | * \param[out] rName event name
|
330 | * \param[out] rName event name
|
331 | */
|
331 | */
|
332 | inline void GetName(std::string& rName) const |
332 | inline void GetName(std::string& rName) const |
333 | {
|
333 | {
|
334 | rName = GetName(); |
334 | rName = GetName(); |
335 | }
|
335 | }
|
336 | 336 | ||
337 | /// Returns the source watch.
|
337 | /// Returns the source watch.
|
338 | /**
|
338 | /**
|
339 | * \return source watch
|
339 | * \return source watch
|
340 | */
|
340 | */
|
341 | inline InotifyWatch* GetWatch() |
341 | inline InotifyWatch* GetWatch() |
342 | {
|
342 | {
|
343 | return m_pWatch; |
343 | return m_pWatch; |
344 | }
|
344 | }
|
345 | 345 | ||
346 | /// Finds the appropriate mask for a name.
|
346 | /// Finds the appropriate mask for a name.
|
347 | /**
|
347 | /**
|
348 | * \param[in] rName mask name
|
348 | * \param[in] rName mask name
|
349 | * \return mask for name; 0 on failure
|
349 | * \return mask for name; 0 on failure
|
350 | */
|
350 | */
|
351 | static uint32_t GetMaskByName(const std::string& rName); |
351 | static uint32_t GetMaskByName(const std::string& rName); |
352 | 352 | ||
353 | /// Fills the string with all types contained in an event mask value.
|
353 | /// Fills the string with all types contained in an event mask value.
|
354 | /**
|
354 | /**
|
355 | * \param[in] uValue event mask value
|
355 | * \param[in] uValue event mask value
|
356 | * \param[out] rStr dumped event types
|
356 | * \param[out] rStr dumped event types
|
357 | */
|
357 | */
|
358 | static void DumpTypes(uint32_t uValue, std::string& rStr); |
358 | static void DumpTypes(uint32_t uValue, std::string& rStr); |
359 | 359 | ||
360 | /// Fills the string with all types contained in the event mask.
|
360 | /// Fills the string with all types contained in the event mask.
|
361 | /**
|
361 | /**
|
362 | * \param[out] rStr dumped event types
|
362 | * \param[out] rStr dumped event types
|
363 | */
|
363 | */
|
364 | void DumpTypes(std::string& rStr) const; |
364 | void DumpTypes(std::string& rStr) const; |
365 | 365 | ||
366 | private: |
366 | private: |
367 | uint32_t m_uMask; ///< mask |
367 | uint32_t m_uMask; ///< mask |
368 | uint32_t m_uCookie; ///< cookie |
368 | uint32_t m_uCookie; ///< cookie |
369 | std::string m_name; ///< name |
369 | std::string m_name; ///< name |
370 | InotifyWatch* m_pWatch; ///< source watch |
370 | InotifyWatch* m_pWatch; ///< source watch |
371 | }; |
371 | }; |
372 | 372 | ||
373 | 373 | ||
374 | 374 | ||
375 | /// inotify watch class
|
375 | /// inotify watch class
|
376 | /**
|
376 | /**
|
377 | * It holds information about the inotify watch on a particular
|
377 | * It holds information about the inotify watch on a particular
|
378 | * inode.
|
378 | * inode.
|
379 | *
|
379 | *
|
380 | * If the INOTIFY_THREAD_SAFE is defined this class is thread-safe.
|
380 | * If the INOTIFY_THREAD_SAFE is defined this class is thread-safe.
|
381 | */
|
381 | */
|
382 | class InotifyWatch
|
382 | class InotifyWatch
|
383 | {
|
383 | {
|
384 | public: |
384 | public: |
385 | /// Constructor.
|
385 | /// Constructor.
|
386 | /**
|
386 | /**
|
387 | * Creates an inotify watch. Because this watch is
|
387 | * Creates an inotify watch. Because this watch is
|
388 | * inactive it has an invalid descriptor (-1).
|
388 | * inactive it has an invalid descriptor (-1).
|
389 | *
|
389 | *
|
390 | * \param[in] rPath watched file path
|
390 | * \param[in] rPath watched file path
|
391 | * \param[in] uMask mask for events
|
391 | * \param[in] uMask mask for events
|
392 | * \param[in] fEnabled events enabled yes/no
|
392 | * \param[in] fEnabled events enabled yes/no
|
393 | */
|
393 | */
|
394 | InotifyWatch(const std::string& rPath, int32_t uMask, bool fEnabled = true) |
394 | InotifyWatch(const std::string& rPath, int32_t uMask, bool fEnabled = true) |
395 | : m_path(rPath), |
395 | : m_path(rPath), |
396 | m_uMask(uMask), |
396 | m_uMask(uMask), |
397 | m_wd((int32_t) -1), |
397 | m_wd((int32_t) -1), |
398 | m_fEnabled(fEnabled) |
398 | m_fEnabled(fEnabled) |
399 | {
|
399 | {
|
400 | IN_LOCK_INIT |
400 | IN_LOCK_INIT |
401 | }
|
401 | }
|
402 | 402 | ||
403 | /// Destructor.
|
403 | /// Destructor.
|
404 | ~InotifyWatch() |
404 | ~InotifyWatch() |
405 | {
|
405 | {
|
406 | IN_LOCK_DONE |
406 | IN_LOCK_DONE |
407 | }
|
407 | }
|
408 | 408 | ||
409 | /// Returns the watch descriptor.
|
409 | /// Returns the watch descriptor.
|
410 | /**
|
410 | /**
|
411 | * \return watch descriptor; -1 for inactive watch
|
411 | * \return watch descriptor; -1 for inactive watch
|
412 | */
|
412 | */
|
413 | inline int32_t GetDescriptor() const |
413 | inline int32_t GetDescriptor() const |
414 | {
|
414 | {
|
415 | return m_wd; |
415 | return m_wd; |
416 | }
|
416 | }
|
417 | 417 | ||
418 | /// Returns the watched file path.
|
418 | /// Returns the watched file path.
|
419 | /**
|
419 | /**
|
420 | * \return file path
|
420 | * \return file path
|
421 | */
|
421 | */
|
422 | inline const std::string& GetPath() const |
422 | inline const std::string& GetPath() const |
423 | {
|
423 | {
|
424 | return m_path; |
424 | return m_path; |
425 | }
|
425 | }
|
426 | 426 | ||
427 | /// Returns the watch event mask.
|
427 | /// Returns the watch event mask.
|
428 | /**
|
428 | /**
|
429 | * \return event mask
|
429 | * \return event mask
|
430 | */
|
430 | */
|
431 | inline uint32_t GetMask() const |
431 | inline uint32_t GetMask() const |
432 | {
|
432 | {
|
433 | return (uint32_t) m_uMask; |
433 | return (uint32_t) m_uMask; |
434 | }
|
434 | }
|
435 | 435 | ||
436 | /// Sets the watch event mask.
|
436 | /// Sets the watch event mask.
|
437 | /**
|
437 | /**
|
438 | * If the watch is active (added to an instance of Inotify)
|
438 | * If the watch is active (added to an instance of Inotify)
|
439 | * this method may fail due to unsuccessful re-setting
|
439 | * this method may fail due to unsuccessful re-setting
|
440 | * the watch in the kernel.
|
440 | * the watch in the kernel.
|
441 | *
|
441 | *
|
442 | * \param[in] uMask event mask
|
442 | * \param[in] uMask event mask
|
443 | *
|
443 | *
|
444 | * \throw InotifyException thrown if changing fails
|
444 | * \throw InotifyException thrown if changing fails
|
445 | */
|
445 | */
|
446 | void SetMask(uint32_t uMask) throw (InotifyException); |
446 | void SetMask(uint32_t uMask) throw (InotifyException); |
447 | 447 | ||
448 | /// Returns the appropriate inotify class instance.
|
448 | /// Returns the appropriate inotify class instance.
|
449 | /**
|
449 | /**
|
450 | * \return inotify instance
|
450 | * \return inotify instance
|
451 | */
|
451 | */
|
452 | inline Inotify* GetInotify() |
452 | inline Inotify* GetInotify() |
453 | {
|
453 | {
|
454 | return m_pInotify; |
454 | return m_pInotify; |
455 | }
|
455 | }
|
456 | 456 | ||
457 | /// Enables/disables the watch.
|
457 | /// Enables/disables the watch.
|
458 | /**
|
458 | /**
|
459 | * If the watch is active (added to an instance of Inotify)
|
459 | * If the watch is active (added to an instance of Inotify)
|
460 | * this method may fail due to unsuccessful re-setting
|
460 | * this method may fail due to unsuccessful re-setting
|
461 | * the watch in the kernel.
|
461 | * the watch in the kernel.
|
462 | *
|
462 | *
|
463 | * Re-setting the current state has no effect.
|
463 | * Re-setting the current state has no effect.
|
464 | *
|
464 | *
|
465 | * \param[in] fEnabled set enabled yes/no
|
465 | * \param[in] fEnabled set enabled yes/no
|
466 | *
|
466 | *
|
467 | * \throw InotifyException thrown if enabling/disabling fails
|
467 | * \throw InotifyException thrown if enabling/disabling fails
|
468 | */
|
468 | */
|
469 | void SetEnabled(bool fEnabled) throw (InotifyException); |
469 | void SetEnabled(bool fEnabled) throw (InotifyException); |
470 | 470 | ||
471 | /// Checks whether the watch is enabled.
|
471 | /// Checks whether the watch is enabled.
|
472 | /**
|
472 | /**
|
473 | * \return true = enables, false = disabled
|
473 | * \return true = enables, false = disabled
|
474 | */
|
474 | */
|
475 | inline bool IsEnabled() const |
475 | inline bool IsEnabled() const |
476 | {
|
476 | {
|
477 | return m_fEnabled; |
477 | return m_fEnabled; |
478 | }
|
478 | }
|
479 | 479 | ||
480 | /// Checks whether the watch is recursive.
|
480 | /// Checks whether the watch is recursive.
|
481 | /**
|
481 | /**
|
482 | * A recursive watch monitors a directory itself and all
|
482 | * A recursive watch monitors a directory itself and all
|
483 | * its subdirectories. This watch is a logical object
|
483 | * its subdirectories. This watch is a logical object
|
484 | * which may have many underlying kernel watches.
|
484 | * which may have many underlying kernel watches.
|
485 | *
|
485 | *
|
486 | * \return currently always false (recursive watches not yet supported)
|
486 | * \return currently always false (recursive watches not yet supported)
|
487 | * \attention Recursive watches are currently NOT supported.
|
487 | * \attention Recursive watches are currently NOT supported.
|
488 | * They are planned for future versions.
|
488 | * They are planned for future versions.
|
489 | */
|
489 | */
|
490 | inline bool IsRecursive() const |
490 | inline bool IsRecursive() const |
491 | {
|
491 | {
|
492 | return false; |
492 | return false; |
493 | }
|
493 | }
|
494 | 494 | ||
495 | private: |
495 | private: |
496 | friend class Inotify; |
496 | friend class Inotify; |
497 | 497 | ||
498 | std::string m_path; ///< watched file path |
498 | std::string m_path; ///< watched file path |
499 | uint32_t m_uMask; ///< event mask |
499 | uint32_t m_uMask; ///< event mask |
500 | int32_t m_wd; ///< watch descriptor |
500 | int32_t m_wd; ///< watch descriptor |
501 | Inotify* m_pInotify; ///< inotify object |
501 | Inotify* m_pInotify; ///< inotify object |
502 | bool m_fEnabled; ///< events enabled yes/no |
502 | bool m_fEnabled; ///< events enabled yes/no |
503 | 503 | ||
504 | IN_LOCK_DECL |
504 | IN_LOCK_DECL |
- | 505 | ||
- | 506 | /// Disables the watch (if it has the one-shot flag).
|
|
- | 507 | /**
|
|
- | 508 | * This method must be called after receiving an event.
|
|
- | 509 | * It ensures the watch object is consistent with the kernel
|
|
- | 510 | * data.
|
|
- | 511 | */
|
|
- | 512 | void OnOneshotEvent(); |
|
505 | }; |
513 | }; |
506 | 514 | ||
507 | 515 | ||
508 | /// Mapping from watch descriptors to watch objects.
|
516 | /// Mapping from watch descriptors to watch objects.
|
509 | typedef std::map<int32_t, InotifyWatch*> IN_WATCH_MAP; |
517 | typedef std::map<int32_t, InotifyWatch*> IN_WATCH_MAP; |
510 | 518 | ||
511 | /// Mapping from paths to watch objects.
|
519 | /// Mapping from paths to watch objects.
|
512 | typedef std::map<std::string, InotifyWatch*> IN_WP_MAP; |
520 | typedef std::map<std::string, InotifyWatch*> IN_WP_MAP; |
513 | 521 | ||
514 | 522 | ||
515 | /// inotify class
|
523 | /// inotify class
|
516 | /**
|
524 | /**
|
517 | * It holds information about the inotify device descriptor
|
525 | * It holds information about the inotify device descriptor
|
518 | * and manages the event queue.
|
526 | * and manages the event queue.
|
519 | *
|
527 | *
|
520 | * If the INOTIFY_THREAD_SAFE is defined this class is thread-safe.
|
528 | * If the INOTIFY_THREAD_SAFE is defined this class is thread-safe.
|
521 | */
|
529 | */
|
522 | class Inotify
|
530 | class Inotify
|
523 | {
|
531 | {
|
524 | public: |
532 | public: |
525 | /// Constructor.
|
533 | /// Constructor.
|
526 | /**
|
534 | /**
|
527 | * Creates and initializes an instance of inotify communication
|
535 | * Creates and initializes an instance of inotify communication
|
528 | * object (opens the inotify device).
|
536 | * object (opens the inotify device).
|
529 | *
|
537 | *
|
530 | * \throw InotifyException thrown if inotify isn't available
|
538 | * \throw InotifyException thrown if inotify isn't available
|
531 | */
|
539 | */
|
532 | Inotify() throw (InotifyException); |
540 | Inotify() throw (InotifyException); |
533 | 541 | ||
534 | /// Destructor.
|
542 | /// Destructor.
|
535 | /**
|
543 | /**
|
536 | * Calls Close() due to clean-up.
|
544 | * Calls Close() due to clean-up.
|
537 | */
|
545 | */
|
538 | ~Inotify(); |
546 | ~Inotify(); |
539 | 547 | ||
540 | /// Removes all watches and closes the inotify device.
|
548 | /// Removes all watches and closes the inotify device.
|
541 | void Close(); |
549 | void Close(); |
542 | 550 | ||
543 | /// Adds a new watch.
|
551 | /// Adds a new watch.
|
544 | /**
|
552 | /**
|
545 | * \param[in] pWatch inotify watch
|
553 | * \param[in] pWatch inotify watch
|
546 | *
|
554 | *
|
547 | * \throw InotifyException thrown if adding failed
|
555 | * \throw InotifyException thrown if adding failed
|
548 | */
|
556 | */
|
549 | void Add(InotifyWatch* pWatch) throw (InotifyException); |
557 | void Add(InotifyWatch* pWatch) throw (InotifyException); |
550 | 558 | ||
551 | /// Adds a new watch.
|
559 | /// Adds a new watch.
|
552 | /**
|
560 | /**
|
553 | * \param[in] rWatch inotify watch
|
561 | * \param[in] rWatch inotify watch
|
554 | *
|
562 | *
|
555 | * \throw InotifyException thrown if adding failed
|
563 | * \throw InotifyException thrown if adding failed
|
556 | */
|
564 | */
|
557 | inline void Add(InotifyWatch& rWatch) throw (InotifyException) |
565 | inline void Add(InotifyWatch& rWatch) throw (InotifyException) |
558 | {
|
566 | {
|
559 | Add(&rWatch); |
567 | Add(&rWatch); |
560 | }
|
568 | }
|
561 | 569 | ||
562 | /// Removes a watch.
|
570 | /// Removes a watch.
|
563 | /**
|
571 | /**
|
564 | * If the given watch is not present it does nothing.
|
572 | * If the given watch is not present it does nothing.
|
565 | *
|
573 | *
|
566 | * \param[in] pWatch inotify watch
|
574 | * \param[in] pWatch inotify watch
|
567 | *
|
575 | *
|
568 | * \throw InotifyException thrown if removing failed
|
576 | * \throw InotifyException thrown if removing failed
|
569 | */
|
577 | */
|
570 | void Remove(InotifyWatch* pWatch) throw (InotifyException); |
578 | void Remove(InotifyWatch* pWatch) throw (InotifyException); |
571 | 579 | ||
572 | /// Removes a watch.
|
580 | /// Removes a watch.
|
573 | /**
|
581 | /**
|
574 | * If the given watch is not present it does nothing.
|
582 | * If the given watch is not present it does nothing.
|
575 | *
|
583 | *
|
576 | * \param[in] rWatch inotify watch
|
584 | * \param[in] rWatch inotify watch
|
577 | *
|
585 | *
|
578 | * \throw InotifyException thrown if removing failed
|
586 | * \throw InotifyException thrown if removing failed
|
579 | */
|
587 | */
|
580 | inline void Remove(InotifyWatch& rWatch) throw (InotifyException) |
588 | inline void Remove(InotifyWatch& rWatch) throw (InotifyException) |
581 | {
|
589 | {
|
582 | Remove(&rWatch); |
590 | Remove(&rWatch); |
583 | }
|
591 | }
|
584 | 592 | ||
585 | /// Removes all watches.
|
593 | /// Removes all watches.
|
586 | void RemoveAll(); |
594 | void RemoveAll(); |
587 | 595 | ||
588 | /// Returns the count of watches.
|
596 | /// Returns the count of watches.
|
589 | /**
|
597 | /**
|
590 | * This is the total count of all watches (regardless whether
|
598 | * This is the total count of all watches (regardless whether
|
591 | * enabled or not).
|
599 | * enabled or not).
|
592 | *
|
600 | *
|
593 | * \return count of watches
|
601 | * \return count of watches
|
594 | *
|
602 | *
|
595 | * \sa GetEnabledCount()
|
603 | * \sa GetEnabledCount()
|
596 | */
|
604 | */
|
597 | inline size_t GetWatchCount() const |
605 | inline size_t GetWatchCount() const |
598 | {
|
606 | {
|
599 | IN_READ_BEGIN |
607 | IN_READ_BEGIN |
600 | size_t n = (size_t) m_paths.size(); |
608 | size_t n = (size_t) m_paths.size(); |
601 | IN_READ_END |
609 | IN_READ_END |
602 | return n; |
610 | return n; |
603 | }
|
611 | }
|
604 | 612 | ||
605 | /// Returns the count of enabled watches.
|
613 | /// Returns the count of enabled watches.
|
606 | /**
|
614 | /**
|
607 | * \return count of enabled watches
|
615 | * \return count of enabled watches
|
608 | *
|
616 | *
|
609 | * \sa GetWatchCount()
|
617 | * \sa GetWatchCount()
|
610 | */
|
618 | */
|
611 | inline size_t GetEnabledCount() const |
619 | inline size_t GetEnabledCount() const |
612 | {
|
620 | {
|
613 | IN_READ_BEGIN |
621 | IN_READ_BEGIN |
614 | size_t n = (size_t) m_watches.size(); |
622 | size_t n = (size_t) m_watches.size(); |
615 | IN_READ_END |
623 | IN_READ_END |
616 | return n; |
624 | return n; |
617 | }
|
625 | }
|
618 | 626 | ||
619 | /// Waits for inotify events.
|
627 | /// Waits for inotify events.
|
620 | /**
|
628 | /**
|
621 | * It waits until one or more events occur. When called
|
629 | * It waits until one or more events occur. When called
|
622 | * in nonblocking mode it only retrieves occurred events
|
630 | * in nonblocking mode it only retrieves occurred events
|
623 | * to the internal queue and exits.
|
631 | * to the internal queue and exits.
|
624 | *
|
632 | *
|
625 | * \param[in] fNoIntr if true it re-calls the system call after a handled signal
|
633 | * \param[in] fNoIntr if true it re-calls the system call after a handled signal
|
626 | *
|
634 | *
|
627 | * \throw InotifyException thrown if reading events failed
|
635 | * \throw InotifyException thrown if reading events failed
|
628 | *
|
636 | *
|
629 | * \sa SetNonBlock()
|
637 | * \sa SetNonBlock()
|
630 | */
|
638 | */
|
631 | void WaitForEvents(bool fNoIntr = false) throw (InotifyException); |
639 | void WaitForEvents(bool fNoIntr = false) throw (InotifyException); |
632 | 640 | ||
633 | /// Returns the count of received and queued events.
|
641 | /// Returns the count of received and queued events.
|
634 | /**
|
642 | /**
|
635 | * This number is related to the events in the queue inside
|
643 | * This number is related to the events in the queue inside
|
636 | * this object, not to the events pending in the kernel.
|
644 | * this object, not to the events pending in the kernel.
|
637 | *
|
645 | *
|
638 | * \return count of events
|
646 | * \return count of events
|
639 | */
|
647 | */
|
640 | inline size_t GetEventCount() |
648 | inline size_t GetEventCount() |
641 | {
|
649 | {
|
642 | IN_READ_BEGIN |
650 | IN_READ_BEGIN |
643 | size_t n = (size_t) m_events.size(); |
651 | size_t n = (size_t) m_events.size(); |
644 | IN_READ_END |
652 | IN_READ_END |
645 | return n; |
653 | return n; |
646 | }
|
654 | }
|
647 | 655 | ||
648 | /// Extracts a queued inotify event.
|
656 | /// Extracts a queued inotify event.
|
649 | /**
|
657 | /**
|
650 | * The extracted event is removed from the queue.
|
658 | * The extracted event is removed from the queue.
|
651 | * If the pointer is NULL it does nothing.
|
659 | * If the pointer is NULL it does nothing.
|
652 | *
|
660 | *
|
653 | * \param[in,out] pEvt event object
|
661 | * \param[in,out] pEvt event object
|
654 | *
|
662 | *
|
655 | * \throw InotifyException thrown if the provided pointer is NULL
|
663 | * \throw InotifyException thrown if the provided pointer is NULL
|
656 | */
|
664 | */
|
657 | bool GetEvent(InotifyEvent* pEvt) throw (InotifyException); |
665 | bool GetEvent(InotifyEvent* pEvt) throw (InotifyException); |
658 | 666 | ||
659 | /// Extracts a queued inotify event.
|
667 | /// Extracts a queued inotify event.
|
660 | /**
|
668 | /**
|
661 | * The extracted event is removed from the queue.
|
669 | * The extracted event is removed from the queue.
|
662 | *
|
670 | *
|
663 | * \param[in,out] rEvt event object
|
671 | * \param[in,out] rEvt event object
|
664 | *
|
672 | *
|
665 | * \throw InotifyException thrown only in very anomalous cases
|
673 | * \throw InotifyException thrown only in very anomalous cases
|
666 | */
|
674 | */
|
667 | bool GetEvent(InotifyEvent& rEvt) throw (InotifyException) |
675 | bool GetEvent(InotifyEvent& rEvt) throw (InotifyException) |
668 | {
|
676 | {
|
669 | return GetEvent(&rEvt); |
677 | return GetEvent(&rEvt); |
670 | }
|
678 | }
|
671 | 679 | ||
672 | /// Extracts a queued inotify event (without removing).
|
680 | /// Extracts a queued inotify event (without removing).
|
673 | /**
|
681 | /**
|
674 | * The extracted event stays in the queue.
|
682 | * The extracted event stays in the queue.
|
675 | * If the pointer is NULL it does nothing.
|
683 | * If the pointer is NULL it does nothing.
|
676 | *
|
684 | *
|
677 | * \param[in,out] pEvt event object
|
685 | * \param[in,out] pEvt event object
|
678 | *
|
686 | *
|
679 | * \throw InotifyException thrown if the provided pointer is NULL
|
687 | * \throw InotifyException thrown if the provided pointer is NULL
|
680 | */
|
688 | */
|
681 | bool PeekEvent(InotifyEvent* pEvt) throw (InotifyException); |
689 | bool PeekEvent(InotifyEvent* pEvt) throw (InotifyException); |
682 | 690 | ||
683 | /// Extracts a queued inotify event (without removing).
|
691 | /// Extracts a queued inotify event (without removing).
|
684 | /**
|
692 | /**
|
685 | * The extracted event stays in the queue.
|
693 | * The extracted event stays in the queue.
|
686 | *
|
694 | *
|
687 | * \param[in,out] rEvt event object
|
695 | * \param[in,out] rEvt event object
|
688 | *
|
696 | *
|
689 | * \throw InotifyException thrown only in very anomalous cases
|
697 | * \throw InotifyException thrown only in very anomalous cases
|
690 | */
|
698 | */
|
691 | bool PeekEvent(InotifyEvent& rEvt) throw (InotifyException) |
699 | bool PeekEvent(InotifyEvent& rEvt) throw (InotifyException) |
692 | {
|
700 | {
|
693 | return PeekEvent(&rEvt); |
701 | return PeekEvent(&rEvt); |
694 | }
|
702 | }
|
695 | 703 | ||
696 | /// Searches for a watch by a watch descriptor.
|
704 | /// Searches for a watch by a watch descriptor.
|
697 | /**
|
705 | /**
|
698 | * It tries to find a watch by the given descriptor.
|
706 | * It tries to find a watch by the given descriptor.
|
699 | *
|
707 | *
|
700 | * \param[in] iDescriptor watch descriptor
|
708 | * \param[in] iDescriptor watch descriptor
|
701 | * \return pointer to a watch; NULL if no such watch exists
|
709 | * \return pointer to a watch; NULL if no such watch exists
|
702 | */
|
710 | */
|
703 | InotifyWatch* FindWatch(int iDescriptor); |
711 | InotifyWatch* FindWatch(int iDescriptor); |
704 | 712 | ||
705 | /// Searches for a watch by a filesystem path.
|
713 | /// Searches for a watch by a filesystem path.
|
706 | /**
|
714 | /**
|
707 | * It tries to find a watch by the given filesystem path.
|
715 | * It tries to find a watch by the given filesystem path.
|
708 | *
|
716 | *
|
709 | * \param[in] rPath filesystem path
|
717 | * \param[in] rPath filesystem path
|
710 | * \return pointer to a watch; NULL if no such watch exists
|
718 | * \return pointer to a watch; NULL if no such watch exists
|
711 | *
|
719 | *
|
712 | * \attention The path must be exactly identical to the one
|
720 | * \attention The path must be exactly identical to the one
|
713 | * used for the searched watch. Be careful about
|
721 | * used for the searched watch. Be careful about
|
714 | * absolute/relative and case-insensitive paths.
|
722 | * absolute/relative and case-insensitive paths.
|
715 | */
|
723 | */
|
716 | InotifyWatch* FindWatch(const std::string& rPath); |
724 | InotifyWatch* FindWatch(const std::string& rPath); |
717 | 725 | ||
718 | /// Returns the file descriptor.
|
726 | /// Returns the file descriptor.
|
719 | /**
|
727 | /**
|
720 | * The descriptor can be used in standard low-level file
|
728 | * The descriptor can be used in standard low-level file
|
721 | * functions (poll(), select(), fcntl() etc.).
|
729 | * functions (poll(), select(), fcntl() etc.).
|
722 | *
|
730 | *
|
723 | * \return valid file descriptor or -1 for inactive object
|
731 | * \return valid file descriptor or -1 for inactive object
|
724 | *
|
732 | *
|
725 | * \sa SetNonBlock()
|
733 | * \sa SetNonBlock()
|
726 | */
|
734 | */
|
727 | inline int GetDescriptor() const |
735 | inline int GetDescriptor() const |
728 | {
|
736 | {
|
729 | return m_fd; |
737 | return m_fd; |
730 | }
|
738 | }
|
731 | 739 | ||
732 | /// Enables/disables non-blocking mode.
|
740 | /// Enables/disables non-blocking mode.
|
733 | /**
|
741 | /**
|
734 | * Use this mode if you want to monitor the descriptor
|
742 | * Use this mode if you want to monitor the descriptor
|
735 | * (acquired thru GetDescriptor()) in functions such as
|
743 | * (acquired thru GetDescriptor()) in functions such as
|
736 | * poll(), select() etc.
|
744 | * poll(), select() etc.
|
737 | *
|
745 | *
|
738 | * \param[in] fNonBlock enable/disable non-blocking mode
|
746 | * \param[in] fNonBlock enable/disable non-blocking mode
|
739 | *
|
747 | *
|
740 | * \throw InotifyException thrown if setting mode failed
|
748 | * \throw InotifyException thrown if setting mode failed
|
741 | *
|
749 | *
|
742 | * \sa GetDescriptor()
|
750 | * \sa GetDescriptor()
|
743 | */
|
751 | */
|
744 | void SetNonBlock(bool fNonBlock) throw (InotifyException); |
752 | void SetNonBlock(bool fNonBlock) throw (InotifyException); |
745 | 753 | ||
746 | /// Acquires a particular inotify capability/limit.
|
754 | /// Acquires a particular inotify capability/limit.
|
747 | /**
|
755 | /**
|
748 | * \param[in] cap capability/limit identifier
|
756 | * \param[in] cap capability/limit identifier
|
749 | * \return capability/limit value
|
757 | * \return capability/limit value
|
750 | * \throw InotifyException thrown if the given value cannot be acquired
|
758 | * \throw InotifyException thrown if the given value cannot be acquired
|
751 | */
|
759 | */
|
752 | static uint32_t GetCapability(InotifyCapability_t cap) throw (InotifyException); |
760 | static uint32_t GetCapability(InotifyCapability_t cap) throw (InotifyException); |
753 | 761 | ||
754 | /// Modifies a particular inotify capability/limit.
|
762 | /// Modifies a particular inotify capability/limit.
|
755 | /**
|
763 | /**
|
756 | * \param[in] cap capability/limit identifier
|
764 | * \param[in] cap capability/limit identifier
|
757 | * \param[in] val new capability/limit value
|
765 | * \param[in] val new capability/limit value
|
758 | * \throw InotifyException thrown if the given value cannot be set
|
766 | * \throw InotifyException thrown if the given value cannot be set
|
759 | * \attention Using this function requires root privileges.
|
767 | * \attention Using this function requires root privileges.
|
760 | * Beware of setting extensive values - it may seriously
|
768 | * Beware of setting extensive values - it may seriously
|
761 | * affect system performance and/or stability.
|
769 | * affect system performance and/or stability.
|
762 | */
|
770 | */
|
763 | static void SetCapability(InotifyCapability_t cap, uint32_t val) throw (InotifyException); |
771 | static void SetCapability(InotifyCapability_t cap, uint32_t val) throw (InotifyException); |
764 | 772 | ||
765 | /// Returns the maximum number of events in the kernel queue.
|
773 | /// Returns the maximum number of events in the kernel queue.
|
766 | /**
|
774 | /**
|
767 | * \return maximum number of events in the kernel queue
|
775 | * \return maximum number of events in the kernel queue
|
768 | * \throw InotifyException thrown if the given value cannot be acquired
|
776 | * \throw InotifyException thrown if the given value cannot be acquired
|
769 | */
|
777 | */
|
770 | inline static uint32_t GetMaxEvents() throw (InotifyException) |
778 | inline static uint32_t GetMaxEvents() throw (InotifyException) |
771 | {
|
779 | {
|
772 | return GetCapability(IN_MAX_EVENTS); |
780 | return GetCapability(IN_MAX_EVENTS); |
773 | }
|
781 | }
|
774 | 782 | ||
775 | /// Sets the maximum number of events in the kernel queue.
|
783 | /// Sets the maximum number of events in the kernel queue.
|
776 | /**
|
784 | /**
|
777 | * \param[in] val new value
|
785 | * \param[in] val new value
|
778 | * \throw InotifyException thrown if the given value cannot be set
|
786 | * \throw InotifyException thrown if the given value cannot be set
|
779 | * \attention Using this function requires root privileges.
|
787 | * \attention Using this function requires root privileges.
|
780 | * Beware of setting extensive values - the greater value
|
788 | * Beware of setting extensive values - the greater value
|
781 | * is set here the more physical memory may be used for the inotify
|
789 | * is set here the more physical memory may be used for the inotify
|
782 | * infrastructure.
|
790 | * infrastructure.
|
783 | */
|
791 | */
|
784 | inline static void SetMaxEvents(uint32_t val) throw (InotifyException) |
792 | inline static void SetMaxEvents(uint32_t val) throw (InotifyException) |
785 | {
|
793 | {
|
786 | SetCapability(IN_MAX_EVENTS, val); |
794 | SetCapability(IN_MAX_EVENTS, val); |
787 | }
|
795 | }
|
788 | 796 | ||
789 | /// Returns the maximum number of inotify instances per process.
|
797 | /// Returns the maximum number of inotify instances per process.
|
790 | /**
|
798 | /**
|
791 | * It means the maximum number of open inotify file descriptors
|
799 | * It means the maximum number of open inotify file descriptors
|
792 | * per running process.
|
800 | * per running process.
|
793 | *
|
801 | *
|
794 | * \return maximum number of inotify instances
|
802 | * \return maximum number of inotify instances
|
795 | * \throw InotifyException thrown if the given value cannot be acquired
|
803 | * \throw InotifyException thrown if the given value cannot be acquired
|
796 | */
|
804 | */
|
797 | inline static uint32_t GetMaxInstances() throw (InotifyException) |
805 | inline static uint32_t GetMaxInstances() throw (InotifyException) |
798 | {
|
806 | {
|
799 | return GetCapability(IN_MAX_INSTANCES); |
807 | return GetCapability(IN_MAX_INSTANCES); |
800 | }
|
808 | }
|
801 | 809 | ||
802 | /// Sets the maximum number of inotify instances per process.
|
810 | /// Sets the maximum number of inotify instances per process.
|
803 | /**
|
811 | /**
|
804 | * \param[in] val new value
|
812 | * \param[in] val new value
|
805 | * \throw InotifyException thrown if the given value cannot be set
|
813 | * \throw InotifyException thrown if the given value cannot be set
|
806 | * \attention Using this function requires root privileges.
|
814 | * \attention Using this function requires root privileges.
|
807 | * Beware of setting extensive values - the greater value
|
815 | * Beware of setting extensive values - the greater value
|
808 | * is set here the more physical memory may be used for the inotify
|
816 | * is set here the more physical memory may be used for the inotify
|
809 | * infrastructure.
|
817 | * infrastructure.
|
810 | */
|
818 | */
|
811 | inline static void SetMaxInstances(uint32_t val) throw (InotifyException) |
819 | inline static void SetMaxInstances(uint32_t val) throw (InotifyException) |
812 | {
|
820 | {
|
813 | SetCapability(IN_MAX_INSTANCES, val); |
821 | SetCapability(IN_MAX_INSTANCES, val); |
814 | }
|
822 | }
|
815 | 823 | ||
816 | /// Returns the maximum number of inotify watches per instance.
|
824 | /// Returns the maximum number of inotify watches per instance.
|
817 | /**
|
825 | /**
|
818 | * It means the maximum number of inotify watches per inotify
|
826 | * It means the maximum number of inotify watches per inotify
|
819 | * file descriptor.
|
827 | * file descriptor.
|
820 | *
|
828 | *
|
821 | * \return maximum number of inotify watches
|
829 | * \return maximum number of inotify watches
|
822 | * \throw InotifyException thrown if the given value cannot be acquired
|
830 | * \throw InotifyException thrown if the given value cannot be acquired
|
823 | */
|
831 | */
|
824 | inline static uint32_t GetMaxWatches() throw (InotifyException) |
832 | inline static uint32_t GetMaxWatches() throw (InotifyException) |
825 | {
|
833 | {
|
826 | return GetCapability(IN_MAX_WATCHES); |
834 | return GetCapability(IN_MAX_WATCHES); |
827 | }
|
835 | }
|
828 | 836 | ||
829 | /// Sets the maximum number of inotify watches per instance.
|
837 | /// Sets the maximum number of inotify watches per instance.
|
830 | /**
|
838 | /**
|
831 | * \param[in] val new value
|
839 | * \param[in] val new value
|
832 | * \throw InotifyException thrown if the given value cannot be set
|
840 | * \throw InotifyException thrown if the given value cannot be set
|
833 | * \attention Using this function requires root privileges.
|
841 | * \attention Using this function requires root privileges.
|
834 | * Beware of setting extensive values - the greater value
|
842 | * Beware of setting extensive values - the greater value
|
835 | * is set here the more physical memory may be used for the inotify
|
843 | * is set here the more physical memory may be used for the inotify
|
836 | * infrastructure.
|
844 | * infrastructure.
|
837 | */
|
845 | */
|
838 | inline static void SetMaxWatches(uint32_t val) throw (InotifyException) |
846 | inline static void SetMaxWatches(uint32_t val) throw (InotifyException) |
839 | {
|
847 | {
|
840 | SetCapability(IN_MAX_WATCHES, val); |
848 | SetCapability(IN_MAX_WATCHES, val); |
841 | }
|
849 | }
|
842 | 850 | ||
843 | private: |
851 | private: |
844 | int m_fd; ///< file descriptor |
852 | int m_fd; ///< file descriptor |
845 | IN_WATCH_MAP m_watches; ///< watches (by descriptors) |
853 | IN_WATCH_MAP m_watches; ///< watches (by descriptors) |
846 | IN_WP_MAP m_paths; ///< watches (by paths) |
854 | IN_WP_MAP m_paths; ///< watches (by paths) |
847 | unsigned char m_buf[INOTIFY_BUFLEN]; ///< buffer for events |
855 | unsigned char m_buf[INOTIFY_BUFLEN]; ///< buffer for events |
848 | std::deque<InotifyEvent> m_events; ///< event queue |
856 | std::deque<InotifyEvent> m_events; ///< event queue |
849 | 857 | ||
850 | IN_LOCK_DECL |
858 | IN_LOCK_DECL |
851 | 859 | ||
852 | friend class InotifyWatch; |
860 | friend class InotifyWatch; |
853 | 861 | ||
854 | static std::string GetCapabilityPath(InotifyCapability_t cap) throw (InotifyException); |
862 | static std::string GetCapabilityPath(InotifyCapability_t cap) throw (InotifyException); |
855 | }; |
863 | }; |
856 | 864 | ||
857 | 865 | ||
858 | #endif //_INOTIFYCXX_H_
|
866 | #endif //_INOTIFYCXX_H_
|
859 | 867 | ||
860 | 868 |