Subversion Repositories public

Rev

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

Rev Author Line No. Line
45 luk 1
 
2
/// inotify C++ interface header
3
/**
4
 * \file inotify-cxx.h
5
 *
6
 * inotify C++ interface
7
 *
63 luk 8
 * Copyright (C) 2006, 2007 Lukas Jelinek, <lukas@aiken.cz>
45 luk 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
 
49 luk 33
// Please ensure that the following headers take the right place
55 luk 34
#include <sys/syscall.h>
45 luk 35
#include <sys/inotify.h>
49 luk 36
 
37
// Use this if syscalls not defined
38
#ifndef __NR_inotify_init
45 luk 39
#include <sys/inotify-syscalls.h>
49 luk 40
#endif // __NR_inotify_init
45 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
 
47 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)
45 luk 53
 
63 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
 
51 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
47 luk 82
 
51 luk 83
#include <pthread.h>
47 luk 84
 
51 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
 
45 luk 145
// forward declaration
146
class InotifyWatch;
147
class Inotify;
148
 
149
 
47 luk 150
/// Class for inotify exceptions
51 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
 */
47 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
 
45 luk 211
/// inotify event class
212
/**
213
 * It holds all information about inotify event and provides
214
 * access to its particular values.
51 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.
45 luk 219
 */
220
class InotifyEvent
221
{
222
public:
223
  /// Constructor.
224
  /**
225
   * Creates a plain event.
226
   */
227
  InotifyEvent()
47 luk 228
  : m_uMask(0),
229
    m_uCookie(0)
45 luk 230
  {
231
    m_pWatch = NULL;
232
  }
233
 
234
  /// Constructor.
235
  /**
236
   * Creates an event based on inotify event data.
237
   * For NULL pointers it works the same way as InotifyEvent().
238
   *
239
   * \param[in] pEvt event data
240
   * \param[in] pWatch inotify watch
241
   */
242
  InotifyEvent(const struct inotify_event* pEvt, InotifyWatch* pWatch)
47 luk 243
  : m_uMask(0),
244
    m_uCookie(0)
45 luk 245
  {
246
    if (pEvt != NULL) {
47 luk 247
      m_uMask = (uint32_t) pEvt->mask;
248
      m_uCookie = (uint32_t) pEvt->cookie;
69 luk 249
      if (pEvt->name != NULL) {
250
        m_name = pEvt->len > 0
251
            ? pEvt->name
252
            : "";
253
      }
45 luk 254
      m_pWatch = pWatch;
255
    }
256
    else {
257
      m_pWatch = NULL;
258
    }
259
  }
260
 
261
  /// Destructor.
262
  ~InotifyEvent() {}
263
 
264
  /// Returns the event watch descriptor.
265
  /**
266
   * \return watch descriptor
267
   *
268
   * \sa InotifyWatch::GetDescriptor()
269
   */
47 luk 270
  int32_t GetDescriptor() const;
45 luk 271
 
272
  /// Returns the event mask.
273
  /**
274
   * \return event mask
275
   *
276
   * \sa InotifyWatch::GetMask()
277
   */
278
  inline uint32_t GetMask() const
279
  {
47 luk 280
    return m_uMask;
45 luk 281
  }
282
 
283
  /// Checks a value for the event type.
284
  /**
285
   * \param[in] uValue checked value
286
   * \param[in] uType type which is checked for
287
   * \return true = the value contains the given type, false = otherwise
288
   */
289
  inline static bool IsType(uint32_t uValue, uint32_t uType)
290
  {
291
    return ((uValue & uType) != 0) && ((~uValue & uType) == 0);
292
  }
293
 
294
  /// Checks for the event type.
295
  /**
296
   * \param[in] uType type which is checked for
297
   * \return true = event mask contains the given type, false = otherwise
298
   */
299
  inline bool IsType(uint32_t uType) const
300
  {
47 luk 301
    return IsType(m_uMask, uType);
45 luk 302
  }
303
 
304
  /// Returns the event cookie.
305
  /**
306
   * \return event cookie
307
   */
308
  inline uint32_t GetCookie() const
309
  {
47 luk 310
    return m_uCookie;
45 luk 311
  }
312
 
313
  /// Returns the event name length.
314
  /**
315
   * \return event name length
316
   */
317
  inline uint32_t GetLength() const
318
  {
47 luk 319
    return (uint32_t) m_name.length();
45 luk 320
  }
321
 
322
  /// Returns the event name.
323
  /**
324
   * \return event name
325
   */
326
  inline const std::string& GetName() const
327
  {
328
    return m_name;
329
  }
330
 
331
  /// Extracts the event name.
332
  /**
333
   * \param[out] rName event name
334
   */
335
  inline void GetName(std::string& rName) const
336
  {
337
    rName = GetName();
338
  }
339
 
340
  /// Returns the source watch.
341
  /**
342
   * \return source watch
343
   */
344
  inline InotifyWatch* GetWatch()
345
  {
346
    return m_pWatch;
347
  }
348
 
349
  /// Finds the appropriate mask for a name.
350
  /**
351
   * \param[in] rName mask name
352
   * \return mask for name; 0 on failure
353
   */
354
  static uint32_t GetMaskByName(const std::string& rName);
355
 
356
  /// Fills the string with all types contained in an event mask value.
357
  /**
358
   * \param[in] uValue event mask value
359
   * \param[out] rStr dumped event types
360
   */
361
  static void DumpTypes(uint32_t uValue, std::string& rStr);
362
 
363
  /// Fills the string with all types contained in the event mask.
364
  /**
365
   * \param[out] rStr dumped event types
366
   */
367
  void DumpTypes(std::string& rStr) const;
368
 
369
private:
47 luk 370
  uint32_t m_uMask;           ///< mask
371
  uint32_t m_uCookie;         ///< cookie
372
  std::string m_name;         ///< name
45 luk 373
  InotifyWatch* m_pWatch;     ///< source watch
374
};
375
 
