GCC Code Coverage Report
Directory: cvmfs/ Exec Total Coverage
File: cvmfs/cache.h Lines: 24 27 88.9 %
Date: 2019-02-03 02:48:13 Branches: 0 0 - %

Line Branch Exec Source
1
/**
2
 * This file is part of the CernVM File System.
3
 */
4
5
#ifndef CVMFS_CACHE_H_
6
#define CVMFS_CACHE_H_
7
8
#ifndef __STDC_FORMAT_MACROS
9
#define __STDC_FORMAT_MACROS
10
#endif
11
12
#include <stdint.h>
13
14
#include <string>
15
16
#include "hash.h"
17
#include "util/pointer.h"
18
19
20
class QuotaManager;
21
22
enum CacheManagerIds {
23
  kUnknownCacheManager = 0,
24
  kPosixCacheManager,
25
  kRamCacheManager,
26
  kTieredCacheManager,
27
  kExternalCacheManager,
28
};
29
30
enum CacheModes {
31
  kCacheReadWrite = 0,
32
  kCacheReadOnly,
33
};
34
35
36
/**
37
 * The Cache Manager provides (virtual) file descriptors to content-addressable
38
 * objects in the cache.  The implementation can use a POSIX file system or
39
 * other means such as a key-value store.  A file descriptor must remain
40
 * readable until closed, no matter if it is removed from the backend storage
41
 * or not (POSIX semantics).
42
 *
43
 * Writing into the cache is streamed and transactional: a file descriptor must
44
 * be acquired from StartTxn and the object is only visible in the cache after
45
 * CommitTxn.  The state of the transaction is carried in an opque transaction
46
 * object, which needs to be provided by the caller.  The size of the object is
47
 * returned by SizeOfTxn.  This way, users of derived classes can take care of
48
 * the storage allocation (e.g. on the stack), while the derived class
49
 * determines the contents of the transaction object.  For race-free read access
50
 * to objects that are just being written to the cache, the OpenFromTxn routine
51
 * is used just before the transaction is committed.
52
 *
53
 * Writing to the cache can be coupled to a quota manager.  The quota manager
54
 * maintains some extra information for data chunks: whether they are
55
 * volatile, whether they are pinned, and a description (usually the path that
56
 * corresponds to a data chunk).  By default the NoopQuotaManager is used, which
57
 * ignores all this extra information.  The CtrlTxn() function is used to
58
 * specify this extra information sometime between StartTxn() and CommitTxn().
59
 *
60
 * The integer return values can be negative and, in this case, represent a
61
 * -errno failure code.  Otherwise the return value 0 indicates a success, or
62
 * >= 0 for a file descriptor.
63
 */
