1
#pragma once
2

            
3
#include <cstdint>
4
#include <list>
5
#include <string>
6

            
7
#include "envoy/api/api.h"
8
#include "envoy/event/dispatcher.h"
9
#include "envoy/filesystem/watcher.h"
10

            
11
#include "source/common/common/logger.h"
12

            
13
#include "absl/container/node_hash_map.h"
14

            
15
namespace Envoy {
16
namespace Filesystem {
17

            
18
/**
19
 * Implementation of Watcher that uses inotify. inotify is an awful API. In order to make this work
20
 * in a somewhat sane way we always watch the directory that owns the thing being watched, and then
21
 * filter for events that are relevant to the thing being watched.
22
 */
23
class WatcherImpl : public Watcher, Logger::Loggable<Logger::Id::file> {
24
public:
25
  WatcherImpl(Event::Dispatcher& dispatcher, Filesystem::Instance& file_system);
26
  ~WatcherImpl() override;
27

            
28
  // Filesystem::Watcher
29
  absl::Status addWatch(absl::string_view path, uint32_t events, OnChangedCb cb) override;
30

            
31
private:
32
  struct FileWatch {
33
    std::string file_;
34
    uint32_t events_;
35
    OnChangedCb cb_;
36
  };
37

            
38
  struct DirectoryWatch {
39
    std::list<FileWatch> watches_;
40
  };
41

            
42
  absl::Status onInotifyEvent();
43
  void callAndLogOnError(OnChangedCb& cb, uint32_t events, const std::string& file);
44

            
45
  Filesystem::Instance& file_system_;
46
  int inotify_fd_;
47
  Event::FileEventPtr inotify_event_;
48
  absl::node_hash_map<int, DirectoryWatch> callback_map_;
49
};
50

            
51
} // namespace Filesystem
52
} // namespace Envoy