watchman/watcher/Watcher.h (50 lines of code) (raw):

/* * Copyright (c) Meta Platforms, Inc. and affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. */ #pragma once #include <folly/futures/Future.h> #include <stdexcept> #include "watchman/PendingCollection.h" #include "watchman/fs/DirHandle.h" #include "watchman/thirdparty/jansson/jansson.h" #define HINT_NUM_DIRS 128 * 1024 #define CFG_HINT_NUM_DIRS "hint_num_dirs" struct watchman_file; namespace watchman { class QueryableView; class InMemoryView; class Root; class TerminalWatcherError : public std::runtime_error { public: using std::runtime_error::runtime_error; }; class Watcher : public std::enable_shared_from_this<Watcher> { public: /** * This Watcher instance's name. */ const w_string name; // if this watcher notifies for individual files contained within // a watched dir, false if it only notifies for dirs #define WATCHER_HAS_PER_FILE_NOTIFICATIONS 1 // if the watcher is comprised of multiple watchers #define WATCHER_HAS_SPLIT_WATCH 4 unsigned flags; Watcher(const char* name, unsigned flags); Watcher(Watcher&&) = delete; Watcher& operator=(Watcher&&) = delete; // Start up threads or similar. Called in the context of the // notify thread virtual bool start(const std::shared_ptr<Root>& root); // Perform watcher-specific cleanup for a watched root when it is freed virtual ~Watcher(); /** * If the returned SemiFuture is valid(), then this watcher requires * flushing any queued events. A Promise has been placed in the * PendingCollection and will be completed when InMemoryView processes the * event. * * In particular, FSEvents may return pending events out of order, so the * observation of a cookie file does not guarantee all prior changes have been * seen. * * Otherwise, this watcher does not require flushing, and a cookie file event * is considered sufficient synchronization. */ virtual folly::SemiFuture<folly::Unit> flushPendingEvents() { return folly::SemiFuture<folly::Unit>::makeEmpty(); } // Initiate an OS-level watch on the provided file virtual bool startWatchFile(watchman_file* file); // Initiate an OS-level watch on the provided dir, return a DIR // handle, or throw on error. virtual std::unique_ptr<DirHandle> startWatchDir( const std::shared_ptr<Root>& root, struct watchman_dir* dir, const char* path) = 0; /** * Signal any threads to terminate. Does not join them, but the reference * count on the root will not fall to zero until the threads stop. */ virtual void stopThreads() {} /** * Wait for an inotify event to become available. * Returns true if events are available or false if signalThreads() has been * called or timeout has elapsed. */ virtual bool waitNotify(int timeoutms) = 0; struct ConsumeNotifyRet { // Should the watch be cancelled? bool cancelSelf; }; /** * Consume any available notifications. If there are none pending, * does not block. * * Notifications are inserted into `coll`. */ virtual ConsumeNotifyRet consumeNotify( const std::shared_ptr<Root>& root, PendingChanges& coll) = 0; /** * Returns a JSON value containing this watcher's debug state. Intended for * inclusion in diagnostics. */ virtual json_ref getDebugInfo() { return json_null(); } /** * Clear any accumulated debug state. */ virtual void clearDebugInfo() {} }; } // namespace watchman