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