CernVM-FS  2.13.0
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
libcvmfs_cache.cc
Go to the documentation of this file.
1 
5 #define _FILE_OFFSET_BITS 64
6 #define __STDC_FORMAT_MACROS
7 
8 
9 #include "libcvmfs_cache.h"
10 
11 #include <unistd.h>
12 
13 #include <cassert>
14 #include <cstdlib>
15 #include <cstring>
16 #include <string>
17 
18 #include "cache_plugin/channel.h"
19 #include "cache_transport.h"
20 #include "crypto/hash.h"
21 #include "manifest.h"
22 #include "monitor.h"
23 #include "util/pointer.h"
24 
25 using namespace std; // NOLINT
26 
27 namespace {
28 
29 static shash::Any Chash2Cpphash(const struct cvmcache_hash *h) {
30  shash::Any hash;
31  memcpy(hash.digest, h->digest, sizeof(h->digest));
32  hash.algorithm = static_cast<shash::Algorithms>(h->algorithm);
33  return hash;
34 }
35 
36 static struct cvmcache_hash Cpphash2Chash(const shash::Any &hash) {
37  struct cvmcache_hash h;
38  memcpy(h.digest, hash.digest, sizeof(h.digest));
39  h.algorithm = hash.algorithm;
40  return h;
41 }
42 
43 static enum cvmcache_object_type ObjectType2CType(cvmfs::EnumObjectType type) {
44  switch (type) {
45  case cvmfs::OBJECT_REGULAR:
47  case cvmfs::OBJECT_CATALOG:
49  case cvmfs::OBJECT_VOLATILE:
51  }
52  abort();
53 }
54 
56  public:
57  explicit ForwardCachePlugin(struct cvmcache_callbacks *callbacks)
58  : CachePlugin(callbacks->capabilities), callbacks_(*callbacks) {
59  assert(callbacks->cvmcache_chrefcnt != NULL);
60  assert(callbacks->cvmcache_obj_info != NULL);
61  assert(callbacks->cvmcache_pread != NULL);
62  if (callbacks->capabilities & CVMCACHE_CAP_WRITE) {
63  assert(callbacks->cvmcache_start_txn != NULL);
64  assert(callbacks->cvmcache_write_txn != NULL);
65  assert(callbacks->cvmcache_commit_txn != NULL);
66  assert(callbacks->cvmcache_abort_txn != NULL);
67  }
68  if (callbacks->capabilities & CVMCACHE_CAP_INFO)
69  assert(callbacks->cvmcache_info != NULL);
70  if (callbacks->capabilities & CVMCACHE_CAP_SHRINK_RATE)
72  if (callbacks->capabilities & CVMCACHE_CAP_SHRINK)
73  assert(callbacks->cvmcache_shrink != NULL);
74  if (callbacks->capabilities & CVMCACHE_CAP_LIST) {
75  assert(callbacks->cvmcache_listing_begin != NULL);
76  assert(callbacks->cvmcache_listing_next != NULL);
77  assert(callbacks->cvmcache_listing_end != NULL);
78  }
79  if (callbacks->capabilities & CVMCACHE_CAP_BREADCRUMB) {
80  assert(callbacks->cvmcache_breadcrumb_store != NULL);
81  assert(callbacks->cvmcache_breadcrumb_load != NULL);
82  }
83  }
84  virtual ~ForwardCachePlugin() { }
85 
86  protected:
87  virtual cvmfs::EnumStatus ChangeRefcount(const shash::Any &id,
88  int32_t change_by) {
89  struct cvmcache_hash c_hash = Cpphash2Chash(id);
90  int result = callbacks_.cvmcache_chrefcnt(&c_hash, change_by);
91  return static_cast<cvmfs::EnumStatus>(result);
92  }
93 
94  virtual cvmfs::EnumStatus GetObjectInfo(const shash::Any &id,
95  ObjectInfo *info) {
96  struct cvmcache_hash c_hash = Cpphash2Chash(id);
97  cvmcache_object_info c_info;
98  memset(&c_info, 0, sizeof(c_info));
100  int result = callbacks_.cvmcache_obj_info(&c_hash, &c_info);
101  info->size = c_info.size;
102  info->object_type = static_cast<cvmfs::EnumObjectType>(c_info.type);
103  info->pinned = c_info.pinned;
104  if (c_info.description) {
105  info->description = string(c_info.description);
106  free(c_info.description);
107  }
108  return static_cast<cvmfs::EnumStatus>(result);
109  }
110 
111  virtual cvmfs::EnumStatus Pread(const shash::Any &id,
112  uint64_t offset,
113  uint32_t *size,
114  unsigned char *buffer) {
115  struct cvmcache_hash c_hash = Cpphash2Chash(id);
116  int result = callbacks_.cvmcache_pread(&c_hash, offset, size, buffer);
117  return static_cast<cvmfs::EnumStatus>(result);
118  }
119 
120  virtual cvmfs::EnumStatus StartTxn(const shash::Any &id,
121  const uint64_t txn_id,
122  const ObjectInfo &info) {
123  if (!(callbacks_.capabilities & CVMCACHE_CAP_WRITE))
124  return cvmfs::STATUS_NOSUPPORT;
125 
126  struct cvmcache_hash c_hash = Cpphash2Chash(id);
127  cvmcache_object_info c_info;
128  memset(&c_info, 0, sizeof(c_info));
129  c_info.size = info.size;
130  c_info.type = ObjectType2CType(info.object_type);
131  if (info.description.empty()) {
132  c_info.description = NULL;
133  } else {
134  c_info.description = strdup(info.description.c_str());
135  }
136  int result = callbacks_.cvmcache_start_txn(&c_hash, txn_id, &c_info);
137  free(c_info.description);
138  return static_cast<cvmfs::EnumStatus>(result);
139  }
140 
141  virtual cvmfs::EnumStatus WriteTxn(const uint64_t txn_id,
142  unsigned char *buffer,
143  uint32_t size) {
144  if (!(callbacks_.capabilities & CVMCACHE_CAP_WRITE))
145  return cvmfs::STATUS_NOSUPPORT;
146 
147  int result = callbacks_.cvmcache_write_txn(txn_id, buffer, size);
148  return static_cast<cvmfs::EnumStatus>(result);
149  }
150 
151  virtual cvmfs::EnumStatus CommitTxn(const uint64_t txn_id) {
152  if (!(callbacks_.capabilities & CVMCACHE_CAP_WRITE))
153  return cvmfs::STATUS_NOSUPPORT;
154 
155  int result = callbacks_.cvmcache_commit_txn(txn_id);
156  return static_cast<cvmfs::EnumStatus>(result);
157  }
158 
159  virtual cvmfs::EnumStatus AbortTxn(const uint64_t txn_id) {
160  if (!(callbacks_.capabilities & CVMCACHE_CAP_WRITE))
161  return cvmfs::STATUS_NOSUPPORT;
162 
163  int result = callbacks_.cvmcache_abort_txn(txn_id);
164  return static_cast<cvmfs::EnumStatus>(result);
165  }
166 
167  virtual cvmfs::EnumStatus GetInfo(Info *info) {
168  if (!(callbacks_.capabilities & CVMCACHE_CAP_INFO))
169  return cvmfs::STATUS_NOSUPPORT;
170 
171  cvmcache_info c_info;
172  c_info.size_bytes = info->size_bytes;
173  c_info.used_bytes = info->used_bytes;
174  c_info.pinned_bytes = info->pinned_bytes;
175  c_info.no_shrink = info->no_shrink;
176  int result = callbacks_.cvmcache_info(&c_info);
177  if (result == CVMCACHE_STATUS_OK) {
178  info->size_bytes = c_info.size_bytes;
179  info->used_bytes = c_info.used_bytes;
180  info->pinned_bytes = c_info.pinned_bytes;
181  info->no_shrink = c_info.no_shrink;
182  }
183  return static_cast<cvmfs::EnumStatus>(result);
184  }
185 
186  virtual cvmfs::EnumStatus Shrink(uint64_t shrink_to, uint64_t *used) {
187  if (!(callbacks_.capabilities & CVMCACHE_CAP_SHRINK))
188  return cvmfs::STATUS_NOSUPPORT;
189 
190  int result = callbacks_.cvmcache_shrink(shrink_to, used);
191  return static_cast<cvmfs::EnumStatus>(result);
192  }
193 
194  virtual cvmfs::EnumStatus ListingBegin(uint64_t lst_id,
195  cvmfs::EnumObjectType type) {
196  if (!(callbacks_.capabilities & CVMCACHE_CAP_LIST))
197  return cvmfs::STATUS_NOSUPPORT;
198 
199  int result = callbacks_.cvmcache_listing_begin(lst_id,
200  ObjectType2CType(type));
201  return static_cast<cvmfs::EnumStatus>(result);
202  }
203 
204  virtual cvmfs::EnumStatus ListingNext(int64_t lst_id, ObjectInfo *item) {
205  if (!(callbacks_.capabilities & CVMCACHE_CAP_LIST))
206  return cvmfs::STATUS_NOSUPPORT;
207 
208  struct cvmcache_object_info c_item;
209  memset(&c_item, 0, sizeof(c_item));
210  int result = callbacks_.cvmcache_listing_next(lst_id, &c_item);
211  if (result == CVMCACHE_STATUS_OK) {
212  item->id = Chash2Cpphash(&c_item.id);
213  item->size = c_item.size;
214  item->object_type = static_cast<cvmfs::EnumObjectType>(c_item.type);
215  item->pinned = c_item.pinned;
216  if (c_item.description) {
217  item->description = string(c_item.description);
218  free(c_item.description);
219  }
220  }
221  return static_cast<cvmfs::EnumStatus>(result);
222  }
223 
224  virtual cvmfs::EnumStatus ListingEnd(int64_t lst_id) {
225  if (!(callbacks_.capabilities & CVMCACHE_CAP_LIST))
226  return cvmfs::STATUS_NOSUPPORT;
227 
228  int result = callbacks_.cvmcache_listing_end(lst_id);
229  return static_cast<cvmfs::EnumStatus>(result);
230  }
231 
232  virtual cvmfs::EnumStatus LoadBreadcrumb(const std::string &fqrn,
233  manifest::Breadcrumb *breadcrumb) {
234  if (!(callbacks_.capabilities & CVMCACHE_CAP_BREADCRUMB))
235  return cvmfs::STATUS_NOSUPPORT;
236 
237  cvmcache_breadcrumb c_breadcrumb;
238  int result = callbacks_.cvmcache_breadcrumb_load(fqrn.c_str(),
239  &c_breadcrumb);
240  if (result == CVMCACHE_STATUS_OK) {
241  breadcrumb->catalog_hash = Chash2Cpphash(&c_breadcrumb.catalog_hash);
242  breadcrumb->timestamp = c_breadcrumb.timestamp;
243  breadcrumb->revision = c_breadcrumb.revision;
244  }
245  return static_cast<cvmfs::EnumStatus>(result);
246  }
247 
248  virtual cvmfs::EnumStatus StoreBreadcrumb(
249  const std::string &fqrn, const manifest::Breadcrumb &breadcrumb) {
250  if (!(callbacks_.capabilities & CVMCACHE_CAP_BREADCRUMB))
251  return cvmfs::STATUS_NOSUPPORT;
252 
253  cvmcache_breadcrumb c_breadcrumb;
254  c_breadcrumb.catalog_hash = Cpphash2Chash(breadcrumb.catalog_hash);
255  c_breadcrumb.timestamp = breadcrumb.timestamp;
256  c_breadcrumb.revision = breadcrumb.revision;
257  int result = callbacks_.cvmcache_breadcrumb_store(fqrn.c_str(),
258  &c_breadcrumb);
259  return static_cast<cvmfs::EnumStatus>(result);
260  }
261 
262  private:
263  struct cvmcache_callbacks callbacks_;
264 };
265 
267 
268 } // anonymous namespace
269 
270 
272  explicit cvmcache_context(ForwardCachePlugin *p) : plugin(p) { }
274 };
275 
276 
277 int cvmcache_hash_cmp(struct cvmcache_hash *a, struct cvmcache_hash *b) {
278  const shash::Any hash_a = Chash2Cpphash(a);
279  const shash::Any hash_b = Chash2Cpphash(b);
280  if (hash_a < hash_b)
281  return -1;
282  else if (hash_a == hash_b)
283  return 0;
284  else
285  return 1;
286 }
287 
288 char *cvmcache_hash_print(const struct cvmcache_hash *h) {
289  const shash::Any hash = Chash2Cpphash(h);
290  return strdup(hash.ToString().c_str());
291 }
292 
293 
295 
296 
298 
300  return getenv(CacheTransport::kEnvReadyNotifyFd) != NULL;
301 }
302 
304  return new cvmcache_context(new ForwardCachePlugin(callbacks));
305 }
306 
307 int cvmcache_listen(struct cvmcache_context *ctx, char *locator) {
308  return ctx->plugin->Listen(locator);
309 }
310 
312  unsigned nworkers) {
313  ctx->plugin->ProcessRequests(nworkers);
314 }
315 
317  ctx->plugin->AskToDetach();
318 }
319 
321  ctx->plugin->WaitFor();
322  delete ctx;
323 }
324 
326  ctx->plugin->Terminate();
327 }
328 
330  return ctx->plugin->max_object_size();
331 }
332 
334  assert(session != NULL);
335  SessionCtx *session_ctx = SessionCtx::GetInstance();
336  assert(session_ctx);
337  session_ctx->Get(
338  &(session->id), &(session->repository_name), &(session->client_instance));
339 }
340 
341 void cvmcache_spawn_watchdog(const char *crash_dump_file) {
342  if (g_watchdog != NULL)
343  return;
345  assert(g_watchdog != NULL);
346  g_watchdog->Spawn((crash_dump_file != NULL) ? string(crash_dump_file) : "");
347 }
348 
350  delete g_watchdog;
351  g_watchdog = NULL;
352 }
uint64_t pinned_bytes
Definition: channel.h:89
struct cvmcache_hash catalog_hash
void Get(uint64_t *id, char **reponame, char **client_instance)
Definition: channel.cc:71
int(* cvmcache_chrefcnt)(struct cvmcache_hash *id, int32_t change_by)
struct cvmcache_hash Cpphash2Chash(const shash::Any &hash)
struct cvmcache_context * ctx
Session * session() const
Definition: repository.h:319
cvmcache_object_type
uint64_t timestamp
Definition: manifest.h:39
static const uint64_t kSizeUnknown
Definition: channel.h:70
int(* cvmcache_info)(struct cvmcache_info *info)
shash::Any catalog_hash
Definition: manifest.h:38
void cvmcache_terminate(struct cvmcache_context *ctx)
int cvmcache_listen(struct cvmcache_context *ctx, char *locator)
std::string ToString(const bool with_suffix=false) const
Definition: hash.h:241
struct cvmcache_hash id
int(* cvmcache_listing_next)(int64_t lst_id, struct cvmcache_object_info *item)
void cvmcache_cleanup_global()
void cvmcache_terminate_watchdog()
virtual cvmfs::EnumStatus LoadBreadcrumb(const std::string &fqrn, manifest::Breadcrumb *breadcrumb)
cvmfs::EnumObjectType object_type
Definition: channel.h:80
assert((mem||(size==0))&&"Out Of Memory")
uint64_t pinned_bytes
int cvmcache_is_supervised()
Algorithms algorithm
Definition: hash.h:122
int(* cvmcache_pread)(struct cvmcache_hash *id, uint64_t offset, uint32_t *size, unsigned char *buffer)
int(* cvmcache_breadcrumb_load)(const char *fqrn, cvmcache_breadcrumb *breadcrumb)
unsigned char digest[digest_size_]
Definition: hash.h:121
void cvmcache_wait_for(struct cvmcache_context *ctx)
uint64_t used_bytes
virtual cvmfs::EnumStatus AbortTxn(const uint64_t txn_id)
Algorithms
Definition: hash.h:41
uint64_t revision
Definition: manifest.h:40
static Watchdog * Create(FnOnCrash on_crash)
Definition: monitor.cc:67
void cvmcache_ask_detach(struct cvmcache_context *ctx)
int(* cvmcache_write_txn)(uint64_t txn_id, unsigned char *buffer, uint32_t size)
virtual cvmfs::EnumStatus StartTxn(const shash::Any &id, const uint64_t txn_id, const ObjectInfo &info)
virtual cvmfs::EnumStatus CommitTxn(const uint64_t txn_id)
int cvmcache_hash_cmp(struct cvmcache_hash *a, struct cvmcache_hash *b)
unsigned char digest[20]
virtual cvmfs::EnumStatus StoreBreadcrumb(const std::string &fqrn, const manifest::Breadcrumb &breadcrumb)
void cvmcache_get_session(cvmcache_session *session)
cvmcache_context(ForwardCachePlugin *p)
int64_t no_shrink
Definition: channel.h:90
UniquePtr< ForwardCachePlugin > plugin
std::string description
Definition: channel.h:82
virtual cvmfs::EnumStatus WriteTxn(const uint64_t txn_id, unsigned char *buffer, uint32_t size)
void cvmcache_spawn_watchdog(const char *crash_dump_file)
char * cvmcache_hash_print(const struct cvmcache_hash *h)
uint64_t size_bytes
enum cvmcache_object_type type
virtual cvmfs::EnumStatus Shrink(uint64_t shrink_to, uint64_t *used)
struct cvmcache_context * cvmcache_init(struct cvmcache_callbacks *callbacks)
virtual cvmfs::EnumStatus ListingBegin(uint64_t lst_id, cvmfs::EnumObjectType type)
void cvmcache_init_global()
int(* cvmcache_shrink)(uint64_t shrink_to, uint64_t *used)
uint64_t used_bytes
Definition: channel.h:88
int(* cvmcache_listing_begin)(uint64_t lst_id, enum cvmcache_object_type type)
virtual cvmfs::EnumStatus ListingEnd(int64_t lst_id)
void cvmcache_process_requests(struct cvmcache_context *ctx, unsigned nworkers)
int(* cvmcache_breadcrumb_store)(const char *fqrn, const cvmcache_breadcrumb *breadcrumb)
static enum cvmcache_object_type ObjectType2CType(cvmfs::EnumObjectType type)
int(* cvmcache_commit_txn)(uint64_t txn_id)
int(* cvmcache_start_txn)(struct cvmcache_hash *id, uint64_t txn_id, struct cvmcache_object_info *info)
int(* cvmcache_listing_end)(int64_t lst_id)
int(* cvmcache_abort_txn)(uint64_t txn_id)
void Spawn(const std::string &crash_dump_path)
Definition: monitor.cc:514
ForwardCachePlugin(struct cvmcache_callbacks *callbacks)
virtual cvmfs::EnumStatus GetObjectInfo(const shash::Any &id, ObjectInfo *info)
virtual cvmfs::EnumStatus ChangeRefcount(const shash::Any &id, int32_t change_by)
int(* cvmcache_obj_info)(struct cvmcache_hash *id, struct cvmcache_object_info *info)
shash::Any Chash2Cpphash(const struct cvmcache_hash *h)
static void size_t size
Definition: smalloc.h:54
virtual cvmfs::EnumStatus Pread(const shash::Any &id, uint64_t offset, uint32_t *size, unsigned char *buffer)
virtual cvmfs::EnumStatus ListingNext(int64_t lst_id, ObjectInfo *item)
static const char * kEnvReadyNotifyFd
uint64_t size_bytes
Definition: channel.h:87
static SessionCtx * GetInstance()
Definition: channel.cc:59
uint32_t cvmcache_max_object_size(struct cvmcache_context *ctx)