GCC Code Coverage Report
Directory: cvmfs/ Exec Total Coverage
File: cvmfs/cache_plugin/libcvmfs_cache.cc Lines: 0 173 0.0 %
Date: 2019-02-03 02:48:13 Branches: 0 98 0.0 %

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