GCC Code Coverage Report


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