Subversion Repositories public

Rev

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