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
: public MessageInstance
<MForward
> {
33 entity_addrvec_t client_addrs
;
34 entity_addr_t client_socket_addr
;
36 uint64_t con_features
;
37 EntityName entity_name
;
38 PaxosServiceMessage
*msg
; // incoming or outgoing message
40 string msg_desc
; // for operator<< only
42 static constexpr int HEAD_VERSION
= 4;
43 static constexpr int COMPAT_VERSION
= 4;
45 MForward() : MessageInstance(MSG_FORWARD
, HEAD_VERSION
, COMPAT_VERSION
),
46 tid(0), con_features(0), msg(NULL
) {}
47 MForward(uint64_t t
, PaxosServiceMessage
*m
, uint64_t feat
,
49 MessageInstance(MSG_FORWARD
, HEAD_VERSION
, COMPAT_VERSION
),
50 tid(t
), client_caps(caps
), msg(NULL
) {
51 client_type
= m
->get_source().type();
52 client_addrs
= m
->get_source_addrs();
53 if (auto con
= m
->get_connection()) {
54 client_socket_addr
= con
->get_peer_socket_addr();
57 msg
= (PaxosServiceMessage
*)m
->get();
60 ~MForward() override
{
62 // message was unclaimed
69 void encode_payload(uint64_t features
) override
{
71 if (!HAVE_FEATURE(features
, SERVER_NAUTILUS
)) {
73 header
.compat_version
= 3;
76 client
.name
= entity_name_t(client_type
, -1);
77 client
.addr
= client_addrs
.legacy_addr();
78 encode(client
, payload
, features
);
79 encode(client_caps
, payload
, features
);
80 // Encode client message with intersection of target and source
81 // features. This could matter if the semantics of the encoded
82 // message are changed when reencoding with more features than the
83 // client had originally. That should never happen, but we may as
84 // well be defensive here.
85 if (con_features
!= features
) {
88 encode_message(msg
, features
& con_features
, payload
);
89 encode(con_features
, payload
);
90 encode(entity_name
, payload
);
93 header
.version
= HEAD_VERSION
;
94 header
.compat_version
= COMPAT_VERSION
;
96 encode(client_type
, payload
, features
);
97 encode(client_addrs
, payload
, features
);
98 encode(client_socket_addr
, payload
, features
);
99 encode(client_caps
, payload
, features
);
100 // Encode client message with intersection of target and source
101 // features. This could matter if the semantics of the encoded
102 // message are changed when reencoding with more features than the
103 // client had originally. That should never happen, but we may as
104 // well be defensive here.
105 if (con_features
!= features
) {
106 msg
->clear_payload();
108 encode_message(msg
, features
& con_features
, payload
);
109 encode(con_features
, payload
);
110 encode(entity_name
, payload
);
113 void decode_payload() override
{
114 auto p
= payload
.cbegin();
116 if (header
.version
< 4) {
117 entity_inst_t client
;
119 client_type
= client
.name
.type();
120 client_addrs
= entity_addrvec_t(client
.addr
);
121 client_socket_addr
= client
.addr
;
123 decode(client_type
, p
);
124 decode(client_addrs
, p
);
125 decode(client_socket_addr
, p
);
127 decode(client_caps
, p
);
128 msg
= (PaxosServiceMessage
*)decode_message(NULL
, 0, p
);
129 decode(con_features
, p
);
130 decode(entity_name
, p
);
133 PaxosServiceMessage
*claim_message() {
134 // let whoever is claiming the message deal with putting it.
136 msg_desc
= stringify(*msg
);
137 PaxosServiceMessage
*m
= msg
;
142 std::string_view
get_type_name() const override
{ return "forward"; }
143 void print(ostream
& o
) const override
{
150 o
<< " caps " << client_caps
152 << " con_features " << con_features
<< ")";