376
 
377
 
378
/// inotify watch class
51 luk 379
/**
380
 * It holds information about the inotify watch on a particular
381
 * inode.
382
 *
383
 * If the INOTIFY_THREAD_SAFE is defined this class is thread-safe.
384
 */
45 luk 385
class InotifyWatch
386
{
387
public:
388
  /// Constructor.
389
  /**
390
   * Creates an inotify watch. Because this watch is
391
   * inactive it has an invalid descriptor (-1).
392
   *
393
   * \param[in] rPath watched file path
394
   * \param[in] uMask mask for events
47 luk 395
   * \param[in] fEnabled events enabled yes/no
45 luk 396
   */
47 luk 397
  InotifyWatch(const std::string& rPath, int32_t uMask, bool fEnabled = true)
398
  : m_path(rPath),
399
    m_uMask(uMask),
400
    m_wd((int32_t) -1),
401
    m_fEnabled(fEnabled)
45 luk 402
  {
51 luk 403
    IN_LOCK_INIT
45 luk 404
  }
405
 
406
  /// Destructor.
51 luk 407
  ~InotifyWatch()
408
  {
409
    IN_LOCK_DONE
410
  }
45 luk 411
 
412
  /// Returns the watch descriptor.
413
  /**
414
   * \return watch descriptor; -1 for inactive watch
415
   */
416
  inline int32_t GetDescriptor() const
417
  {
418
    return m_wd;
419
  }
420
 
421
  /// Returns the watched file path.
422
  /**
423
   * \return file path
424
   */
425
  inline const std::string& GetPath() const
426
  {
427
    return m_path;
428
  }
429
 
430
  /// Returns the watch event mask.
431
  /**
432
   * \return event mask
433
   */
434
  inline uint32_t GetMask() const
435
  {
436
    return (uint32_t) m_uMask;
437
  }
438
 
49 luk 439
  /// Sets the watch event mask.
440
  /**
51 luk 441
   * If the watch is active (added to an instance of Inotify)
49 luk 442
   * this method may fail due to unsuccessful re-setting
443
   * the watch in the kernel.
444
   *
445
   * \param[in] uMask event mask
446
   *
447
   * \throw InotifyException thrown if changing fails
448
   */
449
  void SetMask(uint32_t uMask) throw (InotifyException);  
450
 
45 luk 451
  /// Returns the appropriate inotify class instance.
452
  /**
453
   * \return inotify instance
454
   */
455
  inline Inotify* GetInotify()
456
  {
457
    return m_pInotify;
458
  }
459
 
49 luk 460
  /// Enables/disables the watch.
461
  /**
51 luk 462
   * If the watch is active (added to an instance of Inotify)
49 luk 463
   * this method may fail due to unsuccessful re-setting
464
   * the watch in the kernel.
465
   *
466
   * Re-setting the current state has no effect.
467
   *
468
   * \param[in] fEnabled set enabled yes/no
469
   *
470
   * \throw InotifyException thrown if enabling/disabling fails
471
   */
472
  void SetEnabled(bool fEnabled) throw (InotifyException);
47 luk 473
 
49 luk 474
  /// Checks whether the watch is enabled.
475
  /**
476
   * \return true = enables, false = disabled
477
   */
47 luk 478
  inline bool IsEnabled() const
479
  {
480
    return m_fEnabled;
481
  }
482
 
63 luk 483
  /// Checks whether the watch is recursive.
484
  /**
485
   * A recursive watch monitors a directory itself and all
486
   * its subdirectories. This watch is a logical object
487
   * which may have many underlying kernel watches.
488
   *
489
   * \return currently always false (recursive watches not yet supported)
490
   * \attention Recursive watches are currently NOT supported.
491
   *            They are planned for future versions.
492
   */
493
  inline bool IsRecursive() const
494
  {
495
    return false;    
496
  }
497
 
45 luk 498
private:
499
  friend class Inotify;
500
 
501
  std::string m_path;   ///< watched file path
502
  uint32_t m_uMask;     ///< event mask
503
  int32_t m_wd;         ///< watch descriptor
504
  Inotify* m_pInotify;  ///< inotify object
47 luk 505
  bool m_fEnabled;      ///< events enabled yes/no
51 luk 506
 
507
  IN_LOCK_DECL
63 luk 508
 
65 luk 509
  /// Disables the watch (due to removing by the kernel).
63 luk 510
  /**
511
   * This method must be called after receiving an event.
512
   * It ensures the watch object is consistent with the kernel
513
   * data.
514
   */
65 luk 515
  void __Disable();
45 luk 516
};
517
 
