]> git.proxmox.com Git - ceph.git/blob - ceph/src/messages/MForward.h
import 15.2.0 Octopus source
[ceph.git] / ceph / src / messages / MForward.h
1 // -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
2 // vim: ts=8 sw=2 smarttab
3 /*
4 * Ceph - scalable distributed file system
5 *
6 * Copyright (C) 2004-2010 Sage Weil <sage@newdream.net>
7 *
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.
12 *
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
16 * checking.
17 */
18
19 #ifndef CEPH_MFORWARD_H
20 #define CEPH_MFORWARD_H
21
22 #include "msg/Message.h"
23 #include "mon/MonCap.h"
24 #include "include/encoding.h"
25 #include "include/stringify.h"
26
27 class MForward : public Message {
28 public:
29 uint64_t tid;
30 uint8_t client_type;
31 entity_addrvec_t client_addrs;
32 entity_addr_t client_socket_addr;
33 MonCap client_caps;
34 uint64_t con_features;
35 EntityName entity_name;
36 PaxosServiceMessage *msg; // incoming or outgoing message
37
38 string msg_desc; // for operator<< only
39
40 static constexpr int HEAD_VERSION = 4;
41 static constexpr int COMPAT_VERSION = 4;
42
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,
46 const MonCap& caps) :
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();
53 }
54 con_features = feat;
55 msg = (PaxosServiceMessage*)m->get();
56 }
57 private:
58 ~MForward() override {
59 if (msg) {
60 // message was unclaimed
61 msg->put();
62 msg = NULL;
63 }
64 }
65
66 public:
67 void encode_payload(uint64_t features) override {
68 using ceph::encode;
69 if (!HAVE_FEATURE(features, SERVER_NAUTILUS)) {
70 header.version = 3;
71 header.compat_version = 3;
72 encode(tid, payload);
73 entity_inst_t client;
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) {
84 msg->clear_payload();
85 }
86 encode_message(msg, features & con_features, payload);
87 encode(con_features, payload);
88 encode(entity_name, payload);
89 return;
90 }
91 header.version = HEAD_VERSION;
92 header.compat_version = COMPAT_VERSION;
93 encode(tid, payload);
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();
105 }
106 encode_message(msg, features & con_features, payload);
107 encode(con_features, payload);
108 encode(entity_name, payload);
109 }
110
111 void decode_payload() override {
112 auto p = payload.cbegin();
113 decode(tid, p);
114 if (header.version < 4) {
115 entity_inst_t client;
116 decode(client, p);
117 client_type = client.name.type();
118 client_addrs = entity_addrvec_t(client.addr);
119 client_socket_addr = client.addr;
120 } else {
121 decode(client_type, p);
122 decode(client_addrs, p);
123 decode(client_socket_addr, p);
124 }
125 decode(client_caps, p);
126 msg = (PaxosServiceMessage *)decode_message(NULL, 0, p);
127 decode(con_features, p);
128 decode(entity_name, p);
129 }
130
131 PaxosServiceMessage *claim_message() {
132 // let whoever is claiming the message deal with putting it.
133 ceph_assert(msg);
134 msg_desc = stringify(*msg);
135 PaxosServiceMessage *m = msg;
136 msg = NULL;
137 return m;
138 }
139
140 std::string_view get_type_name() const override { return "forward"; }
141 void print(ostream& o) const override {
142 o << "forward(";
143 if (msg) {
144 o << *msg;
145 } else {
146 o << msg_desc;
147 }
148 o << " caps " << client_caps
149 << " tid " << tid
150 << " con_features " << con_features << ")";
151 }
152 private:
153 template<class T, typename... Args>
154 friend boost::intrusive_ptr<T> ceph::make_message(Args&&... args);
155 };
156
157 #endif