CernVM-FS  2.13.0
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
file_watcher.cc
Go to the documentation of this file.
1 
5 #include "file_watcher.h"
6 
7 #include <unistd.h>
8 
9 #include <cassert>
10 
11 #include "backoff.h"
12 
13 #ifdef __APPLE__
14 #include "file_watcher_kqueue.h"
15 #else
16 #ifdef CVMFS_ENABLE_INOTIFY
17 #include "file_watcher_inotify.h"
18 #endif
19 #endif
20 
21 #include "util/logging.h"
22 #include "util/posix.h"
23 
24 namespace file_watcher {
25 
27 
29 
30 const unsigned FileWatcher::kInitialDelay = 1000;
31 const unsigned FileWatcher::kMaxDelay = 10000;
32 const unsigned FileWatcher::kResetDelay = 50000;
33 
35  : handler_map_()
36  , control_pipe_to_back_()
37  , control_pipe_to_front_()
38  , started_(false) { }
39 
41 
43 #ifdef __APPLE__
44  return new file_watcher::FileWatcherKqueue();
45 #else
46 #ifdef CVMFS_ENABLE_INOTIFY
48 #else
49  return NULL;
50 #endif
51 #endif
52 }
53 
54 void FileWatcher::RegisterHandler(const std::string &file_path,
55  EventHandler *handler) {
56  handler_map_[file_path] = handler;
57 }
58 
60  if (started_) {
61  return false;
62  }
63 
66 
67  assert(pthread_create(&thread_, NULL, &FileWatcher::BackgroundThread, this)
68  == 0);
69 
70  // Before returning, wait for a start signal in the control pipe
71  // from the background thread.
72  char buffer[1];
73  ReadHalfPipe(control_pipe_to_front_[0], buffer, 1);
74 
75  started_ = true;
76  return true;
77 }
78 
80  if (!started_) {
81  return;
82  }
83 
84  WritePipe(control_pipe_to_back_[1], "q", 1);
85  assert(pthread_join(thread_, NULL) == 0);
86 
89 
90  for (HandlerMap::iterator it = handler_map_.begin(); it != handler_map_.end();
91  ++it) {
92  delete it->second;
93  }
94 
95  started_ = false;
96 }
97 
99  FileWatcher *watcher = reinterpret_cast<FileWatcher *>(d);
100 
101  if (!watcher->RunEventLoop(watcher->handler_map_,
102  watcher->control_pipe_to_back_[0],
103  watcher->control_pipe_to_front_[1])) {
104  LogCvmfs(kLogCvmfs, kLogDebug, "Error running event loop.");
105  }
106 
107  pthread_exit(NULL);
108 }
109 
110 void FileWatcher::RegisterFilter(const std::string &file_path,
111  EventHandler *handler) {
112  bool done = false;
114  while (!done) {
115  const int wd = TryRegisterFilter(file_path);
116  if (wd < 0) {
118  "FileWatcher - Could not add watch for file %s. Retrying.",
119  file_path.c_str());
120  throttle.Throttle();
121  continue;
122  }
123 
124  watch_records_[wd] = WatchRecord(file_path, handler);
125 
126  done = true;
127  }
128  throttle.Reset();
129 }
130 
131 } // namespace file_watcher
void RegisterFilter(const std::string &file_path, EventHandler *handler)
static const unsigned kMaxDelay
Definition: file_watcher.h:77
static FileWatcher * Create()
Definition: file_watcher.cc:42
assert((mem||(size==0))&&"Out Of Memory")
static void * BackgroundThread(void *d)
Definition: file_watcher.cc:98
static const unsigned kResetDelay
Definition: file_watcher.h:78
virtual bool RunEventLoop(const HandlerMap &handler_map, int read_pipe, int write_pipe)=0
void MakePipe(int pipe_fd[2])
Definition: posix.cc:487
void Throttle()
Definition: backoff.cc:48
bool ReadHalfPipe(int fd, void *buf, size_t nbyte, unsigned timeout_ms)
Definition: posix.cc:520
static const unsigned kInitialDelay
Definition: file_watcher.h:76
void Reset()
Definition: backoff.cc:40
void RegisterHandler(const std::string &file_path, EventHandler *handler)
Definition: file_watcher.cc:54
std::map< int, WatchRecord > watch_records_
Definition: file_watcher.h:87
virtual int TryRegisterFilter(const std::string &file_path)=0
void WritePipe(int fd, const void *buf, size_t nbyte)
Definition: posix.cc:496
void ClosePipe(int pipe_fd[2])
Definition: posix.cc:559
CVMFS_EXPORT void LogCvmfs(const LogSource source, const int mask, const char *format,...)
Definition: logging.cc:545