1 // -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
2 // vim: ts=8 sw=2 smarttab
4 * Ceph - scalable distributed file system
6 * Copyright (C) 2004-2010 Sage Weil <sage@newdream.net>
8 * This is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU Lesser General Public
10 * License version 2.1, as published by the Free Software
11 * Foundation. See file COPYING.
13 * Client requests often need to get forwarded from some monitor
14 * to the leader. This class encapsulates the original message
15 * along with the client's caps so the leader can do proper permissions
19 #ifndef CEPH_MFORWARD_H
20 #define CEPH_MFORWARD_H
22 #include "msg/Message.h"
23 #include "mon/MonCap.h"
24 #include "include/encoding.h"
25 #include "include/stringify.h"
27 class MForward final
: public Message
{
31 entity_addrvec_t client_addrs
;
32 entity_addr_t client_socket_addr
;
34 uint64_t con_features
;
35 EntityName entity_name
;
36 PaxosServiceMessage
*msg
; // incoming or outgoing message
38 std::string msg_desc
; // for operator<< only
40 static constexpr int HEAD_VERSION
= 4;
41 static constexpr int COMPAT_VERSION
= 4;
43 MForward() : Message
{MSG_FORWARD
, HEAD_VERSION
, COMPAT_VERSION
},
44 tid(0), con_features(0), msg(NULL
) {}
45 MForward(uint64_t t
, PaxosServiceMessage
*m
, uint64_t feat
,
47 Message
{MSG_FORWARD
, HEAD_VERSION
, COMPAT_VERSION
},
48 tid(t
), client_caps(caps
), msg(NULL
) {
49 client_type
= m
->get_source().type();
50 client_addrs
= m
->get_source_addrs();
51 if (auto &con
= m
->get_connection()) {
52 client_socket_addr
= con
->get_peer_socket_addr();
55 msg
= (PaxosServiceMessage
*)m
->get();
60 // message was unclaimed
67 void encode_payload(uint64_t features
) override
{
69 if (!HAVE_FEATURE(features
, SERVER_NAUTILUS
)) {
71 header
.compat_version
= 3;
74 client
.name
= entity_name_t(client_type
, -1);
75 client
.addr
= client_addrs
.legacy_addr();
76 encode(client
, payload
, features
);
77 encode(client_caps
, payload
, features
);
78 // Encode client message with intersection of target and source
79 // features. This could matter if the semantics of the encoded
80 // message are changed when reencoding with more features than the
81 // client had originally. That should never happen, but we may as
82 // well be defensive here.
83 if (con_features
!= features
) {
86 encode_message(msg
, features
& con_features
, payload
);
87 encode(con_features
, payload
);
88 encode(entity_name
, payload
);
91 header
.version
= HEAD_VERSION
;
92 header
.compat_version
= COMPAT_VERSION
;
94 encode(client_type
, payload
, features
);
95 encode(client_addrs
, payload
, features
);
96 encode(client_socket_addr
, payload
, features
);
97 encode(client_caps
, payload
, features
);
98 // Encode client message with intersection of target and source
99 // features. This could matter if the semantics of the encoded
100 // message are changed when reencoding with more features than the
101 // client had originally. That should never happen, but we may as
102 // well be defensive here.
103 if (con_features
!= features
) {
104 msg
->clear_payload();
106 encode_message(msg
, features
& con_features
, payload
);
107 encode(con_features
, payload
);
108 encode(entity_name
, payload
);
111 void decode_payload() override
{
113 auto p
= payload
.cbegin();
115 if (header
.version
< 4) {
116 entity_inst_t client
;
118 client_type
= client
.name
.type();
119 client_addrs
= entity_addrvec_t(client
.addr
);
120 client_socket_addr
= client
.addr
;
122 decode(client_type
, p
);
123 decode(client_addrs
, p
);
124 decode(client_socket_addr
, p
);
126 decode(client_caps
, p
);
127 msg
= (PaxosServiceMessage
*)decode_message(NULL
, 0, p
);
128 decode(con_features
, p
);
129 decode(entity_name
, p
);
132 PaxosServiceMessage
*claim_message() {
133 // let whoever is claiming the message deal with putting it.
135 msg_desc
= stringify(*msg
);
136 PaxosServiceMessage
*m
= msg
;
141 std::string_view
get_type_name() const override
{ return "forward"; }
142 void print(std::ostream
& o
) const override
{
149 o
<< " caps " << client_caps
151 << " con_features " << con_features
<< ")";
154 template<class T
, typename
... Args
>
155 friend boost::intrusive_ptr
<T
> ceph::make_message(Args
&&... args
);