GCC Code Coverage Report


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