Subversion Repositories public

Rev

Rev 39 | Rev 43 | Go to most recent revision | Only display areas with differences | Ignore whitespace | Details | Blame | Last modification | View Log | RSS feed

Rev 39 Rev 41
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, 2007 Lukas Jelinek, <lukas@aiken.cz>
8
 * Copyright (C) 2006, 2007 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->len > 0
-
 
251
            ? pEvt->name
-
 
252
            : "";
-
 
253
      }
251
      m_pWatch = pWatch;
254
      m_pWatch = pWatch;
252
    }
255
    }
253
    else {
256
    else {
254
      m_pWatch = NULL;
257
      m_pWatch = NULL;
255
    }
258
    }
256
  }
259
  }
257
 
260
 
258
  /// Destructor.
261
  /// Destructor.
259
  ~InotifyEvent() {}
262
  ~InotifyEvent() {}
260
 
263
 
261
  /// Returns the event watch descriptor.
264
  /// Returns the event watch descriptor.
262
  /**
265
  /**
263
   * \return watch descriptor
266
   * \return watch descriptor
264
   *
267
   *
265
   * \sa InotifyWatch::GetDescriptor()
268
   * \sa InotifyWatch::GetDescriptor()
266
   */
269
   */
267
  int32_t GetDescriptor() const;
270
  int32_t GetDescriptor() const;
268
 
271
 
269
  /// Returns the event mask.
272
  /// Returns the event mask.
270
  /**
273
  /**
271
   * \return event mask
274
   * \return event mask
272
   *
275
   *
273
   * \sa InotifyWatch::GetMask()
276
   * \sa InotifyWatch::GetMask()
274
   */
277
   */
275
  inline uint32_t GetMask() const
278
  inline uint32_t GetMask() const
276
  {
279
  {
277
    return m_uMask;
280
    return m_uMask;
278
  }
281
  }
279
 
282
 
280
  /// Checks a value for the event type.
283
  /// Checks a value for the event type.
281
  /**
284
  /**
282
   * \param[in] uValue checked value
285
   * \param[in] uValue checked value
283
   * \param[in] uType type which is checked for
286
   * \param[in] uType type which is checked for
284
   * \return true = the value contains the given type, false = otherwise
287
   * \return true = the value contains the given type, false = otherwise
285
   */
288
   */
286
  inline static bool IsType(uint32_t uValue, uint32_t uType)
289
  inline static bool IsType(uint32_t uValue, uint32_t uType)
287
  {
290
  {
288
    return ((uValue & uType) != 0) && ((~uValue & uType) == 0);
291
    return ((uValue & uType) != 0) && ((~uValue & uType) == 0);
289
  }
292
  }
290
 
293
 
291
  /// Checks for the event type.
294
  /// Checks for the event type.
292
  /**
295
  /**
293
   * \param[in] uType type which is checked for
296
   * \param[in] uType type which is checked for
294
   * \return true = event mask contains the given type, false = otherwise
297
   * \return true = event mask contains the given type, false = otherwise
295
   */
298
   */
296
  inline bool IsType(uint32_t uType) const
299
  inline bool IsType(uint32_t uType) const
297
  {
300
  {
298
    return IsType(m_uMask, uType);
301
    return IsType(m_uMask, uType);
299
  }
302
  }
300
 
303
 
301
  /// Returns the event cookie.
304
  /// Returns the event cookie.
302
  /**
305
  /**
303
   * \return event cookie
306
   * \return event cookie
304
   */
307
   */
305
  inline uint32_t GetCookie() const
308
  inline uint32_t GetCookie() const
306
  {
309
  {
307
    return m_uCookie;
310
    return m_uCookie;
308
  }
311
  }
309
 
312
 
310
  /// Returns the event name length.
313
  /// Returns the event name length.
311
  /**
314
  /**
312
   * \return event name length
315
   * \return event name length
313
   */
316
   */
314
  inline uint32_t GetLength() const
317
  inline uint32_t GetLength() const
315
  {
318
  {
316
    return (uint32_t) m_name.length();
319
    return (uint32_t) m_name.length();
317
  }
320
  }
318
 
321
 
319
  /// Returns the event name.
322
  /// Returns the event name.
320
  /**
323
  /**
321
   * \return event name
324
   * \return event name
322
   */
325
   */
323
  inline const std::string& GetName() const
326
  inline const std::string& GetName() const
324
  {
327
  {
325
    return m_name;
328
    return m_name;
326
  }
329
  }
327
 
330
 
328
  /// Extracts the event name.
331
  /// Extracts the event name.
329
  /**
332
  /**
330
   * \param[out] rName event name
333
   * \param[out] rName event name
331
   */
334
   */
332
  inline void GetName(std::string& rName) const
335
  inline void GetName(std::string& rName) const
333
  {
336
  {
334
    rName = GetName();
337
    rName = GetName();
335
  }
338
  }
336
 
339
 
337
  /// Returns the source watch.
340
  /// Returns the source watch.
338
  /**
341
  /**
339
   * \return source watch
342
   * \return source watch
340
   */
343
   */
341
  inline InotifyWatch* GetWatch()
