GCC Code Coverage Report


Directory: cvmfs/
File: cvmfs/cache_transport.h
Date: 2025-06-22 02:36:02
Exec Total Coverage
Lines: 15 39 38.5%
Branches: 2 14 14.3%

Line Branch Exec Source
1 /**
2 * This file is part of the CernVM File System.
3 */
4 #ifndef CVMFS_CACHE_TRANSPORT_H_
5 #define CVMFS_CACHE_TRANSPORT_H_
6
7 #include <stdint.h>
8
9 #include <cstdlib>
10
11 #include "cache.h"
12 #include "cache.pb.h"
13 #include "util/single_copy.h"
14
15 namespace shash {
16 struct Any;
17 }
18
19 45 inline const char *CacheTransportCode2Ascii(const cvmfs::EnumStatus code) {
20
2/14
✗ Branch 0 not taken.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
✓ Branch 6 taken 30 times.
✗ Branch 7 not taken.
✗ Branch 8 not taken.
✗ Branch 9 not taken.
✗ Branch 10 not taken.
✓ Branch 11 taken 15 times.
✗ Branch 12 not taken.
✗ Branch 13 not taken.
45 switch (code) {
21 case cvmfs::STATUS_UNKNOWN:
22 return "unknown cache protocol error";
23 case cvmfs::STATUS_OK:
24 return "OK";
25 case cvmfs::STATUS_NOSUPPORT:
26 return "operation not implemented by cache plugin";
27 case cvmfs::STATUS_FORBIDDEN:
28 return "cache plugin denied the operation";
29 case cvmfs::STATUS_NOSPACE:
30 return "no space in cache";
31 case cvmfs::STATUS_NOENTRY:
32 return "object not found in cache";
33 30 case cvmfs::STATUS_MALFORMED:
34 30 return "malformed cache protocol message";
35 case cvmfs::STATUS_IOERR:
36 return "I/O error";
37 case cvmfs::STATUS_CORRUPTED:
38 return "corrupted data detected";
39 case cvmfs::STATUS_TIMEOUT:
40 return "multipart request timed out";
41 case cvmfs::STATUS_BADCOUNT:
42 return "invalid attempt to set negative reference count";
43 15 case cvmfs::STATUS_OUTOFBOUNDS:
44 15 return "out of bounds";
45 case cvmfs::STATUS_PARTIAL:
46 return "cache could not be cleaned up to the given limit";
47 default:
48 return "unexpected cache protocol error";
49 }
50 }
51
52 /**
53 * Sending and receiving with a file descriptor. Does _not_ take the ownership
54 * of the file descriptor.
55 */
56 class CacheTransport {
57 public:
58 /**
59 * When this environment variable is set, the plugin will notify a cvmfs
60 * client once it is ready to accept connections.
61 */
62 static const char *kEnvReadyNotifyFd; // __CVMFS_CACHE_EXTERNAL_PIPE_READY__
63 static const char kReadyNotification = 'C';
64 static const char kFailureNotification = 'F';
65 /**
66 * Version of the wire protocol. The effective protocol version is negotiated
67 * through the handshake.
68 */
69 static const unsigned char kWireProtocolVersion = 0x01;
70 /**
71 * This is or-ed to the version number if the message has an attachment. In
72 * this case, the 2 bytes after the header specify the size of the protobuf
73 * message alone.
74 */
75 static const unsigned char kFlagHasAttachment = 0x80;
76 /**
77 * Maximum size of the protobuf message _and_ the attachment, should it exist.
78 */
79 static const uint32_t kMaxMsgSize = (2 << 24) - 1; // 24MB (3 bytes)
80 /**
81 * The first byte has the wire protocol version, optionally or-ed with the
82 * "has attachment" flag. The other three bytes encode the overall message
83 * size in little-endian.
84 */
85 static const unsigned kHeaderSize = 4;
86 /**
87 * The "inner header" are two byte following the header. The two bytes encode
88 * in little-endian the size of the protobuf message alone, if there is an
89 * attachment. The inner header is only present if there is an attachment.
90 */
91 static const unsigned kInnerHeaderSize = 2;
92
93 static const uint32_t kFlagSendIgnoreFailure = 0x01;
94 static const uint32_t kFlagSendNonBlocking = 0x02;
95
96
97 /**
98 * A single unit of data transfer contains a "typed" Msg... protobuf message
99 * inside a MsgRpc message. Optionally, there can be an "attachment", which
100 * is a byte stream following the protobuf message. The typed message and the
101 * attachment buffer are (stack)-allocated by users of CacheTransport. The
102 * Frame subclass takes care of wrapping and unwrapping into/from MsgRpc
103 * message.
104 */
105 class Frame : SingleCopy {
106 public:
107 Frame();
108 explicit Frame(google::protobuf::MessageLite *m);
109 ~Frame();
110 void MergeFrom(const Frame &other);
111 void Reset(uint32_t original_att_size);
112
113 176226 void *attachment() const { return attachment_; }
114 297612 uint32_t att_size() const { return att_size_; }
115 124166 void set_att_size(uint32_t size) { att_size_ = size; }
116 175791 void set_attachment(void *attachment, uint32_t att_size) {
117 175791 attachment_ = attachment;
118 175791 att_size_ = att_size;
119 175791 }
120
121 bool ParseMsgRpc(void *buffer, uint32_t size);
122 cvmfs::MsgRpc *GetMsgRpc();
123 google::protobuf::MessageLite *GetMsgTyped();
124 // The Detach message does not follow the command-reply pattern
125 bool IsMsgOutOfBand();
126
127 private:
128 void WrapMsg();
129 void UnwrapMsg();
130 void Release();
131
132 cvmfs::MsgRpc msg_rpc_;
133 bool owns_msg_typed_;
134 /**
135 * Can either point to a user-provided message (sender side) or to a message
136 * inside msg_rpc_ (receiving end)
137 */
138 google::protobuf::MessageLite *msg_typed_;
139 void *attachment_;
140 uint32_t att_size_;
141 bool is_wrapped_;
142 bool is_msg_out_of_band_;
143 }; // class CacheTransport::Frame
144
145
146 explicit CacheTransport(int fd_connection);
147 CacheTransport(int fd_connection, uint32_t flags);
148 67209 ~CacheTransport() { }
149
150 void SendFrame(Frame *frame);
151 bool RecvFrame(Frame *frame);
152
153 void FillMsgHash(const shash::Any &hash, cvmfs::MsgHash *msg_hash);
154 bool ParseMsgHash(const cvmfs::MsgHash &msg_hash, shash::Any *hash);
155 void FillObjectType(int object_flags, cvmfs::EnumObjectType *wire_type);
156 bool ParseObjectType(cvmfs::EnumObjectType wire_type, int *object_flags);
157
158 588 int fd_connection() const { return fd_connection_; }
159
160 private:
161 static const unsigned kMaxStackAlloc = 256 * 1024; // 256 kB
162
163 void SendData(void *message,
164 uint32_t msg_size,
165 void *attachment = NULL,
166 uint32_t att_size = 0);
167 void SendNonBlocking(struct iovec *iov, unsigned iovcnt);
168 bool RecvHeader(uint32_t *size, bool *has_attachment);
169
170 int fd_connection_;
171 uint32_t flags_;
172 }; // class CacheTransport
173
174 #endif // CVMFS_CACHE_TRANSPORT_H_
175