GCC Code Coverage Report


Directory: cvmfs/
File: cvmfs/file_chunk.cc
Date: 2024-04-28 02:33:07
Exec Total Coverage
Lines: 110 138 79.7%
Branches: 63 110 57.3%

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