344
  inline InotifyWatch* GetWatch()
342
  {
345
  {
343
    return m_pWatch;
346
    return m_pWatch;
344
  }
347
  }
345
 
348
 
346
  /// Finds the appropriate mask for a name.
349
  /// Finds the appropriate mask for a name.
347
  /**
350
  /**
348
   * \param[in] rName mask name
351
   * \param[in] rName mask name
349
   * \return mask for name; 0 on failure
352
   * \return mask for name; 0 on failure
350
   */
353
   */
351
  static uint32_t GetMaskByName(const std::string& rName);
354
  static uint32_t GetMaskByName(const std::string& rName);
352
 
355
 
353
  /// Fills the string with all types contained in an event mask value.
356
  /// Fills the string with all types contained in an event mask value.
354
  /**
357
  /**
355
   * \param[in] uValue event mask value
358
   * \param[in] uValue event mask value
356
   * \param[out] rStr dumped event types
359
   * \param[out] rStr dumped event types
357
   */
360
   */
358
  static void DumpTypes(uint32_t uValue, std::string& rStr);
361
  static void DumpTypes(uint32_t uValue, std::string& rStr);
359
 
362
 
360
  /// Fills the string with all types contained in the event mask.
363
  /// Fills the string with all types contained in the event mask.
361
  /**
364
  /**
362
   * \param[out] rStr dumped event types
365
   * \param[out] rStr dumped event types
363
   */
366
   */
364
  void DumpTypes(std::string& rStr) const;
367
  void DumpTypes(std::string& rStr) const;
365
 
368
 
366
private:
369
private:
367
  uint32_t m_uMask;           ///< mask
370
  uint32_t m_uMask;           ///< mask
368
  uint32_t m_uCookie;         ///< cookie
371
  uint32_t m_uCookie;         ///< cookie
369
  std::string m_name;         ///< name
372
  std::string m_name;         ///< name
370
  InotifyWatch* m_pWatch;     ///< source watch
373
  InotifyWatch* m_pWatch;     ///< source watch
371
};
374
};
372
375
373
376
374
377
375
/// inotify watch class
378
/// inotify watch class
376
/**
379
/**
377
 * It holds information about the inotify watch on a particular
380
 * It holds information about the inotify watch on a particular
378
 * inode.
381
 * inode.
379
 *
382
 *
380
 * If the INOTIFY_THREAD_SAFE is defined this class is thread-safe.
383
 * If the INOTIFY_THREAD_SAFE is defined this class is thread-safe.
381
 */
384
 */
