Subversion Repositories public

Rev

Rev 23 | Rev 33 | Go to most recent revision | Details | Compare with Previous | Last modification | View Log | RSS feed

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