GCC Code Coverage Report


Directory: cvmfs/
File: cvmfs/cache_transport.cc
Date: 2024-04-28 02:33:07
Exec Total Coverage
Lines: 331 372 89.0%
Branches: 166 228 72.8%

Line Branch Exec Source
1 /**
2 * This file is part of the CernVM File System.
3 */
4 #include "cvmfs_config.h"
5 #include "cache_transport.h"
6
7 #include <alloca.h>
8 #include <errno.h>
9 #include <sys/socket.h>
10
11 #include <cassert>
12 #include <cstdlib>
13 #include <cstring>
14
15 #include "crypto/hash.h"
16 #include "util/exception.h"
17 #include "util/logging.h"
18 #include "util/posix.h"
19 #include "util/smalloc.h"
20
21 // TODO(jblomer): Check for possible starvation of plugin by dying clients
22 // (blocking read). Probably only relevant for TCP sockets.
23
24 using namespace std; // NOLINT
25
26 const char *CacheTransport::kEnvReadyNotifyFd =
27 "__CVMFS_CACHE_EXTERNAL_PIPE_READY__";
28
29 /**
30 * Called on the sender side to wrap a message into a MsgRpc message for wire
31 * transfer.
32 */
33 13634 cvmfs::MsgRpc *CacheTransport::Frame::GetMsgRpc() {
34
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 13634 times.
13634 assert(msg_typed_ != NULL);
35
1/2
✓ Branch 0 taken 13634 times.
✗ Branch 1 not taken.
13634 if (!is_wrapped_)
36 13634 WrapMsg();
37 13633 return &msg_rpc_;
38 }
39
40
41 /**
42 * Called on the receiving end of an RPC to extract the actual message from the
43 * MsgRpc.
44 */
45 15632 google::protobuf::MessageLite *CacheTransport::Frame::GetMsgTyped() {
46
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 15635 times.
15632 assert(msg_rpc_.IsInitialized());
47
2/2
✓ Branch 0 taken 8557 times.
✓ Branch 1 taken 7078 times.
15635 if (msg_typed_ == NULL)
48 8557 UnwrapMsg();
49 15630 return msg_typed_;
50 }
51
52
53 15637 CacheTransport::Frame::Frame()
54 15637 : owns_msg_typed_(false)
55 15637 , msg_typed_(NULL)
56 15637 , attachment_(NULL)
57 15637 , att_size_(0)
58 15637 , is_wrapped_(false)
59 15637 , is_msg_out_of_band_(false)
60 15637 { }
61
62
63 13634 CacheTransport::Frame::Frame(google::protobuf::MessageLite *m)
64 13634 : owns_msg_typed_(false)
65 13634 , msg_typed_(m)
66 13634 , attachment_(NULL)
67 13634 , att_size_(0)
68 13634 , is_wrapped_(false)
69 13634 , is_msg_out_of_band_(false)
70 13634 { }
71
72
73 29270 CacheTransport::Frame::~Frame() {
74 29270 Reset(0);
75 29262 }
76
77
78 7078 bool CacheTransport::Frame::IsMsgOutOfBand() {
79
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 7078 times.
7078 assert(msg_rpc_.IsInitialized());
80
1/2
✓ Branch 0 taken 7078 times.
✗ Branch 1 not taken.
7078 if (msg_typed_ == NULL)
81 7078 UnwrapMsg();
82 7078 return is_msg_out_of_band_;
83 }
84
85
86 2028 void CacheTransport::Frame::MergeFrom(const Frame &other) {
87 2028 msg_rpc_.CheckTypeAndMergeFrom(other.msg_rpc_);
88 2028 owns_msg_typed_ = true;
89
2/2
✓ Branch 0 taken 1800 times.
✓ Branch 1 taken 228 times.
2028 if (other.att_size_ > 0) {
90
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1800 times.
1800 assert(att_size_ >= other.att_size_);
91 1800 memcpy(attachment_, other.attachment_, other.att_size_);
92 1800 att_size_ = other.att_size_;
93 }
94 2028 }
95
96
97 13607 bool CacheTransport::Frame::ParseMsgRpc(void *buffer, uint32_t size) {
98 13607 bool retval = msg_rpc_.ParseFromArray(buffer, size);
99
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 13607 times.
13607 if (!retval)
100 return false;
101
102 // Cleanup typed message when Frame leaves scope
103 13607 owns_msg_typed_ = true;
104 13607 return true;
105 }
106
107
108 29271 void CacheTransport::Frame::Release() {
109
2/2
✓ Branch 0 taken 15637 times.
✓ Branch 1 taken 13634 times.
29271 if (owns_msg_typed_)
110 15637 return;
111
112 13634 msg_rpc_.release_msg_refcount_req();
113 13633 msg_rpc_.release_msg_refcount_reply();
114 13634 msg_rpc_.release_msg_read_req();
115 13633 msg_rpc_.release_msg_read_reply();
116 13632 msg_rpc_.release_msg_object_info_req();
117 13632 msg_rpc_.release_msg_object_info_reply();
118 13632 msg_rpc_.release_msg_store_req();
119 13632 msg_rpc_.release_msg_store_abort_req();
120 13632 msg_rpc_.release_msg_store_reply();
121 13631 msg_rpc_.release_msg_handshake();
122 13630 msg_rpc_.release_msg_handshake_ack();
123 13630 msg_rpc_.release_msg_quit();
124 13629 msg_rpc_.release_msg_ioctl();
125 13629 msg_rpc_.release_msg_info_req();
126 13630 msg_rpc_.release_msg_info_reply();
127 13631 msg_rpc_.release_msg_shrink_req();
128 13632 msg_rpc_.release_msg_shrink_reply();
129 13629 msg_rpc_.release_msg_list_req();
130 13630 msg_rpc_.release_msg_list_reply();
131 13631 msg_rpc_.release_msg_detach();
132 13631 msg_rpc_.release_msg_breadcrumb_store_req();
133 13631 msg_rpc_.release_msg_breadcrumb_load_req();
134 13629 msg_rpc_.release_msg_breadcrumb_reply();
135 }
136
137
138 29271 void CacheTransport::Frame::Reset(uint32_t original_att_size) {
139 29271 msg_typed_ = NULL;
140 29271 att_size_ = original_att_size;
141 29271 is_wrapped_ = false;
142 29271 is_msg_out_of_band_ = false;
143 29271 Release();
144 29268 msg_rpc_.Clear();
145 29263 owns_msg_typed_ = false;
146 29263 }
147
148
149 13634 void CacheTransport::Frame::WrapMsg() {
150
2/2
✓ Branch 3 taken 44 times.
✓ Branch 4 taken 13590 times.
13634 if (msg_typed_->GetTypeName() == "cvmfs.MsgHandshake") {
151 44 msg_rpc_.set_allocated_msg_handshake(
152 44 reinterpret_cast<cvmfs::MsgHandshake *>(msg_typed_));
153
2/2
✓ Branch 3 taken 18 times.
✓ Branch 4 taken 13572 times.
13590 } else if (msg_typed_->GetTypeName() == "cvmfs.MsgHandshakeAck") {
154 18 msg_rpc_.set_allocated_msg_handshake_ack(
155 18 reinterpret_cast<cvmfs::MsgHandshakeAck *>(msg_typed_));
156
2/2
✓ Branch 3 taken 42 times.
✓ Branch 4 taken 13530 times.
13572 } else if (msg_typed_->GetTypeName() == "cvmfs.MsgQuit") {
157 42 msg_rpc_.set_allocated_msg_quit(
158 42 reinterpret_cast<cvmfs::MsgQuit *>(msg_typed_));
159
2/2
✓ Branch 3 taken 4 times.
✓ Branch 4 taken 13526 times.
13530 } else if (msg_typed_->GetTypeName() == "cvmfs.MsgIoctl") {
160 4 msg_rpc_.set_allocated_msg_ioctl(
161 4 reinterpret_cast<cvmfs::MsgIoctl *>(msg_typed_));
162
2/2
✓ Branch 3 taken 3068 times.
✓ Branch 4 taken 10458 times.
13526 } else if (msg_typed_->GetTypeName() == "cvmfs.MsgRefcountReq") {
163 3068 msg_rpc_.set_allocated_msg_refcount_req(
164 3068 reinterpret_cast<cvmfs::MsgRefcountReq *>(msg_typed_));
165
2/2
✓ Branch 3 taken 564 times.
✓ Branch 4 taken 9894 times.
10458 } else if (msg_typed_->GetTypeName() == "cvmfs.MsgRefcountReply") {
166 564 msg_rpc_.set_allocated_msg_refcount_reply(
167 564 reinterpret_cast<cvmfs::MsgRefcountReply *>(msg_typed_));
168
2/2
✓ Branch 3 taken 40 times.
✓ Branch 4 taken 9854 times.
9894 } else if (msg_typed_->GetTypeName() == "cvmfs.MsgObjectInfoReq") {
169 40 msg_rpc_.set_allocated_msg_object_info_req(
170 40 reinterpret_cast<cvmfs::MsgObjectInfoReq *>(msg_typed_));
171
2/2
✓ Branch 3 taken 16 times.
✓ Branch 4 taken 9838 times.
9854 } else if (msg_typed_->GetTypeName() == "cvmfs.MsgObjectInfoReply") {
172 16 msg_rpc_.set_allocated_msg_object_info_reply(
173 16 reinterpret_cast<cvmfs::MsgObjectInfoReply *>(msg_typed_));
174
2/2
✓ Branch 3 taken 2909 times.
✓ Branch 4 taken 6929 times.
9838 } else if (msg_typed_->GetTypeName() == "cvmfs.MsgReadReq") {
175 2909 msg_rpc_.set_allocated_msg_read_req(
176 2909 reinterpret_cast<cvmfs::MsgReadReq *>(msg_typed_));
177
2/2
✓ Branch 3 taken 2211 times.
✓ Branch 4 taken 4718 times.
6929 } else if (msg_typed_->GetTypeName() == "cvmfs.MsgReadReply") {
178 2211 msg_rpc_.set_allocated_msg_read_reply(
179 2211 reinterpret_cast<cvmfs::MsgReadReply *>(msg_typed_));
180
2/2
✓ Branch 3 taken 3022 times.
✓ Branch 4 taken 1696 times.
4718 } else if (msg_typed_->GetTypeName() == "cvmfs.MsgStoreReq") {
181 3022 msg_rpc_.set_allocated_msg_store_req(
182 3022 reinterpret_cast<cvmfs::MsgStoreReq *>(msg_typed_));
183
2/2
✓ Branch 3 taken 1 times.
✓ Branch 4 taken 1695 times.
1696 } else if (msg_typed_->GetTypeName() == "cvmfs.MsgStoreAbortReq") {
184 1 msg_rpc_.set_allocated_msg_store_abort_req(
185 1 reinterpret_cast<cvmfs::MsgStoreAbortReq *>(msg_typed_));
186
2/2
✓ Branch 3 taken 609 times.
✓ Branch 4 taken 1086 times.
1695 } else if (msg_typed_->GetTypeName() == "cvmfs.MsgStoreReply") {
187 609 msg_rpc_.set_allocated_msg_store_reply(
188 609 reinterpret_cast<cvmfs::MsgStoreReply *>(msg_typed_));
189
2/2
✓ Branch 3 taken 28 times.
✓ Branch 4 taken 1058 times.
1086 } else if (msg_typed_->GetTypeName() == "cvmfs.MsgInfoReq") {
190 28 msg_rpc_.set_allocated_msg_info_req(
191 28 reinterpret_cast<cvmfs::MsgInfoReq *>(msg_typed_));
192
2/2
✓ Branch 3 taken 4 times.
✓ Branch 4 taken 1054 times.
1058 } else if (msg_typed_->GetTypeName() == "cvmfs.MsgInfoReply") {
193 4 msg_rpc_.set_allocated_msg_info_reply(
194 4 reinterpret_cast<cvmfs::MsgInfoReply *>(msg_typed_));
195
2/2
✓ Branch 3 taken 10 times.
✓ Branch 4 taken 1044 times.
1054 } else if (msg_typed_->GetTypeName() == "cvmfs.MsgShrinkReq") {
196 10 msg_rpc_.set_allocated_msg_shrink_req(
197 10 reinterpret_cast<cvmfs::MsgShrinkReq *>(msg_typed_));
198
2/2
✓ Branch 3 taken 2 times.
✓ Branch 4 taken 1042 times.
1044 } else if (msg_typed_->GetTypeName() == "cvmfs.MsgShrinkReply") {
199 2 msg_rpc_.set_allocated_msg_shrink_reply(
200 2 reinterpret_cast<cvmfs::MsgShrinkReply *>(msg_typed_));
201
2/2
✓ Branch 3 taken 18 times.
✓ Branch 4 taken 1024 times.
1042 } else if (msg_typed_->GetTypeName() == "cvmfs.MsgListReq") {
202 18 msg_rpc_.set_allocated_msg_list_req(
203 18 reinterpret_cast<cvmfs::MsgListReq *>(msg_typed_));
204
2/2
✓ Branch 3 taken 10 times.
✓ Branch 4 taken 1014 times.
1024 } else if (msg_typed_->GetTypeName() == "cvmfs.MsgListReply") {
205 10 msg_rpc_.set_allocated_msg_list_reply(
206 10 reinterpret_cast<cvmfs::MsgListReply *>(msg_typed_));
207
2/2
✓ Branch 3 taken 3 times.
✓ Branch 4 taken 1011 times.
1014 } else if (msg_typed_->GetTypeName() == "cvmfs.MsgBreadcrumbStoreReq") {
208 3 msg_rpc_.set_allocated_msg_breadcrumb_store_req(
209 3 reinterpret_cast<cvmfs::MsgBreadcrumbStoreReq *>(msg_typed_));
210
2/2
✓ Branch 3 taken 6 times.
✓ Branch 4 taken 1005 times.
1011 } else if (msg_typed_->GetTypeName() == "cvmfs.MsgBreadcrumbLoadReq") {
211 6 msg_rpc_.set_allocated_msg_breadcrumb_load_req(
212 6 reinterpret_cast<cvmfs::MsgBreadcrumbLoadReq *>(msg_typed_));
213
2/2
✓ Branch 3 taken 3 times.
✓ Branch 4 taken 1002 times.
1005 } else if (msg_typed_->GetTypeName() == "cvmfs.MsgBreadcrumbReply") {
214 3 msg_rpc_.set_allocated_msg_breadcrumb_reply(
215 3 reinterpret_cast<cvmfs::MsgBreadcrumbReply *>(msg_typed_));
216
1/2
✓ Branch 3 taken 1002 times.
✗ Branch 4 not taken.
1002 } else if (msg_typed_->GetTypeName() == "cvmfs.MsgDetach") {
217 1002 msg_rpc_.set_allocated_msg_detach(
218 1002 reinterpret_cast<cvmfs::MsgDetach *>(msg_typed_));
219 1002 is_msg_out_of_band_ = true;
220 } else {
221 // Unexpected message type, should never happen
222 PANIC(NULL);
223 }
224 13634 is_wrapped_ = true;
225 13634 }
226
227
228 15634 void CacheTransport::Frame::UnwrapMsg() {
229
2/2
✓ Branch 1 taken 18 times.
✓ Branch 2 taken 15615 times.
15634 if (msg_rpc_.has_msg_handshake()) {
230 18 msg_typed_ = msg_rpc_.mutable_msg_handshake();
231
2/2
✓ Branch 1 taken 44 times.
✓ Branch 2 taken 15572 times.
15615 } else if (msg_rpc_.has_msg_handshake_ack()) {
232 44 msg_typed_ = msg_rpc_.mutable_msg_handshake_ack();
233
2/2
✓ Branch 1 taken 18 times.
✓ Branch 2 taken 15550 times.
15572 } else if (msg_rpc_.has_msg_quit()) {
234 18 msg_typed_ = msg_rpc_.mutable_msg_quit();
235
2/2
✓ Branch 1 taken 4 times.
✓ Branch 2 taken 15548 times.
15550 } else if (msg_rpc_.has_msg_ioctl()) {
236 4 msg_typed_ = msg_rpc_.mutable_msg_ioctl();
237
2/2
✓ Branch 1 taken 564 times.
✓ Branch 2 taken 14985 times.
15548 } else if (msg_rpc_.has_msg_refcount_req()) {
238 564 msg_typed_ = msg_rpc_.mutable_msg_refcount_req();
239
2/2
✓ Branch 1 taken 3087 times.
✓ Branch 2 taken 11898 times.
14985 } else if (msg_rpc_.has_msg_refcount_reply()) {
240 3087 msg_typed_ = msg_rpc_.mutable_msg_refcount_reply();
241
2/2
✓ Branch 1 taken 16 times.
✓ Branch 2 taken 11879 times.
11898 } else if (msg_rpc_.has_msg_object_info_req()) {
242 16 msg_typed_ = msg_rpc_.mutable_msg_object_info_req();
243
2/2
✓ Branch 1 taken 49 times.
✓ Branch 2 taken 11830 times.
11879 } else if (msg_rpc_.has_msg_object_info_reply()) {
244 49 msg_typed_ = msg_rpc_.mutable_msg_object_info_reply();
245
2/2
✓ Branch 1 taken 2211 times.
✓ Branch 2 taken 9619 times.
11830 } else if (msg_rpc_.has_msg_read_req()) {
246 2211 msg_typed_ = msg_rpc_.mutable_msg_read_req();
247
2/2
✓ Branch 1 taken 4709 times.
✓ Branch 2 taken 4917 times.
9619 } else if (msg_rpc_.has_msg_read_reply()) {
248 4709 msg_typed_ = msg_rpc_.mutable_msg_read_reply();
249
2/2
✓ Branch 1 taken 608 times.
✓ Branch 2 taken 4309 times.
4917 } else if (msg_rpc_.has_msg_store_req()) {
250 608 msg_typed_ = msg_rpc_.mutable_msg_store_req();
251
2/2
✓ Branch 1 taken 1 times.
✓ Branch 2 taken 4308 times.
4309 } else if (msg_rpc_.has_msg_store_abort_req()) {
252 1 msg_typed_ = msg_rpc_.mutable_msg_store_abort_req();
253
2/2
✓ Branch 1 taken 3223 times.
✓ Branch 2 taken 1085 times.
4308 } else if (msg_rpc_.has_msg_store_reply()) {
254 3223 msg_typed_ = msg_rpc_.mutable_msg_store_reply();
255
2/2
✓ Branch 1 taken 4 times.
✓ Branch 2 taken 1081 times.
1085 } else if (msg_rpc_.has_msg_info_req()) {
256 4 msg_typed_ = msg_rpc_.mutable_msg_info_req();
257
2/2
✓ Branch 1 taken 28 times.
✓ Branch 2 taken 1053 times.
1081 } else if (msg_rpc_.has_msg_info_reply()) {
258 28 msg_typed_ = msg_rpc_.mutable_msg_info_reply();
259
2/2
✓ Branch 1 taken 2 times.
✓ Branch 2 taken 1051 times.
1053 } else if (msg_rpc_.has_msg_shrink_req()) {
260 2 msg_typed_ = msg_rpc_.mutable_msg_shrink_req();
261
2/2
✓ Branch 1 taken 10 times.
✓ Branch 2 taken 1041 times.
1051 } else if (msg_rpc_.has_msg_shrink_reply()) {
262 10 msg_typed_ = msg_rpc_.mutable_msg_shrink_reply();
263
2/2
✓ Branch 1 taken 10 times.
✓ Branch 2 taken 1031 times.
1041 } else if (msg_rpc_.has_msg_list_req()) {
264 10 msg_typed_ = msg_rpc_.mutable_msg_list_req();
265
2/2
✓ Branch 1 taken 18 times.
✓ Branch 2 taken 1013 times.
1031 } else if (msg_rpc_.has_msg_list_reply()) {
266 18 msg_typed_ = msg_rpc_.mutable_msg_list_reply();
267
2/2
✓ Branch 1 taken 1 times.
✓ Branch 2 taken 1012 times.
1013 } else if (msg_rpc_.has_msg_breadcrumb_store_req()) {
268 1 msg_typed_ = msg_rpc_.mutable_msg_breadcrumb_store_req();
269
2/2
✓ Branch 1 taken 2 times.
✓ Branch 2 taken 1010 times.
1012 } else if (msg_rpc_.has_msg_breadcrumb_load_req()) {
270 2 msg_typed_ = msg_rpc_.mutable_msg_breadcrumb_load_req();
271
2/2
✓ Branch 1 taken 9 times.
✓ Branch 2 taken 1001 times.
1010 } else if (msg_rpc_.has_msg_breadcrumb_reply()) {
272 9 msg_typed_ = msg_rpc_.mutable_msg_breadcrumb_reply();
273
1/2
✓ Branch 1 taken 1001 times.
✗ Branch 2 not taken.
1001 } else if (msg_rpc_.has_msg_detach()) {
274 1001 msg_typed_ = msg_rpc_.mutable_msg_detach();
275 1001 is_msg_out_of_band_ = true;
276 } else {
277 // Unexpected message type, should never happen
278 PANIC(NULL);
279 }
280 15637 }
281
282
283 //------------------------------------------------------------------------------
284
285
286 44 CacheTransport::CacheTransport(int fd_connection)
287 44 : fd_connection_(fd_connection)
288 44 , flags_(0)
289 {
290
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 44 times.
44 assert(fd_connection_ >= 0);
291 44 }
292
293
294 4461 CacheTransport::CacheTransport(int fd_connection, uint32_t flags)
295 4461 : fd_connection_(fd_connection)
296 4461 , flags_(flags)
297 {
298
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4461 times.
4461 assert(fd_connection_ >= 0);
299 4461 }
300
301
302 206379 void CacheTransport::FillMsgHash(
303 const shash::Any &hash,
304 cvmfs::MsgHash *msg_hash)
305 {
306
3/4
✓ Branch 0 taken 206351 times.
✓ Branch 1 taken 12 times.
✓ Branch 2 taken 16 times.
✗ Branch 3 not taken.
206379 switch (hash.algorithm) {
307 206351 case shash::kSha1:
308 206351 msg_hash->set_algorithm(cvmfs::HASH_SHA1);
309 206351 break;
310 12 case shash::kRmd160:
311 12 msg_hash->set_algorithm(cvmfs::HASH_RIPEMD160);
312 12 break;
313 16 case shash::kShake128:
314 16 msg_hash->set_algorithm(cvmfs::HASH_SHAKE128);
315 16 break;
316 default:
317 PANIC(NULL);
318 }
319 206379 msg_hash->set_digest(hash.digest, shash::kDigestSizes[hash.algorithm]);
320 206379 }
321
322
323 3014 void CacheTransport::FillObjectType(
324 int object_flags, cvmfs::EnumObjectType *wire_type)
325 {
326 3014 *wire_type = cvmfs::OBJECT_REGULAR;
327
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3014 times.
3014 if (object_flags & CacheManager::kLabelCatalog)
328 *wire_type = cvmfs::OBJECT_CATALOG;
329
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3014 times.
3014 if (object_flags & CacheManager::kLabelVolatile)
330 *wire_type = cvmfs::OBJECT_VOLATILE;
331 3014 }
332
333
334 3403 bool CacheTransport::ParseMsgHash(
335 const cvmfs::MsgHash &msg_hash,
336 shash::Any *hash)
337 {
338
2/4
✓ Branch 1 taken 3399 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 4 times.
✗ Branch 4 not taken.
3403 switch (msg_hash.algorithm()) {
339 3399 case cvmfs::HASH_SHA1:
340 3399 hash->algorithm = shash::kSha1;
341 3399 break;
342 case cvmfs::HASH_RIPEMD160:
343 hash->algorithm = shash::kRmd160;
344 break;
345 4 case cvmfs::HASH_SHAKE128:
346 4 hash->algorithm = shash::kShake128;
347 4 break;
348 default:
349 return false;
350 }
351 3403 const unsigned digest_size = shash::kDigestSizes[hash->algorithm];
352
1/2
✗ Branch 2 not taken.
✓ Branch 3 taken 3403 times.
3403 if (msg_hash.digest().length() != digest_size)
353 return false;
354 3403 memcpy(hash->digest, msg_hash.digest().data(), digest_size);
355 3403 return true;
356 }
357
358
359 bool CacheTransport::ParseObjectType(
360 cvmfs::EnumObjectType wire_type, int *object_flags)
361 {
362 *object_flags = 0;
363 switch (wire_type) {
364 case cvmfs::OBJECT_REGULAR:
365 return true;
366 case cvmfs::OBJECT_CATALOG:
367 *object_flags |= CacheManager::kLabelCatalog;
368 return true;
369 case cvmfs::OBJECT_VOLATILE:
370 *object_flags |= CacheManager::kLabelVolatile;
371 return true;
372 default:
373 return false;
374 }
375 }
376
377
378 13610 bool CacheTransport::RecvFrame(CacheTransport::Frame *frame) {
379 uint32_t size;
380 bool has_attachment;
381
1/2
✓ Branch 1 taken 13610 times.
✗ Branch 2 not taken.
13610 bool retval = RecvHeader(&size, &has_attachment);
382
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 13609 times.
13610 if (!retval)
383 1 return false;
384
385 void *buffer;
386
2/2
✓ Branch 0 taken 10316 times.
✓ Branch 1 taken 3293 times.
13609 if (size <= kMaxStackAlloc)
387 10316 buffer = alloca(size);
388 else
389 3293 buffer = smalloc(size);
390
1/2
✓ Branch 1 taken 13609 times.
✗ Branch 2 not taken.
13609 ssize_t nbytes = SafeRead(fd_connection_, buffer, size);
391
2/4
✓ Branch 0 taken 13609 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 13609 times.
13609 if ((nbytes < 0) || (static_cast<uint32_t>(nbytes) != size)) {
392 if (size > kMaxStackAlloc) { free(buffer); }
393 return false;
394 }
395
396 13609 uint32_t msg_size = size;
397
2/2
✓ Branch 0 taken 3509 times.
✓ Branch 1 taken 10100 times.
13609 if (has_attachment) {
398
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3509 times.
3509 if (size < 2) {
399 // kMaxStackAlloc is > 2 (of course!) but we'll leave the condition here
400 // for consistency.
401 if (size > kMaxStackAlloc) { free(buffer); }
402 return false;
403 }
404 3509 msg_size = (*reinterpret_cast<unsigned char *>(buffer)) +
405 3509 ((*(reinterpret_cast<unsigned char *>(buffer) + 1)) << 8);
406
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3509 times.
3509 if ((msg_size + kInnerHeaderSize) > size) {
407 if (size > kMaxStackAlloc) { free(buffer); }
408 return false;
409 }
410 }
411
412 13609 void *ptr_msg = has_attachment
413
2/2
✓ Branch 0 taken 3509 times.
✓ Branch 1 taken 10100 times.
13609 ? (reinterpret_cast<char *>(buffer) + kInnerHeaderSize)
414 : buffer;
415
1/2
✓ Branch 1 taken 13608 times.
✗ Branch 2 not taken.
13609 retval = frame->ParseMsgRpc(ptr_msg, msg_size);
416
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 13608 times.
13608 if (!retval) {
417 if (size > kMaxStackAlloc) { free(buffer); }
418 return false;
419 }
420
421
2/2
✓ Branch 0 taken 3509 times.
✓ Branch 1 taken 10099 times.
13608 if (has_attachment) {
422 3509 uint32_t attachment_size = size - (msg_size + kInnerHeaderSize);
423
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 3509 times.
3509 if (frame->att_size() < attachment_size) {
424 if (size > kMaxStackAlloc) { free(buffer); }
425 return false;
426 }
427 3509 void *ptr_attachment =
428 3509 reinterpret_cast<char *>(buffer) + kInnerHeaderSize + msg_size;
429 3509 memcpy(frame->attachment(), ptr_attachment, attachment_size);
430 3509 frame->set_att_size(attachment_size);
431 } else {
432 10099 frame->set_att_size(0);
433 }
434
2/2
✓ Branch 0 taken 3293 times.
✓ Branch 1 taken 10311 times.
13604 if (size > kMaxStackAlloc) { free(buffer); }
435 13604 return true;
436 }
437
438
439 13610 bool CacheTransport::RecvHeader(uint32_t *size, bool *has_attachment) {
440 unsigned char header[kHeaderSize];
441
1/2
✓ Branch 1 taken 13610 times.
✗ Branch 2 not taken.
13610 ssize_t nbytes = SafeRead(fd_connection_, header, kHeaderSize);
442
3/4
✓ Branch 0 taken 13610 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
✓ Branch 3 taken 13609 times.
13610 if ((nbytes < 0) || (static_cast<unsigned>(nbytes) != kHeaderSize))
443 1 return false;
444
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 13609 times.
13609 if ((header[0] & (~kFlagHasAttachment)) != kWireProtocolVersion)
445 return false;
446 13609 *has_attachment = header[0] & kFlagHasAttachment;
447 13609 *size = header[1] + (header[2] << 8) + (header[3] << 16);
448
2/4
✓ Branch 0 taken 13609 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 13609 times.
✗ Branch 3 not taken.
13609 return (*size > 0) && (*size <= kMaxMsgSize);
449 }
450
451
452 13634 void CacheTransport::SendData(
453 void *message,
454 uint32_t msg_size,
455 void *attachment,
456 uint32_t att_size)
457 {
458 13634 uint32_t total_size =
459
2/2
✓ Branch 0 taken 5229 times.
✓ Branch 1 taken 8405 times.
13634 msg_size + att_size + ((att_size > 0) ? kInnerHeaderSize : 0);
460
461
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 13634 times.
13634 assert(total_size > 0);
462
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 13634 times.
13634 assert(total_size <= kMaxMsgSize);
463
1/2
✓ Branch 1 taken 7898 times.
✗ Branch 2 not taken.
7898 LogCvmfs(kLogCache, kLogDebug,
464 "sending message of size %u to cache transport", total_size);
465
466 unsigned char header[kHeaderSize];
467
2/2
✓ Branch 0 taken 8405 times.
✓ Branch 1 taken 5229 times.
13634 header[0] = kWireProtocolVersion | ((att_size == 0) ? 0 : kFlagHasAttachment);
468 13634 header[1] = (total_size & 0x000000FF);
469 13634 header[2] = (total_size & 0x0000FF00) >> 8;
470 13634 header[3] = (total_size & 0x00FF0000) >> 16;
471 // Only transferred if an attachment is present. Otherwise the overall size
472 // is also the size of the protobuf message.
473 unsigned char inner_header[kInnerHeaderSize];
474
475 struct iovec iov[4];
476 13634 iov[0].iov_base = header;
477 13634 iov[0].iov_len = kHeaderSize;
478
479
2/2
✓ Branch 0 taken 5229 times.
✓ Branch 1 taken 8405 times.
13634 if (att_size > 0) {
480 5229 inner_header[0] = (msg_size & 0x000000FF);
481 5229 inner_header[1] = (msg_size & 0x0000FF00) >> 8;
482 5229 iov[1].iov_base = inner_header;
483 5229 iov[1].iov_len = kInnerHeaderSize;
484 5229 iov[2].iov_base = message;
485 5229 iov[2].iov_len = msg_size;
486 5229 iov[3].iov_base = attachment;
487 5229 iov[3].iov_len = att_size;
488 } else {
489 8405 iov[1].iov_base = message;
490 8405 iov[1].iov_len = msg_size;
491 }
492
2/2
✓ Branch 0 taken 1002 times.
✓ Branch 1 taken 12632 times.
13634 if (flags_ & kFlagSendNonBlocking) {
493
2/4
✓ Branch 0 taken 1002 times.
✗ Branch 1 not taken.
✓ Branch 3 taken 1002 times.
✗ Branch 4 not taken.
1002 SendNonBlocking(iov, (att_size == 0) ? 2 : 4);
494 1002 return;
495 }
496
3/4
✓ Branch 0 taken 7403 times.
✓ Branch 1 taken 5229 times.
✓ Branch 3 taken 12632 times.
✗ Branch 4 not taken.
12632 bool retval = SafeWriteV(fd_connection_, iov, (att_size == 0) ? 2 : 4);
497
498
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 12632 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
12632 if (!retval && !(flags_ & kFlagSendIgnoreFailure)) {
499 PANIC(kLogSyslogErr | kLogDebug,
500 "failed to write to external cache transport (%d), aborting", errno);
501 }
502 }
503
504 1002 void CacheTransport::SendNonBlocking(struct iovec *iov, unsigned iovcnt) {
505
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1002 times.
1002 assert(iovcnt > 0);
506 1002 unsigned total_size = 0;
507
2/2
✓ Branch 0 taken 2004 times.
✓ Branch 1 taken 1002 times.
3006 for (unsigned i = 0; i < iovcnt; ++i)
508 2004 total_size += iov[i].iov_len;
509 1002 unsigned char *buffer = reinterpret_cast<unsigned char *>(alloca(total_size));
510
511 1002 unsigned pos = 0;
512
2/2
✓ Branch 0 taken 2004 times.
✓ Branch 1 taken 1002 times.
3006 for (unsigned i = 0; i < iovcnt; ++i) {
513 2004 memcpy(buffer + pos, iov[i].iov_base, iov[i].iov_len);
514 2004 pos += iov[i].iov_len;
515 }
516
517 1002 int retval = send(fd_connection_, buffer, total_size, MSG_DONTWAIT);
518
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1002 times.
1002 if (retval < 0) {
519 assert(errno != EMSGSIZE);
520 if (!(flags_ & kFlagSendIgnoreFailure)) {
521 PANIC(kLogSyslogErr | kLogDebug,
522 "failed to write to external cache transport (%d), aborting",
523 errno);
524 }
525 }
526 1002 }
527
528
529 13634 void CacheTransport::SendFrame(CacheTransport::Frame *frame) {
530 13634 cvmfs::MsgRpc *msg_rpc = frame->GetMsgRpc();
531 13633 int32_t size = msg_rpc->ByteSize();
532
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 13633 times.
13633 assert(size > 0);
533 #ifdef __APPLE__
534 void *buffer = smalloc(size);
535 #else
536 13633 void *buffer = alloca(size);
537 #endif
538 13633 bool retval = msg_rpc->SerializeToArray(buffer, size);
539
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 13634 times.
13634 assert(retval);
540 13634 SendData(buffer, size, frame->attachment(), frame->att_size());
541 #ifdef __APPLE__
542 free(buffer);
543 #endif
544 13634 }
545