GCC Code Coverage Report


Directory: cvmfs/
File: cvmfs/cache_tiered.cc
Date: 2026-10-11 02:40:02
Exec Total Coverage
Lines: 82 129 63.6%
Branches: 52 132 39.4%

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