382
class InotifyWatch
385
class InotifyWatch
383
{
386
{
384
public:
387
public:
385
  /// Constructor.
388
  /// Constructor.
386
  /**
389
  /**
387
   * Creates an inotify watch. Because this watch is
390
   * Creates an inotify watch. Because this watch is
388
   * inactive it has an invalid descriptor (-1).
391
   * inactive it has an invalid descriptor (-1).
389
   *
392
   *
390
   * \param[in] rPath watched file path
393
   * \param[in] rPath watched file path
391
   * \param[in] uMask mask for events
394
   * \param[in] uMask mask for events
392
   * \param[in] fEnabled events enabled yes/no
395
   * \param[in] fEnabled events enabled yes/no
393
   */
396
   */
394
  InotifyWatch(const std::string& rPath, int32_t uMask, bool fEnabled = true)
397
  InotifyWatch(const std::string& rPath, int32_t uMask, bool fEnabled = true)
395
  : m_path(rPath),
398
  : m_path(rPath),
396
    m_uMask(uMask),
399
    m_uMask(uMask),
397
    m_wd((int32_t) -1),
400
    m_wd((int32_t) -1),
398
    m_fEnabled(fEnabled)
401
    m_fEnabled(fEnabled)
399
  {
402
  {
400
    IN_LOCK_INIT
403
    IN_LOCK_INIT
401
  }
404
  }
402
 
405
 
403
  /// Destructor.
406
  /// Destructor.
404
  ~InotifyWatch()
407
  ~InotifyWatch()
405
  {
408
  {
406
    IN_LOCK_DONE
409
    IN_LOCK_DONE
407
  }
410
  }
408
 
411
 
409
  /// Returns the watch descriptor.
412
  /// Returns the watch descriptor.
410
  /**
413
  /**
411
   * \return watch descriptor; -1 for inactive watch
414
   * \return watch descriptor; -1 for inactive watch
412
   */
415
   */
413
  inline int32_t GetDescriptor() const
416
  inline int32_t GetDescriptor() const
414
  {
417
  {
415
    return m_wd;
418
    return m_wd;
416
  }
419
  }
417
 
420
 
418
  /// Returns the watched file path.
421
  /// Returns the watched file path.
419
  /**
422
  /**
420
   * \return file path
423
   * \return file path
421
   */
424
   */
422
  inline const std::string& GetPath() const
425
  inline const std::string& GetPath() const
423
  {
426
  {
424
    return m_path;
427
    return m_path;
425
  }
428
  }
426
 
429
 
427
  /// Returns the watch event mask.
430
  /// Returns the watch event mask.
428
  /**
431
  /**
429
   * \return event mask
432
   * \return event mask
430
   */
433
   */
431
  inline uint32_t GetMask() const
434
  inline uint32_t GetMask() const
432
  {
435
  {
433
    return (uint32_t) m_uMask;
436
    return (uint32_t) m_uMask;
434
  }
437
  }
435
 
438
 
436
  /// Sets the watch event mask.
439
  /// Sets the watch event mask.
437
  /**
440
  /**
438
   * If the watch is active (added to an instance of Inotify)
441
   * If the watch is active (added to an instance of Inotify)
439
   * this method may fail due to unsuccessful re-setting
442
   * this method may fail due to unsuccessful re-setting
440
   * the watch in the kernel.
443
   * the watch in the kernel.
441
   *
444
   *
442
   * \param[in] uMask event mask
445
   * \param[in] uMask event mask
443
   *
446
   *
444
   * \throw InotifyException thrown if changing fails
447
   * \throw InotifyException thrown if changing fails
445
   */
448
   */
446
  void SetMask(uint32_t uMask) throw (InotifyException);  
449
  void SetMask(uint32_t uMask) throw (InotifyException);  
447
 
450
 
448
  /// Returns the appropriate inotify class instance.
451
  /// Returns the appropriate inotify class instance.
449
  /**
452
  /**
450
   * \return inotify instance
453
   * \return inotify instance
451
   */
454
   */
452
  inline Inotify* GetInotify()
455
  inline Inotify* GetInotify()
453
  {
456
  {
454
    return m_pInotify;
457
    return m_pInotify;
455
  }
458
  }
456
 
459
 
457
  /// Enables/disables the watch.
460
  /// Enables/disables the watch.
458
  /**
461
  /**
459
   * If the watch is active (added to an instance of Inotify)
462
   * If the watch is active (added to an instance of Inotify)
460
   * this method may fail due to unsuccessful re-setting
463
   * this method may fail due to unsuccessful re-setting
461
   * the watch in the kernel.
464
   * the watch in the kernel.
462
   *
465
   *
463
   * Re-setting the current state has no effect.
466
   * Re-setting the current state has no effect.
464
   *
467
   *
465
   * \param[in] fEnabled set enabled yes/no
468
   * \param[in] fEnabled set enabled yes/no
466
   *
469
   *
467
   * \throw InotifyException thrown if enabling/disabling fails
470
   * \throw InotifyException thrown if enabling/disabling fails
468
   */
471
   */
469
  void SetEnabled(bool fEnabled) throw (InotifyException);
472
  void SetEnabled(bool fEnabled) throw (InotifyException);
470
 
473
 
471
  /// Checks whether the watch is enabled.
474
  /// Checks whether the watch is enabled.
472
  /**
475
  /**
473
   * \return true = enables, false = disabled
476
   * \return true = enables, false = disabled
474
   */
477
   */
475
  inline bool IsEnabled() const
478
  inline bool IsEnabled() const
476
  {
479
  {
477
    return m_fEnabled;
480
    return m_fEnabled;
478
  }
481
  }
479
 
482
 
480
  /// Checks whether the watch is recursive.
483
  /// Checks whether the watch is recursive.
481
  /**
484
  /**
482
   * A recursive watch monitors a directory itself and all
485
   * A recursive watch monitors a directory itself and all
483
   * its subdirectories. This watch is a logical object
486
   * its subdirectories. This watch is a logical object
484
   * which may have many underlying kernel watches.
487
   * which may have many underlying kernel watches.
485
   *
488
   *
486
   * \return currently always false (recursive watches not yet supported)
489
   * \return currently always false (recursive watches not yet supported)
487
   * \attention Recursive watches are currently NOT supported.
490
   * \attention Recursive watches are currently NOT supported.
488
   *            They are planned for future versions.
491
   *            They are planned for future versions.
489
   */
492
   */
490
  inline bool IsRecursive() const
493
  inline bool IsRecursive() const
491
  {
494
  {
492
    return false;    
495
    return false;    
493
  }
496
  }
494
 
497
 
495
private:
498
private:
496
  friend class Inotify;
499
  friend class Inotify;
497
500
498
  std::string m_path;   ///< watched file path
501
  std::string m_path;   ///< watched file path
499
  uint32_t m_uMask;     ///< event mask
502
  uint32_t m_uMask;     ///< event mask
500
  int32_t m_wd;         ///< watch descriptor
503
  int32_t m_wd;         ///< watch descriptor
501
  Inotify* m_pInotify;  ///< inotify object
504
  Inotify* m_pInotify;  ///< inotify object
502
  bool m_fEnabled;      ///< events enabled yes/no
505
  bool m_fEnabled;      ///< events enabled yes/no
503
 
506
 
504
  IN_LOCK_DECL
507
  IN_LOCK_DECL
505
 
508
 
506
  /// Disables the watch (due to removing by the kernel).
509
  /// Disables the watch (due to removing by the kernel).
507
  /**
510
  /**
508
   * This method must be called after receiving an event.
511
   * This method must be called after receiving an event.
509
   * It ensures the watch object is consistent with the kernel
512
   * It ensures the watch object is consistent with the kernel
510
   * data.
513
   * data.
511
   */
514
   */
512
  void __Disable();
515
  void __Disable();
513
};
516
};
514
517
515
518
516
/// Mapping from watch descriptors to watch objects.
519
/// Mapping from watch descriptors to watch objects.
517
typedef std::map<int32_t, InotifyWatch*> IN_WATCH_MAP;
520
typedef std::map<int32_t, InotifyWatch*> IN_WATCH_MAP;
518
521
519
/// Mapping from paths to watch objects.
522
/// Mapping from paths to watch objects.
520
typedef std::map<std::string, InotifyWatch*> IN_WP_MAP;
523
typedef std::map<std::string, InotifyWatch*> IN_WP_MAP;
521
524
522
525
523
/// inotify class
526
/// inotify class
524
/**
527
/**
525
 * It holds information about the inotify device descriptor
528
 * It holds information about the inotify device descriptor
526
 * and manages the event queue.
529
 * and manages the event queue.
527
 *
530
 *
528
 * If the INOTIFY_THREAD_SAFE is defined this class is thread-safe.
531
 * If the INOTIFY_THREAD_SAFE is defined this class is thread-safe.
529
 */
