GCC Code Coverage Report


Directory: cvmfs/
File: cvmfs/file_watcher.cc
Date: 2024-04-28 02:33:07
Exec Total Coverage
Lines: 47 52 90.4%
Branches: 25 44 56.8%

Line Branch Exec Source
1 /**
2 * This file is part of the CernVM File System.
3 */
4
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
26 4 EventHandler::EventHandler() {}
27
28 8 EventHandler::~EventHandler() {}
29
30 const unsigned FileWatcher::kInitialDelay = 1000;
31 const unsigned FileWatcher::kMaxDelay = 10000;
32 const unsigned FileWatcher::kResetDelay = 50000;
33
34 4 FileWatcher::FileWatcher()
35 4 : handler_map_()
36
2/2
✓ Branch 0 taken 8 times.
✓ Branch 1 taken 4 times.
12 , control_pipe_to_back_()
37
2/2
✓ Branch 0 taken 8 times.
✓ Branch 1 taken 4 times.
12 , control_pipe_to_front_()
38 4 , started_(false) {}
39
40 8 FileWatcher::~FileWatcher() {
41 8 Stop();
42 }
43
44 4 FileWatcher *FileWatcher::Create() {
45 #ifdef __APPLE__
46 return new file_watcher::FileWatcherKqueue();
47 #else
48 #ifdef CVMFS_ENABLE_INOTIFY
49
1/2
✓ Branch 2 taken 4 times.
✗ Branch 3 not taken.
4 return new file_watcher::FileWatcherInotify();
50 #else
51 return NULL;
52 #endif
53 #endif
54 }
55
56 4 void FileWatcher::RegisterHandler(const std::string& file_path,
57 EventHandler* handler) {
58 4 handler_map_[file_path] = handler;
59 4 }
60
61 4 bool FileWatcher::Spawn() {
62
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 if (started_) {
63 return false;
64 }
65
66
1/2
✓ Branch 1 taken 4 times.
✗ Branch 2 not taken.
4 MakePipe(control_pipe_to_back_);
67
1/2
✓ Branch 1 taken 4 times.
✗ Branch 2 not taken.
4 MakePipe(control_pipe_to_front_);
68
69
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 4 times.
4 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
1/2
✓ Branch 1 taken 4 times.
✗ Branch 2 not taken.
4 ReadHalfPipe(control_pipe_to_front_[0], buffer, 1);
76
77 4 started_ = true;
78 4 return true;
79 }
80
81 8 void FileWatcher::Stop() {
82
2/2
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 4 times.
8 if (!started_) {
83 4 return;
84 }
85
86 4 WritePipe(control_pipe_to_back_[1], "q", 1);
87
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 4 times.
4 assert(pthread_join(thread_, NULL) == 0);
88
89 4 ClosePipe(control_pipe_to_front_);
90 4 ClosePipe(control_pipe_to_back_);
91
92
2/2
✓ Branch 3 taken 4 times.
✓ Branch 4 taken 4 times.
8 for (HandlerMap::iterator it = handler_map_.begin(); it != handler_map_.end();
93 4 ++it) {
94
1/2
✓ Branch 1 taken 4 times.
✗ Branch 2 not taken.
4 delete it->second;
95 }
96
97 4 started_ = false;
98 }
99
100 4 void* FileWatcher::BackgroundThread(void* d) {
101 4 FileWatcher* watcher = reinterpret_cast<FileWatcher*>(d);
102
103
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 4 times.
4 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 4 pthread_exit(NULL);
110 }
111
112 4 void FileWatcher::RegisterFilter(const std::string& file_path,
113 EventHandler* handler) {
114 4 bool done = false;
115
1/2
✓ Branch 1 taken 4 times.
✗ Branch 2 not taken.
4 BackoffThrottle throttle(kInitialDelay, kMaxDelay, kResetDelay);
116
2/2
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 4 times.
8 while (!done) {
117
1/2
✓ Branch 1 taken 4 times.
✗ Branch 2 not taken.
4 int wd = TryRegisterFilter(file_path);
118
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 if (wd < 0) {
119 LogCvmfs(
120 kLogCvmfs, kLogDebug,
121 "FileWatcher - Could not add watch for file %s. Retrying.",
122 file_path.c_str());
123 throttle.Throttle();
124 continue;
125 }
126
127
2/4
✓ Branch 1 taken 4 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 4 times.
✗ Branch 5 not taken.
4 watch_records_[wd] = WatchRecord(file_path, handler);
128
129 4 done = true;
130 }
131
1/2
✓ Branch 1 taken 4 times.
✗ Branch 2 not taken.
4 throttle.Reset();
132 4 }
133
134 } // namespace file_watcher
135