GCC Code Coverage Report


Directory: cvmfs/
File: cvmfs/file_chunk.cc
Date: 2026-10-04 02:40:33
Exec Total Coverage
Lines: 108 136 79.4%
Branches: 63 110 57.3%

Line Branch Exec Source
1 /**
2 * This file is part of the CernVM File System.
3 */
4
5
6 #include "file_chunk.h"
7
8 #include <cassert>
9
10 #include "util/murmur.hxx"
11
12 using namespace std; // NOLINT
13
14 ✗ static inline uint32_t hasher_uint64t(const uint64_t &value) {
15 ✗ return MurmurHash2(&value, sizeof(value), 0x07387a4f);
16 }
17
18
19 //------------------------------------------------------------------------------
20
21
22 470 unsigned FileChunkReflist::FindChunkIdx(const uint64_t off) {
23
2/4
✓ Branch 0 taken 470 times.
✗ Branch 1 not taken.
✓ Branch 3 taken 470 times.
✗ Branch 4 not taken.
470 assert(list && (list->size() > 0));
24 470 unsigned idx_low = 0;
25 470 unsigned idx_high = list->size() - 1;
26 470 unsigned chunk_idx = idx_high / 2;
27
2/2
✓ Branch 0 taken 799 times.
✓ Branch 1 taken 376 times.
1175 while (idx_low < idx_high) {
28
2/2
✓ Branch 2 taken 141 times.
✓ Branch 3 taken 658 times.
799 if (static_cast<uint64_t>(list->AtPtr(chunk_idx)->offset()) > off) {
29
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 141 times.
141 assert(idx_high > 0);
30 141 idx_high = chunk_idx - 1;
31 } else {
32 658 if ((chunk_idx == list->size() - 1)
33
5/6
✓ Branch 0 taken 658 times.
✗ Branch 1 not taken.
✓ Branch 4 taken 94 times.
✓ Branch 5 taken 564 times.
✓ Branch 6 taken 94 times.
✓ Branch 7 taken 564 times.
658 || (static_cast<uint64_t>(list->AtPtr(chunk_idx + 1)->offset())
34 > off)) {
35 94 break;
36 }
37 564 idx_low = chunk_idx + 1;
38 }
39 705 chunk_idx = idx_low + (idx_high - idx_low) / 2;
40 }
41 470 return chunk_idx;
42 }
43
44
45 /**
46 * Returns a consistent hash over hashes of the chunks. Used by libcvmfs.
47 */
48 48 shash::Any FileChunkReflist::HashChunkList() {
49 48 const shash::Algorithms algo = list->AtPtr(0)->content_hash().algorithm;
50
1/2
✓ Branch 1 taken 48 times.
✗ Branch 2 not taken.
48 shash::ContextPtr ctx(algo);
51 48 ctx.buffer = alloca(ctx.size);
52
1/2
✓ Branch 1 taken 48 times.
✗ Branch 2 not taken.
48 shash::Init(ctx);
53
2/2
✓ Branch 1 taken 96 times.
✓ Branch 2 taken 48 times.
144 for (unsigned i = 0; i < list->size(); ++i) {
54 96 shash::Update(
55
1/2
✓ Branch 3 taken 96 times.
✗ Branch 4 not taken.
96 list->AtPtr(i)->content_hash().digest, shash::kDigestSizes[algo], ctx);
56 }
57
1/2
✓ Branch 1 taken 48 times.
✗ Branch 2 not taken.
48 shash::Any result(algo);
58
1/2
✓ Branch 1 taken 48 times.
✗ Branch 2 not taken.
48 shash::Final(ctx, &result);
59 96 return result;
60 }
61
62
63 //------------------------------------------------------------------------------
64
65
66 91 void ChunkTables::InitLocks() {
67 91 lock = reinterpret_cast<pthread_mutex_t *>(smalloc(sizeof(pthread_mutex_t)));
68 91 const int retval = pthread_mutex_init(lock, NULL);
69
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 91 times.
91 assert(retval == 0);
70
71
2/2
✓ Branch 0 taken 11648 times.
✓ Branch 1 taken 91 times.
11739 for (unsigned i = 0; i < kNumHandleLocks; ++i) {
72 pthread_mutex_t *m = reinterpret_cast<pthread_mutex_t *>(
73 11648 smalloc(sizeof(pthread_mutex_t)));
74 11648 const int retval = pthread_mutex_init(m, NULL);
75
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 11648 times.
11648 assert(retval == 0);
76
1/2
✓ Branch 1 taken 11648 times.
✗ Branch 2 not taken.
11648 handle_locks.PushBack(m);
77 }
78 91 }
79
80
81 91 void ChunkTables::InitHashmaps() {
82 91 handle2uniqino.Init(16, 0, hasher_uint64t);
83 91 handle2fd.Init(16, 0, hasher_uint64t);
84 91 inode2chunks.Init(16, 0, hasher_uint64t);
85 91 inode2references.Init(16, 0, hasher_uint64t);
86 91 }
87
88
89
4/8
✓ Branch 2 taken 91 times.
✗ Branch 3 not taken.
✓ Branch 5 taken 91 times.
✗ Branch 6 not taken.
✓ Branch 8 taken 91 times.
✗ Branch 9 not taken.
✓ Branch 11 taken 91 times.
✗ Branch 12 not taken.
91 ChunkTables::ChunkTables() {
90 91 next_handle = 2;
91 91 version = kVersion;
92
1/2
✓ Branch 1 taken 91 times.
✗ Branch 2 not taken.
91 InitLocks();
93
1/2
✓ Branch 1 taken 91 times.
✗ Branch 2 not taken.
91 InitHashmaps();
94 91 }
95
96
97 91 ChunkTables::~ChunkTables() {
98 91 pthread_mutex_destroy(lock);
99 91 free(lock);
100
2/2
✓ Branch 0 taken 11648 times.
✓ Branch 1 taken 91 times.
11739 for (unsigned i = 0; i < kNumHandleLocks; ++i) {
101 11648 pthread_mutex_destroy(handle_locks.At(i));
102 11648 free(handle_locks.At(i));
103 }
104 91 }
105
106
107 ✗ ChunkTables::ChunkTables(const ChunkTables &other) {
108 ✗ version = kVersion;
109 ✗ InitLocks();
110 ✗ InitHashmaps();
111 ✗ CopyFrom(other);
112 }
113
114
115 ✗ ChunkTables &ChunkTables::operator=(const ChunkTables &other) {
116 ✗ if (&other == this)
117 ✗ return *this;
118
119 ✗ handle2uniqino.Clear();
120 ✗ handle2fd.Clear();
121 ✗ inode2chunks.Clear();
122 ✗ inode2references.Clear();
123 ✗ CopyFrom(other);
124 ✗ return *this;
125 }
126
127
128 ✗ void ChunkTables::CopyFrom(const ChunkTables &other) {
129 ✗ assert(version == other.version);
130 ✗ next_handle = other.next_handle;
131 ✗ inode2references = other.inode2references;
132 ✗ inode2chunks = other.inode2chunks;
133 ✗ handle2fd = other.handle2fd;
134 ✗ handle2uniqino = other.handle2uniqino;
135 }
136
137
138 ✗ pthread_mutex_t *ChunkTables::Handle2Lock(const uint64_t handle) const {
139 ✗ const uint32_t hash = hasher_uint64t(handle);
140 ✗ const double bucket = static_cast<double>(hash)
141 ✗ * static_cast<double>(kNumHandleLocks)
142 / static_cast<double>((uint32_t)(-1));
143 ✗ return handle_locks.At((uint32_t)bucket % kNumHandleLocks);
144 }
145
146
147 //------------------------------------------------------------------------------
148
149
150 435 SimpleChunkTables::SimpleChunkTables() {
151 435 lock_ = reinterpret_cast<pthread_mutex_t *>(smalloc(sizeof(pthread_mutex_t)));
152 435 const int retval = pthread_mutex_init(lock_, NULL);
153
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 435 times.
435 assert(retval == 0);
154 435 }
155
156
157 433 SimpleChunkTables::~SimpleChunkTables() {
158
2/2
✓ Branch 1 taken 46 times.
✓ Branch 2 taken 433 times.
479 for (unsigned i = 0; i < fd_table_.size(); ++i) {
159
1/2
✓ Branch 1 taken 46 times.
✗ Branch 2 not taken.
46 delete fd_table_[i].chunk_reflist.list;
160 }
161 433 pthread_mutex_destroy(lock_);
162 433 free(lock_);
163 433 }
164
165
166 368 int SimpleChunkTables::Add(FileChunkReflist chunks) {
167
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 368 times.
368 assert(chunks.list != NULL);
168
1/2
✓ Branch 1 taken 368 times.
✗ Branch 2 not taken.
368 OpenChunks new_entry;
169
1/2
✓ Branch 1 taken 368 times.
✗ Branch 2 not taken.
368 new_entry.chunk_reflist = chunks;
170
1/2
✓ Branch 1 taken 368 times.
✗ Branch 2 not taken.
368 new_entry.chunk_fd = new ChunkFd();
171 368 unsigned i = 0;
172 368 Lock();
173
2/2
✓ Branch 1 taken 690 times.
✓ Branch 2 taken 322 times.
1012 for (; i < fd_table_.size(); ++i) {
174
2/2
✓ Branch 1 taken 46 times.
✓ Branch 2 taken 644 times.
690 if (fd_table_[i].chunk_reflist.list == NULL) {
175
1/2
✓ Branch 2 taken 46 times.
✗ Branch 3 not taken.
46 fd_table_[i] = new_entry;
176 46 Unlock();
177 46 return i;
178 }
179 }
180
1/2
✓ Branch 1 taken 322 times.
✗ Branch 2 not taken.
322 fd_table_.push_back(new_entry);
181 322 Unlock();
182 322 return i;
183 368 }
184
185
186 138 SimpleChunkTables::OpenChunks SimpleChunkTables::Get(int fd) {
187 138 OpenChunks result;
188
2/2
✓ Branch 0 taken 46 times.
✓ Branch 1 taken 92 times.
138 if (fd < 0)
189 46 return result;
190
191 92 const unsigned idx = static_cast<unsigned>(fd);
192 92 Lock();
193
2/2
✓ Branch 1 taken 46 times.
✓ Branch 2 taken 46 times.
92 if (idx < fd_table_.size())
194
1/2
✓ Branch 2 taken 46 times.
✗ Branch 3 not taken.
46 result = fd_table_[idx];
195 92 Unlock();
196 92 return result;
197 }
198
199
200 414 void SimpleChunkTables::Release(int fd) {
201
2/2
✓ Branch 0 taken 46 times.
✓ Branch 1 taken 368 times.
414 if (fd < 0)
202 46 return;
203
204 368 Lock();
205 368 const unsigned idx = static_cast<unsigned>(fd);
206
2/2
✓ Branch 1 taken 46 times.
✓ Branch 2 taken 322 times.
368 if (idx >= fd_table_.size()) {
207 46 Unlock();
208 46 return;
209 }
210
211
1/2
✓ Branch 1 taken 322 times.
✗ Branch 2 not taken.
322 delete fd_table_[idx].chunk_reflist.list;
212 322 fd_table_[idx].chunk_reflist.list = NULL;
213 322 fd_table_[idx].chunk_reflist.path.Assign("", 0);
214
1/2
✓ Branch 1 taken 322 times.
✗ Branch 2 not taken.
322 delete fd_table_[idx].chunk_fd;
215 322 fd_table_[idx].chunk_fd = NULL;
216
6/6
✓ Branch 1 taken 552 times.
✓ Branch 2 taken 46 times.
✓ Branch 4 taken 276 times.
✓ Branch 5 taken 276 times.
✓ Branch 6 taken 276 times.
✓ Branch 7 taken 322 times.
598 while (!fd_table_.empty() && (fd_table_.back().chunk_reflist.list == NULL)) {
217 276 fd_table_.pop_back();
218 }
219 322 Unlock();
220 }
221