Subversion Repositories public

Rev

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

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