CernVM-FS  2.9.0
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
glue_buffer.cc
Go to the documentation of this file.
1 
5 #define __STDC_FORMAT_MACROS
6 
7 #include "cvmfs_config.h"
8 #include "glue_buffer.h"
9 
10 #include <errno.h>
11 #include <poll.h>
12 #include <unistd.h>
13 
14 #include <cassert>
15 #include <cstdlib>
16 #include <cstring>
17 
18 #include <string>
19 #include <vector>
20 
21 #include "logging.h"
22 #include "platform.h"
23 #include "smalloc.h"
24 #include "util/posix.h"
25 
26 using namespace std; // NOLINT
27 
28 namespace glue {
29 
30 PathStore &PathStore::operator= (const PathStore &other) {
31  if (&other == this)
32  return *this;
33 
34  delete string_heap_;
35  CopyFrom(other);
36  return *this;
37 }
38 
39 
40 PathStore::PathStore(const PathStore &other) {
41  CopyFrom(other);
42 }
43 
44 
45 void PathStore::CopyFrom(const PathStore &other) {
46  map_ = other.map_;
47 
48  string_heap_ = new StringHeap(other.string_heap_->used());
49  shash::Md5 empty_path = map_.empty_key();
50  for (unsigned i = 0; i < map_.capacity(); ++i) {
51  if (map_.keys()[i] != empty_path) {
52  (map_.values() + i)->name =
53  string_heap_->AddString(map_.values()[i].name.length(),
54  map_.values()[i].name.data());
55  }
56  }
57 }
58 
59 
60 //------------------------------------------------------------------------------
61 
62 
63 void InodeTracker::InitLock() {
64  lock_ =
65  reinterpret_cast<pthread_mutex_t *>(smalloc(sizeof(pthread_mutex_t)));
66  int retval = pthread_mutex_init(lock_, NULL);
67  assert(retval == 0);
68 }
69 
70 
71 void InodeTracker::CopyFrom(const InodeTracker &other) {
72  assert(other.version_ == kVersion);
73  version_ = kVersion;
74  path_map_ = other.path_map_;
75  inode_map_ = other.inode_map_;
76  inode_references_ = other.inode_references_;
77  statistics_ = other.statistics_;
78 }
79 
80 
81 InodeTracker::InodeTracker() {
82  version_ = kVersion;
83  InitLock();
84 }
85 
86 
87 InodeTracker::InodeTracker(const InodeTracker &other) {
88  CopyFrom(other);
89  InitLock();
90 }
91 
92 
93 InodeTracker &InodeTracker::operator= (const InodeTracker &other) {
94  if (&other == this)
95  return *this;
96 
97  CopyFrom(other);
98  return *this;
99 }
100 
101 
102 InodeTracker::~InodeTracker() {
103  pthread_mutex_destroy(lock_);
104  free(lock_);
105 }
106 
107 
108 //------------------------------------------------------------------------------
109 
110 NentryTracker::NentryTracker() : version_(kVersion), is_active_(true) {
111  pipe_terminate_[0] = pipe_terminate_[1] = -1;
113  InitLock();
114 }
115 
116 
118  if (pipe_terminate_[1] >= 0) {
119  char t = 'T';
120  WritePipe(pipe_terminate_[1], &t, 1);
121  pthread_join(thread_cleaner_, NULL);
123  }
124 }
125 
126 
128  CopyFrom(other);
129  pipe_terminate_[0] = pipe_terminate_[1] = -1;
131  InitLock();
132 }
133 
134 
136  if (&other == this)
137  return *this;
138 
139  Lock();
140  CopyFrom(other);
141  Unlock();
142  return *this;
143 }
144 
145 
147  assert(other.version_ == kVersion);
148 
149  version_ = kVersion;
150  statistics_ = other.statistics_;
151  is_active_ = other.is_active_;
152  entries_ = other.entries_;
153 }
154 
155 
157  Lock();
158  NentryTracker *new_tracker = new NentryTracker(*this);
159  statistics_.num_remove += entries_.size();
160  entries_.Clear();
161  Unlock();
162  return new_tracker;
163 }
164 
165 
166 void NentryTracker::SpawnCleaner(unsigned interval_s) {
167  assert(pipe_terminate_[0] == -1);
168  cleaning_interval_ms_ = interval_s * 1000;
171  int retval = pthread_create(&thread_cleaner_, NULL, MainCleaner, this);
172  assert(retval == 0);
173 }
174 
175 
176 void *NentryTracker::MainCleaner(void *data) {
177  NentryTracker *tracker = reinterpret_cast<NentryTracker *>(data);
178  LogCvmfs(kLogCvmfs, kLogDebug, "starting negative entry cache cleaner");
179 
180  struct pollfd watch_term;
181  watch_term.fd = tracker->pipe_terminate_[0];
182  watch_term.events = POLLIN | POLLPRI;
183  int timeout_ms = tracker->cleaning_interval_ms_;;
184  uint64_t deadline = platform_monotonic_time() + timeout_ms / 1000;
185  while (true) {
186  watch_term.revents = 0;
187  int retval = poll(&watch_term, 1, timeout_ms);
188  if (retval < 0) {
189  if (errno == EINTR) {
190  if (timeout_ms >= 0) {
191  uint64_t now = platform_monotonic_time();
192  timeout_ms = (now > deadline) ? 0 : (deadline - now) * 1000;
193  }
194  continue;
195  }
196  abort();
197  }
198  timeout_ms = tracker->cleaning_interval_ms_;
199  deadline = platform_monotonic_time() + timeout_ms / 1000;
200 
201  if (retval == 0) {
202  LogCvmfs(kLogCvmfs, kLogDebug, "negative entry cleaner: pruning");
203  tracker->Prune();
204  continue;
205  }
206 
207  assert(watch_term.revents != 0);
208 
209  char c = 0;
210  ReadPipe(tracker->pipe_terminate_[0], &c, 1);
211  assert(c == 'T');
212  break;
213  }
214  LogCvmfs(kLogCvmfs, kLogDebug, "stopping negative entry cache cleaner");
215  return NULL;
216 }
217 
218 
220  lock_ =
221  reinterpret_cast<pthread_mutex_t *>(smalloc(sizeof(pthread_mutex_t)));
222  int retval = pthread_mutex_init(lock_, NULL);
223  assert(retval == 0);
224 }
225 
226 
228  Lock();
230  Unlock();
231 }
232 
233 
235  Entry *head = NULL;
236  Lock();
237  entries_.Peek(&head);
238  return Cursor(head);
239 }
240 
241 
243  uint64_t *inode_parent, NameString *name)
244 {
245  if (cursor->head == NULL)
246  return false;
247  if (cursor->pos >= entries_.size())
248  return false;
249  Entry *e = cursor->head + cursor->pos;
250  *inode_parent = e->inode_parent;
251  *name = e->name;
252  cursor->pos++;
253  return true;
254  }
255 
256 
258  Unlock();
259 }
260 
261 } // namespace glue
#define LogCvmfs(source, mask,...)
Definition: logging.h:20
InodeReferences inode_references_
Definition: glue_buffer.h:629
void Lock() const
Definition: glue_buffer.h:714
void SpawnCleaner(unsigned interval_s)
Definition: glue_buffer.cc:166
static const unsigned kVersion
Definition: glue_buffer.h:709
uint64_t inode_parent
Definition: glue_buffer.h:649
void EndEnumerate(Cursor *cursor)
Definition: glue_buffer.cc:257
bool NextEntry(Cursor *cursor, uint64_t *inode_parent, NameString *name)
Definition: glue_buffer.cc:242
pthread_mutex_t * lock_
Definition: glue_buffer.h:734
NentryTracker * Move()
Definition: glue_buffer.cc:156
void Unlock() const
Definition: glue_buffer.h:718
BigQueue< Entry > entries_
Definition: glue_buffer.h:738
NameString name
Definition: glue_buffer.h:650
perf::Statistics * statistics_
Definition: repository.h:138
assert((mem||(size==0))&&"Out Of Memory")
StringHeap * string_heap_
Definition: glue_buffer.h:308
void MakePipe(int pipe_fd[2])
Definition: posix.cc:525
Definition: glue_buffer.h:641
void CopyFrom(const NentryTracker &other)
Definition: glue_buffer.cc:146
Statistics statistics_
Definition: glue_buffer.h:630
pthread_t thread_cleaner_
Definition: glue_buffer.h:742
uint64_t platform_monotonic_time()
SmallHashDynamic< shash::Md5, PathInfo > map_
Definition: glue_buffer.h:307
uint64_t used() const
Definition: glue_buffer.h:143
const char * kVersion
Definition: preload.cc:27
NentryTracker & operator=(const NentryTracker &other)
Definition: glue_buffer.cc:135
void WritePipe(int fd, const void *buf, size_t nbyte)
Definition: posix.cc:534
static void * MainCleaner(void *data)
Definition: glue_buffer.cc:176
void ReadPipe(int fd, void *buf, size_t nbyte)
Definition: posix.cc:546
void ClosePipe(int pipe_fd[2])
Definition: posix.cc:584
Statistics statistics_
Definition: glue_buffer.h:736
void DoPrune(uint64_t now)
Definition: glue_buffer.h:723