518
 
519
/// Mapping from watch descriptors to watch objects.
520
typedef std::map<int32_t, InotifyWatch*> IN_WATCH_MAP;
521
 
49 luk 522
/// Mapping from paths to watch objects.
523
typedef std::map<std::string, InotifyWatch*> IN_WP_MAP;
45 luk 524
 
49 luk 525
 
45 luk 526
/// inotify class
51 luk 527
/**
528
 * It holds information about the inotify device descriptor
529
 * and manages the event queue.
530
 *
531
 * If the INOTIFY_THREAD_SAFE is defined this class is thread-safe.
532
 */
45 luk 533
class Inotify
534
{
535
public:
536
  /// Constructor.
537
  /**
538
   * Creates and initializes an instance of inotify communication
539
   * object (opens the inotify device).
47 luk 540
   *
541
   * \throw InotifyException thrown if inotify isn't available
45 luk 542
   */
47 luk 543
  Inotify() throw (InotifyException);
45 luk 544
 
545
  /// Destructor.
546
  /**
47 luk 547
   * Calls Close() due to clean-up.
45 luk 548
   */
549
  ~Inotify();
550
 
551
  /// Removes all watches and closes the inotify device.
552
  void Close();
47 luk 553
 
45 luk 554
  /// Adds a new watch.
555
  /**
556
   * \param[in] pWatch inotify watch
47 luk 557
   *
558
   * \throw InotifyException thrown if adding failed
45 luk 559
   */
47 luk 560
  void Add(InotifyWatch* pWatch) throw (InotifyException);
45 luk 561
 
562
  /// Adds a new watch.
563
  /**
564
   * \param[in] rWatch inotify watch
47 luk 565
   *
566
   * \throw InotifyException thrown if adding failed
45 luk 567
   */
47 luk 568
  inline void Add(InotifyWatch& rWatch) throw (InotifyException)
45 luk 569
  {
47 luk 570
    Add(&rWatch);
45 luk 571
  }
572
 
573
  /// Removes a watch.
574
  /**
575
   * If the given watch is not present it does nothing.
576
   *
577
   * \param[in] pWatch inotify watch
47 luk 578
   *
579
   * \throw InotifyException thrown if removing failed
45 luk 580
   */
47 luk 581
  void Remove(InotifyWatch* pWatch) throw (InotifyException);
45 luk 582
 
583
  /// Removes a watch.
584
  /**
585
   * If the given watch is not present it does nothing.
586
   *
587
   * \param[in] rWatch inotify watch
47 luk 588
   *
589
   * \throw InotifyException thrown if removing failed
45 luk 590
   */
47 luk 591
  inline void Remove(InotifyWatch& rWatch) throw (InotifyException)
45 luk 592
  {
593
    Remove(&rWatch);
594
  }
595
 
596
  /// Removes all watches.
597
  void RemoveAll();
598
 
599
  /// Returns the count of watches.
600
  /**
49 luk 601
   * This is the total count of all watches (regardless whether
602
   * enabled or not).
603
   *
45 luk 604
   * \return count of watches
51 luk 605
   *
606
   * \sa GetEnabledCount()
45 luk 607
   */
608
  inline size_t GetWatchCount() const
609
  {
51 luk 610
    IN_READ_BEGIN
611
    size_t n = (size_t) m_paths.size();
612
    IN_READ_END
613
    return n;
45 luk 614
  }
615
 
51 luk 616
  /// Returns the count of enabled watches.
617
  /**
618
   * \return count of enabled watches
619
   *
620
   * \sa GetWatchCount()
621
   */  
622
  inline size_t GetEnabledCount() const
623
  {
624
    IN_READ_BEGIN
625
    size_t n = (size_t) m_watches.size();
626
    IN_READ_END
627
    return n;
628
  }
629
 
45 luk 630
  /// Waits for inotify events.
631
  /**
47 luk 632
   * It waits until one or more events occur. When called
633
   * in nonblocking mode it only retrieves occurred events
634
   * to the internal queue and exits.
45 luk 635
   *
636
   * \param[in] fNoIntr if true it re-calls the system call after a handled signal
47 luk 637
   *
638
   * \throw InotifyException thrown if reading events failed
639
   *
640
   * \sa SetNonBlock()
45 luk 641
   */
47 luk 642
  void WaitForEvents(bool fNoIntr = false) throw (InotifyException);
45 luk 643
 
644
  /// Returns the count of received and queued events.
645
  /**
646
   * This number is related to the events in the queue inside
647
   * this object, not to the events pending in the kernel.
648
   *
649
   * \return count of events
650
   */
51 luk 651
  inline size_t GetEventCount()
652
  {
653
    IN_READ_BEGIN
654
    size_t n = (size_t) m_events.size();
655
    IN_READ_END
656
    return n;
657
  }
45 luk 658
 
659
  /// Extracts a queued inotify event.
660
  /**
661
   * The extracted event is removed from the queue.
662
   * If the pointer is NULL it does nothing.
663
   *
664
   * \param[in,out] pEvt event object
47 luk 665
   *
666
   * \throw InotifyException thrown if the provided pointer is NULL
45 luk 667
   */
47 luk 668
  bool GetEvent(InotifyEvent* pEvt) throw (InotifyException);
45 luk 669
 
670
  /// Extracts a queued inotify event.
671
  /**
672
   * The extracted event is removed from the queue.
673
   *
674
   * \param[in,out] rEvt event object
47 luk 675
   *
676
   * \throw InotifyException thrown only in very anomalous cases
45 luk 677
   */
47 luk 678
  bool GetEvent(InotifyEvent& rEvt) throw (InotifyException)
45 luk 679
  {
680
    return GetEvent(&rEvt);
681
  }
682
 
683
  /// Extracts a queued inotify event (without removing).
684
  /**
685
   * The extracted event stays in the queue.
686
   * If the pointer is NULL it does nothing.
687
   *
688
   * \param[in,out] pEvt event object
47 luk 689
   *
690
   * \throw InotifyException thrown if the provided pointer is NULL
45 luk 691
   */
47 luk 692
  bool PeekEvent(InotifyEvent* pEvt) throw (InotifyException);
45 luk 693
 
694
  /// Extracts a queued inotify event (without removing).
695
  /**
696
   * The extracted event stays in the queue.
697
   *
698
   * \param[in,out] rEvt event object
47 luk 699
   *
700
   * \throw InotifyException thrown only in very anomalous cases
45 luk 701
   */
47 luk 702
  bool PeekEvent(InotifyEvent& rEvt) throw (InotifyException)
45 luk 703
  {
704
    return PeekEvent(&rEvt);
705
  }
706
 
49 luk 707
  /// Searches for a watch by a watch descriptor.
45 luk 708
  /**
709
   * It tries to find a watch by the given descriptor.
710
   *
711
   * \param[in] iDescriptor watch descriptor
49 luk 712
   * \return pointer to a watch; NULL if no such watch exists
45 luk 713
   */
47 luk 714
  InotifyWatch* FindWatch(int iDescriptor);
715
 
49 luk 716
  /// Searches for a watch by a filesystem path.
717
  /**
718
   * It tries to find a watch by the given filesystem path.
719
   *
720
   * \param[in] rPath filesystem path
721
   * \return pointer to a watch; NULL if no such watch exists
722
   *
723
   * \attention The path must be exactly identical to the one
724
   *            used for the searched watch. Be careful about
725
   *            absolute/relative and case-insensitive paths.
726
   */
727
   InotifyWatch* FindWatch(const std::string& rPath);
728
 
47 luk 729
  /// Returns the file descriptor.
730
  /**
731
   * The descriptor can be used in standard low-level file
732
   * functions (poll(), select(), fcntl() etc.).
733
   *
734
   * \return valid file descriptor or -1 for inactive object
735
   *
736
   * \sa SetNonBlock()
737
   */
738
  inline int GetDescriptor() const
739
  {
740
    return m_fd;
741
  }
742
 
743
  /// Enables/disables non-blocking mode.
744
  /**
745
   * Use this mode if you want to monitor the descriptor
746
   * (acquired thru GetDescriptor()) in functions such as
747
   * poll(), select() etc.
748
   *
67 luk 749
   * Non-blocking mode is disabled by default.
750
   *
47 luk 751
   * \param[in] fNonBlock enable/disable non-blocking mode
752
   *
753
   * \throw InotifyException thrown if setting mode failed
754
   *
67 luk 755
   * \sa GetDescriptor(), SetCloseOnExec()
47 luk 756
   */
757
  void SetNonBlock(bool fNonBlock) throw (InotifyException);
63 luk 758
 
67 luk 759
  /// Enables/disables closing on exec.
760
  /**
761
   * Enable this if you want to close the descriptor when
762
   * executing another program. Otherwise, the descriptor
763
   * will be inherited.
764
   *
765
   * Closing on exec is disabled by default.
766
   *
767
   * \param[in] fClOnEx enable/disable closing on exec
768
   *
769
   * \throw InotifyException thrown if setting failed
770
   *
771
   * \sa GetDescriptor(), SetNonBlock()
772
   */
773
  void SetCloseOnExec(bool fClOnEx) throw (InotifyException);
774
 
63 luk 775
  /// Acquires a particular inotify capability/limit.
776
  /**
777
   * \param[in] cap capability/limit identifier
778
   * \return capability/limit value
779
   * \throw InotifyException thrown if the given value cannot be acquired
780
   */
781
  static uint32_t GetCapability(InotifyCapability_t cap) throw (InotifyException);
782
 
783
  /// Modifies a particular inotify capability/limit.
784
  /**
785
   * \param[in] cap capability/limit identifier
786
   * \param[in] val new capability/limit value
787
   * \throw InotifyException thrown if the given value cannot be set
788
   * \attention Using this function requires root privileges.
789
   *            Beware of setting extensive values - it may seriously
790
   *            affect system performance and/or stability.
791
   */
792
  static void SetCapability(InotifyCapability_t cap, uint32_t val) throw (InotifyException);
793
 
794
  /// Returns the maximum number of events in the kernel queue.
795
  /**
796
   * \return maximum number of events in the kernel queue
797
   * \throw InotifyException thrown if the given value cannot be acquired
798
   */
799
  inline static uint32_t GetMaxEvents() throw (InotifyException)
800
  {
801
    return GetCapability(IN_MAX_EVENTS);
802
  }
803
 
804
  /// Sets the maximum number of events in the kernel queue.
805
  /**
806
   * \param[in] val new value
807
   * \throw InotifyException thrown if the given value cannot be set
808
   * \attention Using this function requires root privileges.
809
   *            Beware of setting extensive values - the greater value
810
   *            is set here the more physical memory may be used for the inotify
811
   *            infrastructure.
812
   */
813
  inline static void SetMaxEvents(uint32_t val) throw (InotifyException)
814
  {
815
    SetCapability(IN_MAX_EVENTS, val);
816
  }
817
 
818
  /// Returns the maximum number of inotify instances per process.
819
  /**
820
   * It means the maximum number of open inotify file descriptors
821
   * per running process.
822
   *
823
   * \return maximum number of inotify instances
824
   * \throw InotifyException thrown if the given value cannot be acquired
825
   */
826
  inline static uint32_t GetMaxInstances() throw (InotifyException)
827
  {
828
    return GetCapability(IN_MAX_INSTANCES);
829
  }
830
 
831
  /// Sets the maximum number of inotify instances per process.
832
  /**
833
   * \param[in] val new value
834
   * \throw InotifyException thrown if the given value cannot be set
835
   * \attention Using this function requires root privileges.
836
   *            Beware of setting extensive values - the greater value
837
   *            is set here the more physical memory may be used for the inotify
838
   *            infrastructure.
839
   */
840
  inline static void SetMaxInstances(uint32_t val) throw (InotifyException)
841
  {
842
    SetCapability(IN_MAX_INSTANCES, val);
843
  }
844
 
845
  /// Returns the maximum number of inotify watches per instance.
846
  /**
847
   * It means the maximum number of inotify watches per inotify
848
   * file descriptor.
849
   *
850
   * \return maximum number of inotify watches
851
   * \throw InotifyException thrown if the given value cannot be acquired
852
   */
853
  inline static uint32_t GetMaxWatches() throw (InotifyException)
854
  {
855
    return GetCapability(IN_MAX_WATCHES);
856
  }
857
 
858
  /// Sets the maximum number of inotify watches per instance.
859
  /**
860
   * \param[in] val new value
861
   * \throw InotifyException thrown if the given value cannot be set
862
   * \attention Using this function requires root privileges.
863
   *            Beware of setting extensive values - the greater value
864
   *            is set here the more physical memory may be used for the inotify
865
   *            infrastructure.
866
   */
867
  inline static void SetMaxWatches(uint32_t val) throw (InotifyException)
868
  {
869
    SetCapability(IN_MAX_WATCHES, val);
870
  }
45 luk 871
 
872
private:
873
  int m_fd;                             ///< file descriptor
49 luk 874
  IN_WATCH_MAP m_watches;               ///< watches (by descriptors)
875
  IN_WP_MAP m_paths;                    ///< watches (by paths)
45 luk 876
  unsigned char m_buf[INOTIFY_BUFLEN];  ///< buffer for events
877
  std::deque<InotifyEvent> m_events;    ///< event queue
49 luk 878
 
51 luk 879
  IN_LOCK_DECL
880
 
49 luk 881
  friend class InotifyWatch;
63 luk 882
 
883
  static std::string GetCapabilityPath(InotifyCapability_t cap) throw (InotifyException);
45 luk 884
};
885
 
886
 
887
#endif //_INOTIFYCXX_H_
51 luk 888