64
class CacheManager : SingleCopy {
65
 public:
66
  /**
67
   * Sizes of objects should be known for StartTxn().  For file catalogs we
68
   * cannot ensure that, however, because the size field for nested catalogs
69
   * was only recently added.
70
   */
71
  static const uint64_t kSizeUnknown;
72
73
  /**
74
   * Relevant for the quota management
75
   */
76
  enum ObjectType {
77
    kTypeRegular = 0,
78
    kTypeCatalog,  // implies pinned
79
    kTypePinned,
80
    kTypeVolatile,
81
  };
82
83
  /**
84
   * Meta-data of an object that the cache may or may not maintain.  Good cache
85
   * implementations should at least distinguish between volatile and regular
86
   * objects.
87
   */
88
5972
  struct ObjectInfo {
89
420
    ObjectInfo() : type(kTypeRegular), description() { }
90
4804
    ObjectInfo(ObjectType t, const std::string &d) : type(t), description(d) { }
91
92
    ObjectType type;
93
    /**
94
     * Typically the path that triggered storing the object in the cache
95
     */
96
    std::string description;
97
  };
98
99
  /**
100
   * A content hash together with a (partial) ObjectInfo meta-data.
101
   */
102
731
  struct BlessedObject {
103
420
    explicit BlessedObject(const shash::Any &id) : id(id), info() { }
104
142
    BlessedObject(const shash::Any &id, const ObjectInfo info)
105
      : id(id)
106
142
      , info(info) { }
107
1
    BlessedObject(const shash::Any &id, ObjectType type)
108
      : id(id)
109
1
      , info(type, "") { }
110
    BlessedObject(const shash::Any &id, const std::string &description)
111
      : id(id)
112
      , info(kTypeRegular, description) { }
113
168
    BlessedObject(
114
      const shash::Any &id,
115
      ObjectType type,
116
      const std::string &description)
117
      : id(id)
118
168
      , info(type, description) { }
119
120
    shash::Any id;
121
    ObjectInfo info;
122
  };
123
  // Convenience constructors, users can call Open(CacheManager::Bless(my_hash))
124
420
  static inline BlessedObject Bless(const shash::Any &id) {
125
420
    return BlessedObject(id);
126
  }
127
142
  static inline BlessedObject Bless(
128
    const shash::Any &id,
129
    const ObjectInfo &info)
130
  {
131
142
    return BlessedObject(id, info);
132
  }
133
1
  static inline BlessedObject Bless(const shash::Any &id, ObjectType type) {
134
1
    return BlessedObject(id, type);
135
  }
136
  static inline BlessedObject Bless(
137
    const shash::Any &id,
138
    const std::string &description)
139
  {
140
    return BlessedObject(id, description);
141
  }
142
168
  static inline BlessedObject Bless(
143
    const shash::Any &id,
144
    ObjectType type,
145
    const std::string &description)
146
  {
147
168
    return BlessedObject(id, type, description);
148
  }
149
150
  virtual CacheManagerIds id() = 0;
151
  /**
152
   * Return a human readable description of the cache instance.  Used in
153
   * cvmfs_talk.
154
   */
155
  virtual std::string Describe() = 0;
156
157
  virtual bool AcquireQuotaManager(QuotaManager *quota_mgr) = 0;
158
159
  virtual ~CacheManager();
160
  /**
161
   * Opening an object might get it from a third-party source, e.g. when the
162
   * tiered cache manager issues a copy-up operation.  In this case it is
163
   * beneficial to register the object with the accurate meta-data, in the same
164
   * way it is done during transactions.
165
   */
166
  virtual int Open(const BlessedObject &object) = 0;
167
  virtual int64_t GetSize(int fd) = 0;
168
  virtual int Close(int fd) = 0;
169
  virtual int64_t Pread(int fd, void *buf, uint64_t size, uint64_t offset) = 0;
170
  virtual int Dup(int fd) = 0;
171
  virtual int Readahead(int fd) = 0;
172
173
  virtual uint32_t SizeOfTxn() = 0;
174
  virtual int StartTxn(const shash::Any &id, uint64_t size, void *txn) = 0;
175
  virtual void CtrlTxn(const ObjectInfo &object_info,
176
                       const int flags,  // reserved for future use
177
                       void *txn) = 0;
178
  virtual int64_t Write(const void *buf, uint64_t sz, void *txn) = 0;
179
  virtual int Reset(void *txn) = 0;
180
  virtual int AbortTxn(void *txn) = 0;
181
  virtual int OpenFromTxn(void *txn) = 0;
182
  virtual int CommitTxn(void *txn) = 0;
183
184
  virtual void Spawn() = 0;
185
186
  int OpenPinned(const shash::Any &id,
187
                 const std::string &description,
188
                 bool is_catalog);
189
  int ChecksumFd(int fd, shash::Any *id);
190
  bool Open2Mem(const shash::Any &id, const std::string &description,
191
                unsigned char **buffer, uint64_t *size);
192
  bool CommitFromMem(const shash::Any &id,
193
                     const unsigned char *buffer,
194
                     const uint64_t size,
195
                     const std::string &description);
196
197
73
  QuotaManager *quota_mgr() { return quota_mgr_; }
198
199
  // Rescue the open file table during reload of the fuse module.  For the
200
  // POSIX cache, nothing needs to be done because the table is keep in the
201
  // kernel for the process.  Other cache managers need to do it manually.
202
  void *SaveState(const int fd_progress);
203
  void RestoreState(const int fd_progress, void *state);
204
  void FreeState(const int fd_progress, void *state);
205
206
  /**
207
   * While not strictly necessary, cache managers often have a directory
208
   * associated with them. This directory is currently used to find the
209
   * cached manifest copy, the cvmfschecksum.$reponame file. This is important
210
   * to make pre-loaded alien caches work, even in a tiered setup.
211
   */
212
51
  virtual std::string GetBackingDirectory() { return ""; }
213
214
 protected:
215
  CacheManager();
216
217
  // Unless overwritten, Saving/Restoring states will crash the Fuse module
218
  virtual void *DoSaveState() { return NULL; }
219
  virtual bool DoRestoreState(void *data) { return false; }
220
  virtual bool DoFreeState(void *data) { return false; }
221
222
  /**
223
   * Never NULL but defaults to NoopQuotaManager.
224
   */
225
  QuotaManager *quota_mgr_;
226
227
 private:
228
  static const unsigned kStateVersion = 0;
229
230
  /**
231
   * Wraps around the concrete cache manager's state block in memory.  The
232
   * state pointer is used in DoSaveState, DoRestoreState, DoFreeState.
233
   */
234
  struct State : SingleCopy {
235
4
    State()
236
      : version(kStateVersion)
237
      , manager_type(kUnknownCacheManager)
238
4
      , concrete_state(NULL)
239
4
    { }
240
241
    unsigned version;
242
    CacheManagerIds manager_type;
243
    void *concrete_state;
244
  };
245
};  // class CacheManager
246
247
#endif  // CVMFS_CACHE_H_