Subversion Repositories public

Rev

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

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