]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - contrib/llvm/tools/clang/include/clang/DirectoryWatcher/DirectoryWatcher.h
Fix a memory leak in if_delgroups() introduced in r334118.
[FreeBSD/FreeBSD.git] / contrib / llvm / tools / clang / include / clang / DirectoryWatcher / DirectoryWatcher.h
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.
63 class DirectoryWatcher {
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.
71       WatchedDirRemoved,
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.
89       WatcherGotInvalidated
90     };
91
92     EventKind Kind;
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