GCC Code Coverage Report
Directory: cvmfs/ Exec Total Coverage
File: cvmfs/cache_transport.h Lines: 13 25 52.0 %
Date: 2019-02-03 02:48:13 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
3
inline const char *CacheTransportCode2Ascii(const cvmfs::EnumStatus code) {
20



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