CernVM-FS  2.12.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  Stop();
42 }
43 
45 #ifdef __APPLE__
47 #else
48 #ifdef CVMFS_ENABLE_INOTIFY
50 #else
51  return NULL;
52 #endif
53 #endif
54 }
55 
56 void FileWatcher::RegisterHandler(const std::string& file_path,
57  EventHandler* handler) {
58  handler_map_[file_path] = handler;
59 }
60 
62  if (started_) {
63  return false;
64  }
65 
68 
69  assert(pthread_create(&thread_, NULL,
70  &FileWatcher::BackgroundThread, this) == 0);
71 
72  // Before returning, wait for a start signal in the control pipe
73  // from the background thread.
74  char buffer[1];
75  ReadHalfPipe(control_pipe_to_front_[0], buffer, 1);
76 
77  started_ = true;
78  return true;
79 }
80 
82  if (!started_) {
83  return;
84  }
85 
86  WritePipe(control_pipe_to_back_[1], "q", 1);
87  assert(pthread_join(thread_, NULL) == 0);
88 
91 
92  for (HandlerMap::iterator it = handler_map_.begin(); it != handler_map_.end();
93  ++it) {
94  delete it->second;
95  }
96 
97  started_ = false;
98 }
99 
101  FileWatcher* watcher = reinterpret_cast<FileWatcher*>(d);
102 
103  if (!watcher->RunEventLoop(watcher->handler_map_,
104  watcher->control_pipe_to_back_[0],
105  watcher->control_pipe_to_front_[1])) {
106  LogCvmfs(kLogCvmfs, kLogDebug, "Error running event loop.");
107  }
108 
109  pthread_exit(NULL);
110 }
111 
112 void FileWatcher::RegisterFilter(const std::string& file_path,
113  EventHandler* handler) {
114  bool done = false;
116  while (!done) {
117  int wd = TryRegisterFilter(file_path);
118  if (wd < 0) {
119  LogCvmfs(
121  "FileWatcher - Could not add watch for file %s. Retrying.",
122  file_path.c_str());
123  throttle.Throttle();
124  continue;
125  }
126 
127  watch_records_[wd] = WatchRecord(file_path, handler);
128 
129  done = true;
130  }
131  throttle.Reset();
132 }
133 
134 } // namespace file_watcher
void RegisterFilter(const std::string &file_path, EventHandler *handler)
static const unsigned kMaxDelay
Definition: file_watcher.h:80
static FileWatcher * Create()
Definition: file_watcher.cc:44
assert((mem||(size==0))&&"Out Of Memory")
static void * BackgroundThread(void *d)
static const unsigned kResetDelay
Definition: file_watcher.h:81
virtual bool RunEventLoop(const HandlerMap &handler_map, int read_pipe, int write_pipe)=0
void MakePipe(int pipe_fd[2])
Definition: posix.cc:492
void Throttle()
Definition: backoff.cc:50
void ReadHalfPipe(int fd, void *buf, size_t nbyte)
Definition: posix.cc:525
static const unsigned kInitialDelay
Definition: file_watcher.h:79
void Reset()
Definition: backoff.cc:42
void RegisterHandler(const std::string &file_path, EventHandler *handler)
Definition: file_watcher.cc:56
std::map< int, WatchRecord > watch_records_
Definition: file_watcher.h:91
virtual int TryRegisterFilter(const std::string &file_path)=0
void WritePipe(int fd, const void *buf, size_t nbyte)
Definition: posix.cc:501
void ClosePipe(int pipe_fd[2])
Definition: posix.cc:551
CVMFS_EXPORT void LogCvmfs(const LogSource source, const int mask, const char *format,...)
Definition: logging.cc:528