Subversion Repositories public

Rev

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

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