532
 */
530
class Inotify
533
class Inotify
531
{
534
{
532
public:
535
public:
533
  /// Constructor.
536
  /// Constructor.
534
  /**
537
  /**
535
   * Creates and initializes an instance of inotify communication
538
   * Creates and initializes an instance of inotify communication
536
   * object (opens the inotify device).
539
   * object (opens the inotify device).
537
   *
540
   *
538
   * \throw InotifyException thrown if inotify isn't available
541
   * \throw InotifyException thrown if inotify isn't available
539
   */
542
   */
540
  Inotify() throw (InotifyException);
543
  Inotify() throw (InotifyException);
541
 
544
 
542
  /// Destructor.
545
  /// Destructor.
543
  /**
546
  /**
544
   * Calls Close() due to clean-up.
547
   * Calls Close() due to clean-up.
545
   */
548
   */
546
  ~Inotify();
549
  ~Inotify();
547
 
550
 
548
  /// Removes all watches and closes the inotify device.
551
  /// Removes all watches and closes the inotify device.
549
  void Close();
552
  void Close();
550
   
553
   
551
  /// Adds a new watch.
554
  /// Adds a new watch.
552
  /**
555
  /**
553
   * \param[in] pWatch inotify watch
556
   * \param[in] pWatch inotify watch
554
   *
557
   *
555
   * \throw InotifyException thrown if adding failed
558
   * \throw InotifyException thrown if adding failed
556
   */
559
   */
557
  void Add(InotifyWatch* pWatch) throw (InotifyException);
560
  void Add(InotifyWatch* pWatch) throw (InotifyException);
558
 
561
 
559
  /// Adds a new watch.
562
  /// Adds a new watch.
560
  /**
563
  /**
561
   * \param[in] rWatch inotify watch
564
   * \param[in] rWatch inotify watch
562
   *
565
   *
563
   * \throw InotifyException thrown if adding failed
566
   * \throw InotifyException thrown if adding failed
564
   */
567
   */
565
  inline void Add(InotifyWatch& rWatch) throw (InotifyException)
568
  inline void Add(InotifyWatch& rWatch) throw (InotifyException)
566
  {
569
  {
567
    Add(&rWatch);
570
    Add(&rWatch);
568
  }
571
  }
569
 
572
 
570
  /// Removes a watch.
573
  /// Removes a watch.
571
  /**
574
  /**
572
   * If the given watch is not present it does nothing.
575
   * If the given watch is not present it does nothing.
573
   *
576
   *
574
   * \param[in] pWatch inotify watch
577
   * \param[in] pWatch inotify watch
575
   *
578
   *
576
   * \throw InotifyException thrown if removing failed
579
   * \throw InotifyException thrown if removing failed
577
   */
580
   */
578
  void Remove(InotifyWatch* pWatch) throw (InotifyException);
581
  void Remove(InotifyWatch* pWatch) throw (InotifyException);
579
 
582
 
580
  /// Removes a watch.
583
  /// Removes a watch.
581
  /**
584
  /**
582
   * If the given watch is not present it does nothing.
585
   * If the given watch is not present it does nothing.
583
   *
586
   *
584
   * \param[in] rWatch inotify watch
587
   * \param[in] rWatch inotify watch
585
   *
588
   *
586
   * \throw InotifyException thrown if removing failed
589
   * \throw InotifyException thrown if removing failed
587
   */
590
   */
588
  inline void Remove(InotifyWatch& rWatch) throw (InotifyException)
591
  inline void Remove(InotifyWatch& rWatch) throw (InotifyException)
589
  {
592
  {
590
    Remove(&rWatch);
593
    Remove(&rWatch);
591
  }
594
  }
592
 
595
 
593
  /// Removes all watches.
596
  /// Removes all watches.
594
  void RemoveAll();
597
  void RemoveAll();
595
 
598
 
596
  /// Returns the count of watches.
599
  /// Returns the count of watches.
597
  /**
600
  /**
598
   * This is the total count of all watches (regardless whether
601
   * This is the total count of all watches (regardless whether
599
   * enabled or not).
602
   * enabled or not).
600
   *
603
   *
601
   * \return count of watches
604
   * \return count of watches
602
   *
605
   *
603
   * \sa GetEnabledCount()
606
   * \sa GetEnabledCount()
604
   */
607
   */
605
  inline size_t GetWatchCount() const
608
  inline size_t GetWatchCount() const
606
  {
609
  {
607
    IN_READ_BEGIN
610
    IN_READ_BEGIN
608
    size_t n = (size_t) m_paths.size();
611
    size_t n = (size_t) m_paths.size();
609
    IN_READ_END
612
    IN_READ_END
610
    return n;
613
    return n;
611
  }
614
  }
612
 
615
 
613
  /// Returns the count of enabled watches.
616
  /// Returns the count of enabled watches.
614
  /**
617
  /**
615
   * \return count of enabled watches
618
   * \return count of enabled watches
616
   *
619
   *
617
   * \sa GetWatchCount()
620
   * \sa GetWatchCount()
618
   */  
621
   */  
619
  inline size_t GetEnabledCount() const
622
  inline size_t GetEnabledCount() const
620
  {
623
  {
621
    IN_READ_BEGIN
624
    IN_READ_BEGIN
622
    size_t n = (size_t) m_watches.size();
625
    size_t n = (size_t) m_watches.size();
623
    IN_READ_END
626
    IN_READ_END
624
    return n;
627
    return n;
625
  }
628
  }
626
 
629
 
627
  /// Waits for inotify events.
630
  /// Waits for inotify events.
628
  /**
631
  /**
629
   * It waits until one or more events occur. When called
632
   * It waits until one or more events occur. When called
630
   * in nonblocking mode it only retrieves occurred events
633
   * in nonblocking mode it only retrieves occurred events
631
   * to the internal queue and exits.
634
   * to the internal queue and exits.
632
   *
635
   *
633
   * \param[in] fNoIntr if true it re-calls the system call after a handled signal
636
   * \param[in] fNoIntr if true it re-calls the system call after a handled signal
634
   *
637
   *
635
   * \throw InotifyException thrown if reading events failed
638
   * \throw InotifyException thrown if reading events failed
636
   *
639
   *
637
   * \sa SetNonBlock()
640
   * \sa SetNonBlock()
638
   */
641
   */
639
  void WaitForEvents(bool fNoIntr = false) throw (InotifyException);
642
  void WaitForEvents(bool fNoIntr = false) throw (InotifyException);
640
 
643
 
641
  /// Returns the count of received and queued events.
644
  /// Returns the count of received and queued events.
642
  /**
645
  /**
643
   * This number is related to the events in the queue inside
646
   * This number is related to the events in the queue inside
644
   * this object, not to the events pending in the kernel.
647
   * this object, not to the events pending in the kernel.
645
   *
648
   *
646
   * \return count of events
649
   * \return count of events
647
   */
650
   */
648
  inline size_t GetEventCount()
651
  inline size_t GetEventCount()
649
  {
652
  {
650
    IN_READ_BEGIN
653
    IN_READ_BEGIN
651
    size_t n = (size_t) m_events.size();
654
    size_t n = (size_t) m_events.size();
652
    IN_READ_END
655
    IN_READ_END
653
    return n;
656
    return n;
654
  }
657
  }
655
 
658
 
656
  /// Extracts a queued inotify event.
659
  /// Extracts a queued inotify event.
657
  /**
660
  /**
658
   * The extracted event is removed from the queue.
661
   * The extracted event is removed from the queue.
659
   * If the pointer is NULL it does nothing.
662
   * If the pointer is NULL it does nothing.
660
   *
663
   *
661
   * \param[in,out] pEvt event object
664
   * \param[in,out] pEvt event object
662
   *
665
   *
663
   * \throw InotifyException thrown if the provided pointer is NULL
666
   * \throw InotifyException thrown if the provided pointer is NULL
664
   */
667
   */
665
  bool GetEvent(InotifyEvent* pEvt) throw (InotifyException);
668
  bool GetEvent(InotifyEvent* pEvt) throw (InotifyException);
666
 
669
 
667
  /// Extracts a queued inotify event.
670
  /// Extracts a queued inotify event.
668
  /**
671
  /**
669
   * The extracted event is removed from the queue.
672
   * The extracted event is removed from the queue.
670
   *
673
   *
671
   * \param[in,out] rEvt event object
674
   * \param[in,out] rEvt event object
672
   *
675
   *
673
   * \throw InotifyException thrown only in very anomalous cases
676
   * \throw InotifyException thrown only in very anomalous cases
674
   */
677
   */
675
  bool GetEvent(InotifyEvent& rEvt) throw (InotifyException)
678
  bool GetEvent(InotifyEvent& rEvt) throw (InotifyException)
676
  {
679
  {
677
    return GetEvent(&rEvt);
680
    return GetEvent(&rEvt);
678
  }
681
  }
679
 
682
 
680
  /// Extracts a queued inotify event (without removing).
683
  /// Extracts a queued inotify event (without removing).
681
  /**
684
  /**
682
   * The extracted event stays in the queue.
685
   * The extracted event stays in the queue.
683
   * If the pointer is NULL it does nothing.
686
   * If the pointer is NULL it does nothing.
684
   *
687
   *
685
   * \param[in,out] pEvt event object
688
   * \param[in,out] pEvt event object
686
   *
689
   *
687
   * \throw InotifyException thrown if the provided pointer is NULL
690
   * \throw InotifyException thrown if the provided pointer is NULL
688
   */
691
   */
689
  bool PeekEvent(InotifyEvent* pEvt) throw (InotifyException);
692
  bool PeekEvent(InotifyEvent* pEvt) throw (InotifyException);
690
 
693
 
691
  /// Extracts a queued inotify event (without removing).
694
  /// Extracts a queued inotify event (without removing).
692
  /**
695
  /**
693
   * The extracted event stays in the queue.
696
   * The extracted event stays in the queue.
694
   *
697
   *
695
   * \param[in,out] rEvt event object
698
   * \param[in,out] rEvt event object
696
   *
699
   *
697
   * \throw InotifyException thrown only in very anomalous cases
700
   * \throw InotifyException thrown only in very anomalous cases
698
   */
701
   */
699
  bool PeekEvent(InotifyEvent& rEvt) throw (InotifyException)
702
  bool PeekEvent(InotifyEvent& rEvt) throw (InotifyException)
700
  {
703
  {
701
    return PeekEvent(&rEvt);
704
    return PeekEvent(&rEvt);
702
  }
705
  }
703
 
706
 
704
  /// Searches for a watch by a watch descriptor.
707
  /// Searches for a watch by a watch descriptor.
705
  /**
708
  /**
706
   * It tries to find a watch by the given descriptor.
709
   * It tries to find a watch by the given descriptor.
707
   *
710
   *
708
   * \param[in] iDescriptor watch descriptor
711
   * \param[in] iDescriptor watch descriptor
709
   * \return pointer to a watch; NULL if no such watch exists
712
   * \return pointer to a watch; NULL if no such watch exists
710
   */
713
   */
711
  InotifyWatch* FindWatch(int iDescriptor);
714
  InotifyWatch* FindWatch(int iDescriptor);
712
 
715
 
713
  /// Searches for a watch by a filesystem path.
716
  /// Searches for a watch by a filesystem path.
714
  /**
717
  /**
715
   * It tries to find a watch by the given filesystem path.
718
   * It tries to find a watch by the given filesystem path.
716
   *
719
   *
717
   * \param[in] rPath filesystem path
720
   * \param[in] rPath filesystem path
718
   * \return pointer to a watch; NULL if no such watch exists
721
   * \return pointer to a watch; NULL if no such watch exists
719
   *
722
   *
720
   * \attention The path must be exactly identical to the one
723
   * \attention The path must be exactly identical to the one
721
   *            used for the searched watch. Be careful about
724
   *            used for the searched watch. Be careful about
722
   *            absolute/relative and case-insensitive paths.
725
   *            absolute/relative and case-insensitive paths.
723
   */
726
   */
724
   InotifyWatch* FindWatch(const std::string& rPath);
727
   InotifyWatch* FindWatch(const std::string& rPath);
725
 
728
 
726
  /// Returns the file descriptor.
729
  /// Returns the file descriptor.
727
  /**
730
  /**
728
   * The descriptor can be used in standard low-level file
731
   * The descriptor can be used in standard low-level file
729
   * functions (poll(), select(), fcntl() etc.).
732
   * functions (poll(), select(), fcntl() etc.).
730
   *
733
   *
731
   * \return valid file descriptor or -1 for inactive object
734
   * \return valid file descriptor or -1 for inactive object
732
   *
735
   *
733
   * \sa SetNonBlock()
736
   * \sa SetNonBlock()
734
   */
737
   */
735
  inline int GetDescriptor() const
738
  inline int GetDescriptor() const
736
  {
739
  {
737
    return m_fd;
740
    return m_fd;
738
  }
741
  }
739
 
742
 
740
  /// Enables/disables non-blocking mode.
743
  /// Enables/disables non-blocking mode.
741
  /**
744
  /**
742
   * Use this mode if you want to monitor the descriptor
745
   * Use this mode if you want to monitor the descriptor
743
   * (acquired thru GetDescriptor()) in functions such as
746
   * (acquired thru GetDescriptor()) in functions such as
744
   * poll(), select() etc.
747
   * poll(), select() etc.
745
   *
748
   *
746
   * Non-blocking mode is disabled by default.
749
   * Non-blocking mode is disabled by default.
747
   *
750
   *
748
   * \param[in] fNonBlock enable/disable non-blocking mode
751
   * \param[in] fNonBlock enable/disable non-blocking mode
749
   *
752
   *
750
   * \throw InotifyException thrown if setting mode failed
753
   * \throw InotifyException thrown if setting mode failed
751
   *
754
   *
752
   * \sa GetDescriptor(), SetCloseOnExec()
755
   * \sa GetDescriptor(), SetCloseOnExec()
753
   */
756
   */
754
  void SetNonBlock(bool fNonBlock) throw (InotifyException);
757
  void SetNonBlock(bool fNonBlock) throw (InotifyException);
755
 
758
 
756
  /// Enables/disables closing on exec.
759
  /// Enables/disables closing on exec.
757
  /**
760
  /**
758
   * Enable this if you want to close the descriptor when
761
   * Enable this if you want to close the descriptor when
759
   * executing another program. Otherwise, the descriptor
762
   * executing another program. Otherwise, the descriptor
760
   * will be inherited.
763
   * will be inherited.
761
   *
764
   *
762
   * Closing on exec is disabled by default.
765
   * Closing on exec is disabled by default.
763
   *
766
   *
764
   * \param[in] fClOnEx enable/disable closing on exec
767
   * \param[in] fClOnEx enable/disable closing on exec
765
   *
768
   *
766
   * \throw InotifyException thrown if setting failed
769
   * \throw InotifyException thrown if setting failed
767
   *
770
   *
768
   * \sa GetDescriptor(), SetNonBlock()
771
   * \sa GetDescriptor(), SetNonBlock()
769
   */
772
   */
770
  void SetCloseOnExec(bool fClOnEx) throw (InotifyException);
773
  void SetCloseOnExec(bool fClOnEx) throw (InotifyException);
771
 
774
 
772
  /// Acquires a particular inotify capability/limit.
775
  /// Acquires a particular inotify capability/limit.
773
  /**
776
  /**
774
   * \param[in] cap capability/limit identifier
777
   * \param[in] cap capability/limit identifier
775
   * \return capability/limit value
778
   * \return capability/limit value
776
   * \throw InotifyException thrown if the given value cannot be acquired
779
   * \throw InotifyException thrown if the given value cannot be acquired
777
   */
780
   */
778
  static uint32_t GetCapability(InotifyCapability_t cap) throw (InotifyException);
781
  static uint32_t GetCapability(InotifyCapability_t cap) throw (InotifyException);
779
 
782
 
780
  /// Modifies a particular inotify capability/limit.
783
  /// Modifies a particular inotify capability/limit.
781
  /**
784
  /**
782
   * \param[in] cap capability/limit identifier
785
   * \param[in] cap capability/limit identifier
783
   * \param[in] val new capability/limit value
786
   * \param[in] val new capability/limit value
784
   * \throw InotifyException thrown if the given value cannot be set
787
   * \throw InotifyException thrown if the given value cannot be set
785
   * \attention Using this function requires root privileges.
788
   * \attention Using this function requires root privileges.
786
   *            Beware of setting extensive values - it may seriously
789
   *            Beware of setting extensive values - it may seriously
787
   *            affect system performance and/or stability.
790
   *            affect system performance and/or stability.
788
   */
791
   */
789
  static void SetCapability(InotifyCapability_t cap, uint32_t val) throw (InotifyException);
792
  static void SetCapability(InotifyCapability_t cap, uint32_t val) throw (InotifyException);
790
 
793
 
791
  /// Returns the maximum number of events in the kernel queue.
794
  /// Returns the maximum number of events in the kernel queue.
792
  /**
795
  /**
793
   * \return maximum number of events in the kernel queue
796
   * \return maximum number of events in the kernel queue
794
   * \throw InotifyException thrown if the given value cannot be acquired
797
   * \throw InotifyException thrown if the given value cannot be acquired
795
   */
798
   */
796
  inline static uint32_t GetMaxEvents() throw (InotifyException)
799
  inline static uint32_t GetMaxEvents() throw (InotifyException)
797
  {
800
  {
798
    return GetCapability(IN_MAX_EVENTS);
801
    return GetCapability(IN_MAX_EVENTS);
799
  }
802
  }
800
 
803
 
801
  /// Sets the maximum number of events in the kernel queue.
804
  /// Sets the maximum number of events in the kernel queue.
802
  /**
805
  /**
803
   * \param[in] val new value
806
   * \param[in] val new value
804
   * \throw InotifyException thrown if the given value cannot be set
807
   * \throw InotifyException thrown if the given value cannot be set
805
   * \attention Using this function requires root privileges.
808
   * \attention Using this function requires root privileges.
806
   *            Beware of setting extensive values - the greater value
809
   *            Beware of setting extensive values - the greater value
807
   *            is set here the more physical memory may be used for the inotify
810
   *            is set here the more physical memory may be used for the inotify
808
   *            infrastructure.
811
   *            infrastructure.
809
   */
812
   */
810
  inline static void SetMaxEvents(uint32_t val) throw (InotifyException)
813
  inline static void SetMaxEvents(uint32_t val) throw (InotifyException)
811
  {
814
  {
812
    SetCapability(IN_MAX_EVENTS, val);
815
    SetCapability(IN_MAX_EVENTS, val);
813
  }
816
  }
814
 
817
 
815
  /// Returns the maximum number of inotify instances per process.
818
  /// Returns the maximum number of inotify instances per process.
816
  /**
819
  /**
817
   * It means the maximum number of open inotify file descriptors
820
   * It means the maximum number of open inotify file descriptors
818
   * per running process.
821
   * per running process.
819
   *
822
   *
820
   * \return maximum number of inotify instances
823
   * \return maximum number of inotify instances
821
   * \throw InotifyException thrown if the given value cannot be acquired
824
   * \throw InotifyException thrown if the given value cannot be acquired
822
   */
825
   */
823
  inline static uint32_t GetMaxInstances() throw (InotifyException)
826
  inline static uint32_t GetMaxInstances() throw (InotifyException)
824
  {
827
  {
825
    return GetCapability(IN_MAX_INSTANCES);
828
    return GetCapability(IN_MAX_INSTANCES);
826
  }
829
  }
827
 
830
 
828
  /// Sets the maximum number of inotify instances per process.
831
  /// Sets the maximum number of inotify instances per process.
829
  /**
832
  /**
830
   * \param[in] val new value
833
   * \param[in] val new value
831
   * \throw InotifyException thrown if the given value cannot be set
834
   * \throw InotifyException thrown if the given value cannot be set
832
   * \attention Using this function requires root privileges.
835
   * \attention Using this function requires root privileges.
833
   *            Beware of setting extensive values - the greater value
836
   *            Beware of setting extensive values - the greater value
834
   *            is set here the more physical memory may be used for the inotify
837
   *            is set here the more physical memory may be used for the inotify
835
   *            infrastructure.
838
   *            infrastructure.
836
   */
839
   */
837
  inline static void SetMaxInstances(uint32_t val) throw (InotifyException)
840
  inline static void SetMaxInstances(uint32_t val) throw (InotifyException)
838
  {
841
  {
839
    SetCapability(IN_MAX_INSTANCES, val);
842
    SetCapability(IN_MAX_INSTANCES, val);
840
  }
843
  }
841
 
844
 
842
  /// Returns the maximum number of inotify watches per instance.
845
  /// Returns the maximum number of inotify watches per instance.
843
  /**
846
  /**
844
   * It means the maximum number of inotify watches per inotify
847
   * It means the maximum number of inotify watches per inotify
845
   * file descriptor.
848
   * file descriptor.
846
   *
849
   *
847
   * \return maximum number of inotify watches
850
   * \return maximum number of inotify watches
848
   * \throw InotifyException thrown if the given value cannot be acquired
851
   * \throw InotifyException thrown if the given value cannot be acquired
849
   */
852
   */
850
  inline static uint32_t GetMaxWatches() throw (InotifyException)
853
  inline static uint32_t GetMaxWatches() throw (InotifyException)
851
  {
854
  {
852
    return GetCapability(IN_MAX_WATCHES);
855
    return GetCapability(IN_MAX_WATCHES);
853
  }
856
  }
854
 
857
 
855
  /// Sets the maximum number of inotify watches per instance.
858
  /// Sets the maximum number of inotify watches per instance.
856
  /**
859
  /**
857
   * \param[in] val new value
860
   * \param[in] val new value
858
   * \throw InotifyException thrown if the given value cannot be set
861
   * \throw InotifyException thrown if the given value cannot be set
859
   * \attention Using this function requires root privileges.
862
   * \attention Using this function requires root privileges.
860
   *            Beware of setting extensive values - the greater value
863
   *            Beware of setting extensive values - the greater value
861
   *            is set here the more physical memory may be used for the inotify
864
   *            is set here the more physical memory may be used for the inotify
862
   *            infrastructure.
865
   *            infrastructure.
863
   */
866
   */
864
  inline static void SetMaxWatches(uint32_t val) throw (InotifyException)
867
  inline static void SetMaxWatches(uint32_t val) throw (InotifyException)
865
  {
868
  {
866
    SetCapability(IN_MAX_WATCHES, val);
869
    SetCapability(IN_MAX_WATCHES, val);
867
  }
870
  }
868
871
869
private:
872
private:
870
  int m_fd;                             ///< file descriptor
873
  int m_fd;                             ///< file descriptor
871
  IN_WATCH_MAP m_watches;               ///< watches (by descriptors)
874
  IN_WATCH_MAP m_watches;               ///< watches (by descriptors)
872
  IN_WP_MAP m_paths;                    ///< watches (by paths)
875
  IN_WP_MAP m_paths;                    ///< watches (by paths)
873
  unsigned char m_buf[INOTIFY_BUFLEN];  ///< buffer for events
876
  unsigned char m_buf[INOTIFY_BUFLEN];  ///< buffer for events
874
  std::deque<InotifyEvent> m_events;    ///< event queue
877
  std::deque<InotifyEvent> m_events;    ///< event queue
875
 
878
 
876
  IN_LOCK_DECL
879
  IN_LOCK_DECL
877
 
880
 
878
  friend class InotifyWatch;
881
  friend class InotifyWatch;
879
 
882
 
880
  static std::string GetCapabilityPath(InotifyCapability_t cap) throw (InotifyException);
883
  static std::string GetCapabilityPath(InotifyCapability_t cap) throw (InotifyException);
881
};
884
};
882
885
883
886
884
#endif //_INOTIFYCXX_H_
887
#endif //_INOTIFYCXX_H_
885
888
886
 
889