Subversion Repositories public

Rev

Rev 81 | Only display areas with differences | Ignore whitespace | Details | Blame | Last modification | View Log | RSS feed

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