Subversion Repositories public

Rev

Rev 65 | 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
 
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;
45 luk 249
      if (pEvt->name != NULL)
250
        m_name = pEvt->name;
251
      m_pWatch = pWatch;
252
    }
253
    else {
254
      m_pWatch = NULL;
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
   */
47 luk 267
  int32_t GetDescriptor() const;
45 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
  {
47 luk 277
    return m_uMask;
45 luk 278
  }
279
 
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
 
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
  {
47 luk 298
    return IsType(m_uMask, uType);
45 luk 299
  }
300
 
301
  /// Returns the event cookie.
302
  /**
303
   * \return event cookie
304
   */
305
  inline uint32_t GetCookie() const
306
  {
47 luk 307
    return m_uCookie;
45 luk 308
  }
309
 
310
  /// Returns the event name length.
311
  /**
312
   * \return event name length
313
   */
314
  inline uint32_t GetLength() const
315
  {
47 luk 316
    return (uint32_t) m_name.length();
45 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
 
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
 
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:
47 luk 367
  uint32_t m_uMask;           ///< mask
368
  uint32_t m_uCookie;         ///< cookie
369
  std::string m_name;         ///< name
45 luk 370
  InotifyWatch* m_pWatch;     ///< source watch
371
};
372
 
373
 
374
 
375
/// inotify watch class
51 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
 */
45 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
47 luk 392
   * \param[in] fEnabled events enabled yes/no
45 luk 393
   */
47 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)
45 luk 399
  {
51 luk 400
    IN_LOCK_INIT
45 luk 401
  }
402
 
403
  /// Destructor.
51 luk 404
  ~InotifyWatch()
405
  {
406
    IN_LOCK_DONE
407
  }
45 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
 
49 luk 436
  /// Sets the watch event mask.
437
  /**
51 luk 438
   * If the watch is active (added to an instance of Inotify)
49 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
 
45 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
 
49 luk 457
  /// Enables/disables the watch.
458
  /**
51 luk 459
   * If the watch is active (added to an instance of Inotify)
49 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);
47 luk 470
 
49 luk 471
  /// Checks whether the watch is enabled.
472
  /**
473
   * \return true = enables, false = disabled
474
   */
47 luk 475
  inline bool IsEnabled() const
476
  {
477
    return m_fEnabled;
478
  }
479
 
63 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
 
45 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
501
  Inotify* m_pInotify;  ///< inotify object
47 luk 502
  bool m_fEnabled;      ///< events enabled yes/no
51 luk 503
 
504
  IN_LOCK_DECL
63 luk 505
 
65 luk 506
  /// Disables the watch (due to removing by the kernel).
63 luk 507
  /**
508
   * This method must be called after receiving an event.
509
   * It ensures the watch object is consistent with the kernel
510
   * data.
511
   */
65 luk 512
  void __Disable();
45 luk 513
};
514
 
515
 
516
/// Mapping from watch descriptors to watch objects.
517
typedef std::map<int32_t, InotifyWatch*> IN_WATCH_MAP;
518
 
49 luk 519
/// Mapping from paths to watch objects.
520
typedef std::map<std::string, InotifyWatch*> IN_WP_MAP;
45 luk 521
 
49 luk 522
 
45 luk 523
/// inotify class
51 luk 524
/**
525
 * It holds information about the inotify device descriptor
526
 * and manages the event queue.
527
 *
528
 * If the INOTIFY_THREAD_SAFE is defined this class is thread-safe.
529
 */
