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