CernVM-FS  2.12.0
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
cache_tiered.cc
Go to the documentation of this file.
1 
4 #include "cvmfs_config.h"
5 #include "cache_tiered.h"
6 
7 #include <errno.h>
8 
9 #include <string>
10 #include <vector>
11 
12 #include "quota.h"
13 #include "util/platform.h"
14 #include "util/posix.h"
15 
16 
18  return "Tiered Cache\n"
19  " - upper layer: " + upper_->Describe() +
20  " - lower layer: " + lower_->Describe();
21 }
22 
23 
25  SavedState *state = reinterpret_cast<SavedState *>(data);
26  upper_->FreeState(-1, state->state_upper);
27  lower_->FreeState(-1, state->state_lower);
28  delete state;
29  return true;
30 }
31 
32 
34  SavedState *state = reinterpret_cast<SavedState *>(data);
35  int new_root_fd = upper_->RestoreState(-1, state->state_upper);
36  // The lower cache layer does not keep the root catalog open
37  int retval = lower_->RestoreState(-1, state->state_lower);
38  assert(retval == -1);
39  return new_root_fd;
40 }
41 
42 
44  SavedState *state = new SavedState();
45  state->state_upper = upper_->SaveState(-1);
46  state->state_lower = lower_->SaveState(-1);
47  return state;
48 }
49 
50 
52  int fd = upper_->Open(object);
53  if ((fd >= 0) || (fd != -ENOENT)) {return fd;}
54 
55  int fd2 = lower_->Open(object);
56  if (fd2 < 0) {return fd;} // NOTE: use error code from upper.
57 
58  // Lower cache hit; upper cache miss. Copy object into the upper cache.
59  int64_t size = lower_->GetSize(fd2);
60  if (size < 0) {
61  lower_->Close(fd2);
62  return fd;
63  }
64 
65  void *txn = alloca(upper_->SizeOfTxn());
66  if (upper_->StartTxn(object.id, size, txn) < 0) {
67  lower_->Close(fd2);
68  return fd;
69  }
70  upper_->CtrlTxn(object.label, 0, txn);
71 
72  std::vector<char> m_buffer;
73  m_buffer.resize(kCopyBufferSize);
74  uint64_t remaining = size;
75  uint64_t offset = 0;
76  while (remaining > 0) {
77  unsigned nbytes = remaining > kCopyBufferSize ? kCopyBufferSize : remaining;
78  int64_t result = lower_->Pread(fd2, &m_buffer[0], nbytes, offset);
79  // The file we are reading is supposed to be exactly `size` bytes.
80  if ((result < 0) || (result != nbytes)) {
81  lower_->Close(fd2);
82  upper_->AbortTxn(txn);
83  return fd;
84  }
85  result = upper_->Write(&m_buffer[0], nbytes, txn);
86  if (result < 0) {
87  lower_->Close(fd2);
88  upper_->AbortTxn(txn);
89  return fd;
90  }
91  offset += nbytes;
92  remaining -= nbytes;
93  }
94  lower_->Close(fd2);
95  int fd_return = upper_->OpenFromTxn(txn);
96  if (fd_return < 0) {
97  upper_->AbortTxn(txn);
98  return fd;
99  }
100  if (upper_->CommitTxn(txn) < 0) {
101  upper_->Close(fd_return);
102  return fd;
103  }
104  return fd_return;
105 }
106 
107 
108 int TieredCacheManager::StartTxn(const shash::Any &id, uint64_t size, void *txn)
109 {
110  int upper_result = upper_->StartTxn(id, size, txn);
111  if (lower_readonly_ || (upper_result < 0)) {
112  return upper_result;
113  }
114 
115  void *txn2 = static_cast<char *>(txn) + upper_->SizeOfTxn();
116  int lower_result = lower_->StartTxn(id, size, txn2);
117  if (lower_result < 0) {
118  upper_->AbortTxn(txn);
119  }
120  return lower_result;
121 }
122 
123 
125  CacheManager *upper_cache,
126  CacheManager *lower_cache)
127 {
128  TieredCacheManager *cache_mgr =
129  new TieredCacheManager(upper_cache, lower_cache);
130  delete cache_mgr->quota_mgr_;
131  cache_mgr->quota_mgr_ = upper_cache->quota_mgr();
132 
133  return cache_mgr;
134 }
135 
136 
137 void TieredCacheManager::CtrlTxn(const Label &label, const int flags, void *txn)
138 {
139  upper_->CtrlTxn(label, flags, txn);
140  if (!lower_readonly_) {
141  void *txn2 = static_cast<char*>(txn) + upper_->SizeOfTxn();
142  lower_->CtrlTxn(label, flags, txn2);
143  }
144 }
145 
146 
147 int64_t TieredCacheManager::Write(const void *buf, uint64_t size, void *txn) {
148  int upper_result = upper_->Write(buf, size, txn);
149  if (lower_readonly_ || (upper_result < 0)) { return upper_result; }
150 
151  void *txn2 = static_cast<char*>(txn) + upper_->SizeOfTxn();
152  return lower_->Write(buf, size, txn2);
153 }
154 
155 
157  int upper_result = upper_->Reset(txn);
158 
159  int lower_result = upper_result;
160  if (!lower_readonly_) {
161  void *txn2 = static_cast<char*>(txn) + upper_->SizeOfTxn();
162  lower_result = lower_->Reset(txn2);
163  }
164 
165  return (upper_result < 0) ? upper_result : lower_result;
166 }
167 
168 
170  int upper_result = upper_->AbortTxn(txn);
171 
172  int lower_result = upper_result;
173  if (!lower_readonly_) {
174  void *txn2 = static_cast<char*>(txn) + upper_->SizeOfTxn();
175  lower_result = lower_->AbortTxn(txn2);
176  }
177 
178  return (upper_result < 0) ? upper_result : lower_result;
179 }
180 
181 
183  int upper_result = upper_->CommitTxn(txn);
184 
185  int lower_result = upper_result;
186  if (!lower_readonly_) {
187  void *txn2 = static_cast<char*>(txn) + upper_->SizeOfTxn();
188  lower_result = lower_->CommitTxn(txn2);
189  }
190 
191  return (upper_result < 0) ? upper_result : lower_result;
192 }
193 
194 
196 {
197  manifest::Breadcrumb breadcrumb = upper_->LoadBreadcrumb(fqrn);
198  if (!breadcrumb.IsValid())
199  breadcrumb = lower_->LoadBreadcrumb(fqrn);
200  return breadcrumb;
201 }
202 
203 
205  bool upper_success = upper_->StoreBreadcrumb(manifest);
206  bool lower_success = true;
207  if (!lower_readonly_)
208  lower_success = lower_->StoreBreadcrumb(manifest);
209  return upper_success && lower_success;
210 }
211 
212 
214  upper_->Spawn();
215  lower_->Spawn();
216 }
217 
218 
220  quota_mgr_ = NULL; // gets deleted by upper
221  delete upper_;
222  delete lower_;
223 }
const manifest::Manifest * manifest() const
Definition: repository.h:125
virtual int64_t GetSize(int fd)=0
virtual int AbortTxn(void *txn)
int RestoreState(const int fd_progress, void *state)
Definition: cache.cc:188
virtual void Spawn()=0
virtual manifest::Breadcrumb LoadBreadcrumb(const std::string &)
Definition: cache.h:217
void * SaveState(const int fd_progress)
Definition: cache.cc:215
assert((mem||(size==0))&&"Out Of Memory")
virtual int AbortTxn(void *txn)=0
virtual bool StoreBreadcrumb(const manifest::Manifest &)
Definition: cache.h:220
virtual bool DoFreeState(void *data)
Definition: cache_tiered.cc:24
virtual void * DoSaveState()
Definition: cache_tiered.cc:43
virtual std::string Describe()
Definition: cache_tiered.cc:17
TieredCacheManager(CacheManager *upper_cache, CacheManager *lower_cache)
Definition: cache_tiered.h:82
virtual int Open(const LabeledObject &object)=0
virtual int Reset(void *txn)
static CacheManager * Create(CacheManager *upper_cache, CacheManager *lower_cache)
virtual int CommitTxn(void *txn)=0
virtual int Open(const LabeledObject &object)
Definition: cache_tiered.cc:51
virtual int OpenFromTxn(void *txn)=0
virtual int CommitTxn(void *txn)
virtual void CtrlTxn(const Label &label, const int flags, void *txn)
virtual int DoRestoreState(void *data)
Definition: cache_tiered.cc:33
virtual int Close(int fd)=0
virtual int64_t Write(const void *buf, uint64_t size, void *txn)
virtual int Reset(void *txn)=0
void FreeState(const int fd_progress, void *state)
Definition: cache.cc:99
CacheManager * lower_
Definition: cache_tiered.h:87
virtual void CtrlTxn(const Label &label, const int flags, void *txn)=0
CacheManager * upper_
Definition: cache_tiered.h:86
QuotaManager * quota_mgr()
Definition: cache.h:193
static const unsigned kCopyBufferSize
Definition: cache_tiered.h:73
virtual int StartTxn(const shash::Any &id, uint64_t size, void *txn)
QuotaManager * quota_mgr_
Definition: cache.h:235
virtual uint32_t SizeOfTxn()=0
bool IsValid() const
Definition: manifest.h:35
virtual manifest::Breadcrumb LoadBreadcrumb(const std::string &fqrn)
virtual ~TieredCacheManager()
virtual int StartTxn(const shash::Any &id, uint64_t size, void *txn)=0
virtual void Spawn()
static void size_t size
Definition: smalloc.h:54
virtual int64_t Pread(int fd, void *buf, uint64_t size, uint64_t offset)=0
virtual bool StoreBreadcrumb(const manifest::Manifest &manifest)
virtual std::string Describe()=0
virtual int64_t Write(const void *buf, uint64_t sz, void *txn)=0