struct MForward : public Message {
uint64_t tid;
- PaxosServiceMessage *msg;
entity_inst_t client;
MonCap client_caps;
uint64_t con_features;
EntityName entity_name;
+ PaxosServiceMessage *msg; // incoming message
+ bufferlist msg_bl; // outgoing message
static const int HEAD_VERSION = 3;
static const int COMPAT_VERSION = 1;
MForward() : Message(MSG_FORWARD, HEAD_VERSION, COMPAT_VERSION),
- tid(0), msg(NULL), con_features(0) {}
+ tid(0), con_features(0), msg(NULL) {}
//the message needs to have caps filled in!
MForward(uint64_t t, PaxosServiceMessage *m, uint64_t feat) :
Message(MSG_FORWARD, HEAD_VERSION, COMPAT_VERSION),
- tid(t), msg(m) {
+ tid(t), msg(NULL) {
client = m->get_source_inst();
client_caps = m->get_session()->caps;
con_features = feat;
+ set_message(m, feat);
}
MForward(uint64_t t, PaxosServiceMessage *m, uint64_t feat,
- const MonCap& caps) :
+ const MonCap& caps) :
Message(MSG_FORWARD, HEAD_VERSION, COMPAT_VERSION),
- tid(t), msg(m), client_caps(caps) {
+ tid(t), client_caps(caps), msg(NULL) {
client = m->get_source_inst();
con_features = feat;
+ set_message(m, feat);
}
private:
~MForward() {
- if (msg) msg->put();
+ if (msg) {
+ // message was unclaimed
+ msg->put();
+ msg = NULL;
+ }
+ }
+
+ PaxosServiceMessage *get_msg_from_bl() {
+ bufferlist::iterator p = msg_bl.begin();
+ return (msg_bl.length() ?
+ (PaxosServiceMessage*)decode_message(NULL, 0, p) : NULL);
}
public:
::encode(tid, payload);
::encode(client, payload);
::encode(client_caps, payload, features);
- encode_message(msg, features, payload);
+ payload.append(msg_bl);
::encode(con_features, payload);
::encode(entity_name, payload);
}
}
+ void set_message(PaxosServiceMessage *m, uint64_t features) {
+ encode_message(m, features, msg_bl);
+
+ // keep a pointer to the message. We will not use it except for print(),
+ // and we will drop it in the dtor if it is not claimed.
+ // we could avoid doing this if only we had a const bufferlist iterator :)
+ msg = m;
+ }
+
+ PaxosServiceMessage *claim_message() {
+ if (!msg) {
+ return get_msg_from_bl();
+ }
+
+ PaxosServiceMessage *m = msg;
+ msg = NULL;
+ return m;
+ }
+
const char *get_type_name() const { return "forward"; }
void print(ostream& o) const {
- if (msg)
+ if (msg) {
o << "forward(" << *msg << " caps " << client_caps
<< " tid " << tid
<< " con_features " << con_features << ") to leader";
- else o << "forward(??? ) to leader";
+ } else {
+ o << "forward(??? ) to leader";
+ }
}
};
dout(10) << "forward_request " << rr->tid << " request " << *req
<< " features " << rr->con_features << dendl;
- MForward *forward = new MForward(rr->tid, req,
+ MForward *forward = new MForward(rr->tid,
+ req,
rr->con_features,
rr->session->caps);
forward->set_priority(req->get_priority());
} else {
// see PaxosService::dispatch(); we rely on this being anon
// (c->msgr == NULL)
+ PaxosServiceMessage *req = m->claim_message();
+ assert(req != NULL);
+
ConnectionRef c(new AnonConnection(cct));
- MonSession *s = new MonSession(m->msg->get_source_inst(),
+ MonSession *s = new MonSession(req->get_source_inst(),
static_cast<Connection*>(c.get()));
c->set_priv(s->get());
c->set_peer_addr(m->client.addr);
s->proxy_con = m->get_connection();
s->proxy_tid = m->tid;
- PaxosServiceMessage *req = m->msg;
- m->msg = NULL; // so ~MForward doesn't delete it
req->set_connection(c);
// not super accurate, but better than nothing.