Subversion Repositories QNX 8.QNX8 LLVM/Clang compiler suite

Rev

Blame | Last modification | View Log | Download | RSS feed

  1. //===- DirectoryWatcher.h - Listens for directory file changes --*- C++ -*-===//
  2. //
  3. // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
  4. // See https://llvm.org/LICENSE.txt for license information.
  5. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
  6. //
  7. //===----------------------------------------------------------------------===//
  8.  
  9. #ifndef LLVM_CLANG_DIRECTORYWATCHER_DIRECTORYWATCHER_H
  10. #define LLVM_CLANG_DIRECTORYWATCHER_DIRECTORYWATCHER_H
  11.  
  12. #include "llvm/ADT/ArrayRef.h"
  13. #include "llvm/ADT/StringRef.h"
  14. #include "llvm/Support/Error.h"
  15. #include <functional>
  16. #include <memory>
  17. #include <string>
  18.  
  19. namespace clang {
  20. /// Provides notifications for file changes in a directory.
  21. ///
  22. /// Invokes client-provided function on every filesystem event in the watched
  23. /// directory. Initially the watched directory is scanned and for every file
  24. /// found, an event is synthesized as if the file was added.
  25. ///
  26. /// This is not a general purpose directory monitoring tool - list of
  27. /// limitations follows.
  28. ///
  29. /// Only flat directories with no subdirectories are supported. In case
  30. /// subdirectories are present the behavior is unspecified - events *might* be
  31. /// passed to Receiver on macOS (due to FSEvents being used) while they
  32. /// *probably* won't be passed on Linux (due to inotify being used).
  33. ///
  34. /// Known potential inconsistencies
  35. /// - For files that are deleted befor the initial scan processed them, clients
  36. /// might receive Removed notification without any prior Added notification.
  37. /// - Multiple notifications might be produced when a file is added to the
  38. /// watched directory during the initial scan. We are choosing the lesser evil
  39. /// here as the only known alternative strategy would be to invalidate the
  40. /// watcher instance and force user to create a new one whenever filesystem
  41. /// event occurs during the initial scan but that would introduce continuous
  42. /// restarting failure mode (watched directory is not always "owned" by the same
  43. /// process that is consuming it). Since existing clients can handle duplicate
  44. /// events well, we decided for simplicity.
  45. ///
  46. /// Notifications are provided only for changes done through local user-space
  47. /// filesystem interface. Specifically, it's unspecified if notification would
  48. /// be provided in case of a:
  49. /// - a file mmap-ed and changed
  50. /// - a file changed via remote (NFS) or virtual (/proc) FS access to monitored
  51. /// directory
  52. /// - another filesystem mounted to the watched directory
  53. ///
  54. /// No support for LLVM VFS.
  55. ///
  56. /// It is unspecified whether notifications for files being deleted are sent in
  57. /// case the whole watched directory is sent.
  58. ///
  59. /// Directories containing "too many" files and/or receiving events "too
  60. /// frequently" are not supported - if the initial scan can't be finished before
  61. /// the watcher instance gets invalidated (see WatcherGotInvalidated) there's no
  62. /// good error handling strategy - the only option for client is to destroy the
  63. /// watcher, restart watching with new instance and hope it won't repeat.
  64. class DirectoryWatcher {
  65. public:
  66.   struct Event {
  67.     enum class EventKind {
  68.       Removed,
  69.       /// Content of a file was modified.
  70.       Modified,
  71.       /// The watched directory got deleted.
  72.       WatchedDirRemoved,
  73.       /// The DirectoryWatcher that originated this event is no longer valid and
  74.       /// its behavior is unspecified.
  75.       ///
  76.       /// The prime case is kernel signalling to OS-specific implementation of
  77.       /// DirectoryWatcher some resource limit being hit.
  78.       /// *Usually* kernel starts dropping or squashing events together after
  79.       /// that and so would DirectoryWatcher. This means that *some* events
  80.       /// might still be passed to Receiver but this behavior is unspecified.
  81.       ///
  82.       /// Another case is after the watched directory itself is deleted.
  83.       /// WatcherGotInvalidated will be received at least once during
  84.       /// DirectoryWatcher instance lifetime - when handling errors this is done
  85.       /// on best effort basis, when an instance is being destroyed then this is
  86.       /// guaranteed.
  87.       ///
  88.       /// The only proper response to this kind of event is to destruct the
  89.       /// originating DirectoryWatcher instance and create a new one.
  90.       WatcherGotInvalidated
  91.     };
  92.  
  93.     EventKind Kind;
  94.     /// Filename that this event is related to or an empty string in
  95.     /// case this event is related to the watched directory itself.
  96.     std::string Filename;
  97.  
  98.     Event(EventKind Kind, llvm::StringRef Filename)
  99.         : Kind(Kind), Filename(Filename) {}
  100.   };
  101.  
  102.   /// llvm fatal_error if \param Path doesn't exist or isn't a directory.
  103.   /// Returns llvm::Expected Error if OS kernel API told us we can't start
  104.   /// watching. In such case it's unclear whether just retrying has any chance
  105.   /// to succeed.
  106.   static llvm::Expected<std::unique_ptr<DirectoryWatcher>>
  107.   create(llvm::StringRef Path,
  108.          std::function<void(llvm::ArrayRef<DirectoryWatcher::Event> Events,
  109.                             bool IsInitial)>
  110.              Receiver,
  111.          bool WaitForInitialSync);
  112.  
  113.   virtual ~DirectoryWatcher() = default;
  114.   DirectoryWatcher(const DirectoryWatcher &) = delete;
  115.   DirectoryWatcher &operator=(const DirectoryWatcher &) = delete;
  116.   DirectoryWatcher(DirectoryWatcher &&) = default;
  117.  
  118. protected:
  119.   DirectoryWatcher() = default;
  120. };
  121.  
  122. } // namespace clang
  123.  
  124. #endif // LLVM_CLANG_DIRECTORYWATCHER_DIRECTORYWATCHER_H
  125.