45 luk 530
class Inotify
531
{
532
public:
533
  /// Constructor.
534
  /**
535
   * Creates and initializes an instance of inotify communication
536
   * object (opens the inotify device).
47 luk 537
   *
538
   * \throw InotifyException thrown if inotify isn't available
45 luk 539
   */
47 luk 540
  Inotify() throw (InotifyException);
45 luk 541
 
542
  /// Destructor.
543
  /**
47 luk 544
   * Calls Close() due to clean-up.
45 luk 545
   */
546
  ~Inotify();
547
 
548
  /// Removes all watches and closes the inotify device.
549
  void Close();
47 luk 550
 
45 luk 551
  /// Adds a new watch.
552
  /**
553
   * \param[in] pWatch inotify watch
47 luk 554
   *
555
   * \throw InotifyException thrown if adding failed
45 luk 556
   */
47 luk 557
  void Add(InotifyWatch* pWatch) throw (InotifyException);
45 luk 558
 
559
  /// Adds a new watch.
560
  /**
561
   * \param[in] rWatch inotify watch
47 luk 562
   *
563
   * \throw InotifyException thrown if adding failed
45 luk 564
   */
47 luk 565
  inline void Add(InotifyWatch& rWatch) throw (InotifyException)
45 luk 566
  {
47 luk 567
    Add(&rWatch);
45 luk 568
  }
569
 
570
  /// Removes a watch.
571
  /**
572
   * If the given watch is not present it does nothing.
573
   *
574
   * \param[in] pWatch inotify watch
47 luk 575
   *
576
   * \throw InotifyException thrown if removing failed
45 luk 577
   */
47 luk 578
  void Remove(InotifyWatch* pWatch) throw (InotifyException);
45 luk 579
 
580
  /// Removes a watch.
581
  /**
582
   * If the given watch is not present it does nothing.
583
   *
584
   * \param[in] rWatch inotify watch
47 luk 585
   *
586
   * \throw InotifyException thrown if removing failed
45 luk 587
   */
47 luk 588
  inline void Remove(InotifyWatch& rWatch) throw (InotifyException)
45 luk 589
  {
590
    Remove(&rWatch);
591
  }
592
 
593
  /// Removes all watches.
594
  void RemoveAll();
595
 
596
  /// Returns the count of watches.
597
  /**
49 luk 598
   * This is the total count of all watches (regardless whether
599
   * enabled or not).
600
   *
45 luk 601
   * \return count of watches
51 luk 602
   *
603
   * \sa GetEnabledCount()
45 luk 604
   */
605
  inline size_t GetWatchCount() const
606
  {
51 luk 607
    IN_READ_BEGIN
608
    size_t n = (size_t) m_paths.size();
609
    IN_READ_END
610
    return n;
45 luk 611
  }
612
 
51 luk 613
  /// Returns the count of enabled watches.
614
  /**
615
   * \return count of enabled watches
616
   *
617
   * \sa GetWatchCount()
618
   */  
619
  inline size_t GetEnabledCount() const
620
  {
621
    IN_READ_BEGIN
622
    size_t n = (size_t) m_watches.size();
623
    IN_READ_END
624
    return n;
625
  }
626
 
45 luk 627
  /// Waits for inotify events.
628
  /**
47 luk 629
   * It waits until one or more events occur. When called
630
   * in nonblocking mode it only retrieves occurred events
631
   * to the internal queue and exits.
45 luk 632
   *
633
   * \param[in] fNoIntr if true it re-calls the system call after a handled signal
47 luk 634
   *
635
   * \throw InotifyException thrown if reading events failed
636
   *
637
   * \sa SetNonBlock()
45 luk 638
   */
47 luk 639
  void WaitForEvents(bool fNoIntr = false) throw (InotifyException);
45 luk 640
 
641
  /// Returns the count of received and queued events.
642
  /**
643
   * This number is related to the events in the queue inside
644
   * this object, not to the events pending in the kernel.
645
   *
646
   * \return count of events
647
   */
51 luk 648
  inline size_t GetEventCount()
649
  {
650
    IN_READ_BEGIN
651
    size_t n = (size_t) m_events.size();
652
    IN_READ_END
653
    return n;
654
  }
45 luk 655
 
656
  /// Extracts a queued inotify event.
657
  /**
658
   * The extracted event is removed from the queue.
659
   * If the pointer is NULL it does nothing.
660
   *
661
   * \param[in,out] pEvt event object
47 luk 662
   *
663
   * \throw InotifyException thrown if the provided pointer is NULL
45 luk 664
   */
47 luk 665
  bool GetEvent(InotifyEvent* pEvt) throw (InotifyException);
45 luk 666
 
667
  /// Extracts a queued inotify event.
668
  /**
669
   * The extracted event is removed from the queue.
670
   *
671
   * \param[in,out] rEvt event object
47 luk 672
   *
673
   * \throw InotifyException thrown only in very anomalous cases
45 luk 674
   */
47 luk 675
  bool GetEvent(InotifyEvent& rEvt) throw (InotifyException)
45 luk 676
  {
677
    return GetEvent(&rEvt);
678
  }
679
 
680
  /// Extracts a queued inotify event (without removing).
681
  /**
682
   * The extracted event stays in the queue.
683
   * If the pointer is NULL it does nothing.
684
   *
685
   * \param[in,out] pEvt event object
47 luk 686
   *
687
   * \throw InotifyException thrown if the provided pointer is NULL
45 luk 688
   */
47 luk 689
  bool PeekEvent(InotifyEvent* pEvt) throw (InotifyException);
45 luk 690
 
691
  /// Extracts a queued inotify event (without removing).
692
  /**
693
   * The extracted event stays in the queue.
694
   *
695
   * \param[in,out] rEvt event object
47 luk 696
   *
697
   * \throw InotifyException thrown only in very anomalous cases
45 luk 698
   */
47 luk 699
  bool PeekEvent(InotifyEvent& rEvt) throw (InotifyException)
45 luk 700
  {
701
    return PeekEvent(&rEvt);
702
  }
703
 
49 luk 704
  /// Searches for a watch by a watch descriptor.
45 luk 705
  /**
706
   * It tries to find a watch by the given descriptor.
707
   *
708
   * \param[in] iDescriptor watch descriptor
49 luk 709
   * \return pointer to a watch; NULL if no such watch exists
45 luk 710
   */
47 luk 711
  InotifyWatch* FindWatch(int iDescriptor);
712
 
49 luk 713
  /// Searches for a watch by a filesystem path.
714
  /**
715
   * It tries to find a watch by the given filesystem path.
716
   *
717
   * \param[in] rPath filesystem path
718
   * \return pointer to a watch; NULL if no such watch exists
719
   *
720
   * \attention The path must be exactly identical to the one
721
   *            used for the searched watch. Be careful about
722
   *            absolute/relative and case-insensitive paths.
723
   */
724
   InotifyWatch* FindWatch(const std::string& rPath);
725
 
47 luk 726
  /// Returns the file descriptor.
727
  /**
728
   * The descriptor can be used in standard low-level file
729
   * functions (poll(), select(), fcntl() etc.).
730
   *
731
   * \return valid file descriptor or -1 for inactive object
732
   *
733
   * \sa SetNonBlock()
734
   */
735
  inline int GetDescriptor() const
736
  {
737
    return m_fd;
738
  }
739
 
740
  /// Enables/disables non-blocking mode.
741
  /**
742
   * Use this mode if you want to monitor the descriptor
743
   * (acquired thru GetDescriptor()) in functions such as
744
   * poll(), select() etc.
745
   *
67 luk 746
   * Non-blocking mode is disabled by default.
747
   *
47 luk 748
   * \param[in] fNonBlock enable/disable non-blocking mode
749
   *
750
   * \throw InotifyException thrown if setting mode failed
751
   *
67 luk 752
   * \sa GetDescriptor(), SetCloseOnExec()
47 luk 753
   */
754
  void SetNonBlock(bool fNonBlock) throw (InotifyException);
63 luk 755
 
67 luk 756
  /// Enables/disables closing on exec.
757
  /**
758
   * Enable this if you want to close the descriptor when
759
   * executing another program. Otherwise, the descriptor
760
   * will be inherited.
761
   *
762
   * Closing on exec is disabled by default.
763
   *
764
   * \param[in] fClOnEx enable/disable closing on exec
765
   *
766
   * \throw InotifyException thrown if setting failed
767
   *
768
   * \sa GetDescriptor(), SetNonBlock()
769
   */
770
  void SetCloseOnExec(bool fClOnEx) throw (InotifyException);
771
 
63 luk 772
  /// Acquires a particular inotify capability/limit.
773
  /**
774
   * \param[in] cap capability/limit identifier
775
   * \return capability/limit value
776
   * \throw InotifyException thrown if the given value cannot be acquired
777
   */
778
  static uint32_t GetCapability(InotifyCapability_t cap) throw (InotifyException);
779
 
780
  /// Modifies a particular inotify capability/limit.
781
  /**
782
   * \param[in] cap capability/limit identifier
783
   * \param[in] val new capability/limit value
784
   * \throw InotifyException thrown if the given value cannot be set
785
   * \attention Using this function requires root privileges.
786
   *            Beware of setting extensive values - it may seriously
787
   *            affect system performance and/or stability.
788
   */
789
  static void SetCapability(InotifyCapability_t cap, uint32_t val) throw (InotifyException);
790
 
791
  /// Returns the maximum number of events in the kernel queue.
792
  /**
793
   * \return maximum number of events in the kernel queue
794
   * \throw InotifyException thrown if the given value cannot be acquired
795
   */
796
  inline static uint32_t GetMaxEvents() throw (InotifyException)
797
  {
798
    return GetCapability(IN_MAX_EVENTS);
799
  }
800
 
801
  /// Sets the maximum number of events in the kernel queue.
802
  /**
803
   * \param[in] val new value
804
   * \throw InotifyException thrown if the given value cannot be set
805
   * \attention Using this function requires root privileges.
806
   *            Beware of setting extensive values - the greater value
807
   *            is set here the more physical memory may be used for the inotify
808
   *            infrastructure.
809
   */
810
  inline static void SetMaxEvents(uint32_t val) throw (InotifyException)
811
  {
812
    SetCapability(IN_MAX_EVENTS, val);
813
  }
814
 
815
  /// Returns the maximum number of inotify instances per process.
816
  /**
817
   * It means the maximum number of open inotify file descriptors
818
   * per running process.
819
   *
820
   * \return maximum number of inotify instances
821
   * \throw InotifyException thrown if the given value cannot be acquired
822
   */
823
  inline static uint32_t GetMaxInstances() throw (InotifyException)
824
  {
825
    return GetCapability(IN_MAX_INSTANCES);
826
  }
827
 
828
  /// Sets the maximum number of inotify instances per process.
829
  /**
830
   * \param[in] val new value
831
   * \throw InotifyException thrown if the given value cannot be set
832
   * \attention Using this function requires root privileges.
833
   *            Beware of setting extensive values - the greater value
834
   *            is set here the more physical memory may be used for the inotify
835
   *            infrastructure.
836
   */
837
  inline static void SetMaxInstances(uint32_t val) throw (InotifyException)
838
  {
839
    SetCapability(IN_MAX_INSTANCES, val);
840
  }
841
 
842
  /// Returns the maximum number of inotify watches per instance.
843
  /**
844
   * It means the maximum number of inotify watches per inotify
845
   * file descriptor.
846
   *
847
   * \return maximum number of inotify watches
848
   * \throw InotifyException thrown if the given value cannot be acquired
849
   */
850
  inline static uint32_t GetMaxWatches() throw (InotifyException)
851
  {
852
    return GetCapability(IN_MAX_WATCHES);
853
  }
854
 
855
  /// Sets the maximum number of inotify watches per instance.
856
  /**
857
   * \param[in] val new value
858
   * \throw InotifyException thrown if the given value cannot be set
859
   * \attention Using this function requires root privileges.
860
   *            Beware of setting extensive values - the greater value
861
   *            is set here the more physical memory may be used for the inotify
862
   *            infrastructure.
863
   */
864
  inline static void SetMaxWatches(uint32_t val) throw (InotifyException)
865
  {
866
    SetCapability(IN_MAX_WATCHES, val);
867
  }
45 luk 868
 
869
private:
870
  int m_fd;                             ///< file descriptor
49 luk 871
  IN_WATCH_MAP m_watches;               ///< watches (by descriptors)
872
  IN_WP_MAP m_paths;                    ///< watches (by paths)
45 luk 873
  unsigned char m_buf[INOTIFY_BUFLEN];  ///< buffer for events
874
  std::deque<InotifyEvent> m_events;    ///< event queue
49 luk 875
 
51 luk 876
  IN_LOCK_DECL
877
 
49 luk 878
  friend class InotifyWatch;
63 luk 879
 
880
  static std::string GetCapabilityPath(InotifyCapability_t cap) throw (InotifyException);
45 luk 881
};
882
 
883
 
884
#endif //_INOTIFYCXX_H_
51 luk 885