watchman/watcher/fsevents.h (75 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 <optional>
#include "watchman/RingBuffer.h"
#include "watchman/fs/Pipe.h"
#include "watchman/watcher/Watcher.h"
#if HAVE_FSEVENTS
namespace watchman {
class Client;
class Configuration;
struct FSEventsStream;
struct FSEventsLogEntry;
struct watchman_fsevent {
w_string path;
FSEventStreamEventFlags flags;
watchman_fsevent(w_string&& path, FSEventStreamEventFlags flags)
: path(std::move(path)), flags(flags) {}
};
class FSEventsWatcher : public Watcher {
public:
explicit FSEventsWatcher(
bool hasFileWatching,
const Configuration& config,
std::optional<w_string> dir = std::nullopt);
explicit FSEventsWatcher(
const w_string& root_path,
const Configuration& config,
std::optional<w_string> dir = std::nullopt);
~FSEventsWatcher();
bool start(const std::shared_ptr<Root>& root) override;
folly::SemiFuture<folly::Unit> flushPendingEvents() override;
std::unique_ptr<DirHandle> startWatchDir(
const std::shared_ptr<Root>& root,
struct watchman_dir* dir,
const char* path) override;
Watcher::ConsumeNotifyRet consumeNotify(
const std::shared_ptr<Root>& root,
PendingChanges& changes) override;
bool waitNotify(int timeoutms) override;
void stopThreads() override;
void FSEventsThread(const std::shared_ptr<Root>& root);
json_ref getDebugInfo() override;
void clearDebugInfo() override;
static void cmd_debug_fsevents_inject_drop(
Client* client,
const json_ref& args);
private:
static std::unique_ptr<FSEventsStream> fse_stream_make(
const std::shared_ptr<Root>& root,
FSEventsWatcher* watcher,
FSEventStreamEventId since,
w_string& failure_reason);
static void fse_callback(
ConstFSEventStreamRef,
void* clientCallBackInfo,
size_t numEvents,
void* eventPaths,
const FSEventStreamEventFlags eventFlags[],
const FSEventStreamEventId eventIds[]);
watchman::Pipe fsePipe_;
std::condition_variable fseCond_;
struct Items {
// Unflattened queue of pending events. The fse_callback function will push
// exactly one vector to the end of this one, flattening the vector would
// require extra copying and allocations.
std::vector<std::vector<watchman_fsevent>> items;
// Sync requests to be inserted into PendingCollection.
std::vector<folly::Promise<folly::Unit>> syncs;
};
folly::Synchronized<Items, std::mutex> items_;
std::unique_ptr<FSEventsStream> stream_;
const bool attemptResyncOnDrop_{false};
const bool hasFileWatching_{false};
const bool enableStreamFlush_{true};
std::optional<w_string> subdir{std::nullopt};
// Incremented in fse_callback
std::atomic<size_t> totalEventsSeen_{0};
/**
* If not null, holds a fixed-size ring of the last `fsevents_ring_log_size`
* FSEvents events.
*/
std::unique_ptr<RingBuffer<FSEventsLogEntry>> ringBuffer_;
};
} // namespace watchman
#endif