]> git.proxmox.com Git - ceph.git/blob - ceph/src/messages/MForward.h
update sources to ceph Nautilus 14.2.1
[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 MessageInstance<MForward> {
28 public:
29 friend factory;
30
31 uint64_t tid;
32 uint8_t client_type;
33 entity_addrvec_t client_addrs;
34 entity_addr_t client_socket_addr;
35 MonCap client_caps;
36 uint64_t con_features;
37 EntityName entity_name;
38 PaxosServiceMessage *msg; // incoming or outgoing message
39
40 string msg_desc; // for operator<< only
41
42 static constexpr int HEAD_VERSION = 4;
43 static constexpr int COMPAT_VERSION = 4;
44
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,
48 const MonCap& caps) :
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();
55 }
56 con_features = feat;
57 msg = (PaxosServiceMessage*)m->get();
58 }
59 private:
60 ~MForward() override {
61 if (msg) {
62 // message was unclaimed
63 msg->put();
64 msg = NULL;
65 }
66 }
67
68 public:
69 void encode_payload(uint64_t features) override {
70 using ceph::encode;
71 if (!HAVE_FEATURE(features, SERVER_NAUTILUS)) {
72 header.version = 3;
73 header.compat_version = 3;
74 encode(tid, payload);
75 entity_inst_t client;
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) {
86 msg->clear_payload();
87 }
88 encode_message(msg, features & con_features, payload);
89 encode(con_features, payload);
90 encode(entity_name, payload);
91 return;
92 }
93 header.version = HEAD_VERSION;
94 header.compat_version = COMPAT_VERSION;
95 encode(tid, payload);
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();
107 }
108 encode_message(msg, features & con_features, payload);
109 encode(con_features, payload);
110 encode(entity_name, payload);
111 }
112
113 void decode_payload() override {
114 auto p = payload.cbegin();
115 decode(tid, p);
116 if (header.version < 4) {
117 entity_inst_t client;
118 decode(client, p);
119 client_type = client.name.type();
120 client_addrs = entity_addrvec_t(client.addr);
121 client_socket_addr = client.addr;
122 } else {
123 decode(client_type, p);
124 decode(client_addrs, p);
125 decode(client_socket_addr, p);
126 }
127 decode(client_caps, p);
128 msg = (PaxosServiceMessage *)decode_message(NULL, 0, p);
129 decode(con_features, p);
130 decode(entity_name, p);
131 }
132
133 PaxosServiceMessage *claim_message() {
134 // let whoever is claiming the message deal with putting it.
135 ceph_assert(msg);
136 msg_desc = stringify(*msg);
137 PaxosServiceMessage *m = msg;
138 msg = NULL;
139 return m;
140 }
141
142 std::string_view get_type_name() const override { return "forward"; }
143 void print(ostream& o) const override {
144 o << "forward(";
145 if (msg) {
146 o << *msg;
147 } else {
148 o << msg_desc;
149 }
150 o << " caps " << client_caps
151 << " tid " << tid
152 << " con_features " << con_features << ")";
153 }
154 };
155
156 #endif