GCC Code Coverage Report


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