blob: 887bcc38384d3f3d744c1c3b4f108c65133bf716 [file]
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef ROCKETMQ_PROTOCOL_TOPICROUTEDATA_HPP_
#define ROCKETMQ_PROTOCOL_TOPICROUTEDATA_HPP_
#include <json/json.h>
#include <algorithm>
#include <cstdlib>
#include <memory>
#include "ByteArray.h"
#include "Logging.h"
#include "RemotingSerializable.h"
#include "UtilAll.h"
namespace rocketmq {
class QueueData {
public:
QueueData() : read_queue_nums_(16), write_queue_nums_(16), perm_(6) {}
QueueData(const std::string& broker_name, int read_queue_nums, int write_queue_nums, int perm)
: broker_name_(broker_name),
read_queue_nums_(read_queue_nums),
write_queue_nums_(write_queue_nums),
perm_(perm) {}
QueueData(std::string&& broker_name, int read_queue_nums, int write_queue_nums, int perm)
: broker_name_(std::move(broker_name)),
read_queue_nums_(read_queue_nums),
write_queue_nums_(write_queue_nums),
perm_(perm) {}
bool operator<(const QueueData& other) const { return broker_name_ < other.broker_name_; }
bool operator==(const QueueData& other) const {
return broker_name_ == other.broker_name_ && read_queue_nums_ == other.read_queue_nums_ &&
write_queue_nums_ == other.write_queue_nums_ && perm_ == other.perm_;
}
bool operator!=(const QueueData& other) const { return !operator==(other); }
public:
inline const std::string& broker_name() const { return broker_name_; }
inline void broker_name(const std::string& broker_name) { broker_name_ = broker_name; }
inline int read_queue_nums() const { return read_queue_nums_; }
inline void set_read_queue_nums(int read_queue_nums) { read_queue_nums_ = read_queue_nums; }
inline int write_queue_nums() const { return write_queue_nums_; }
inline void set_write_queue_nums(int write_queue_nums) { write_queue_nums_ = write_queue_nums; }
inline int perm() const { return perm_; }
inline void set_perm(int perm) { perm_ = perm; }
private:
std::string broker_name_;
int read_queue_nums_;
int write_queue_nums_;
int perm_;
};
class BrokerData {
public:
BrokerData();
BrokerData(const std::string& broker_name) : broker_name_(broker_name) {}
BrokerData(std::string&& broker_name) : broker_name_(std::move(broker_name)) {}
BrokerData(const std::string& broker_name, const std::map<int, std::string>& broker_addrs)
: broker_name_(broker_name), broker_addrs_(broker_addrs) {}
BrokerData(std::string&& broker_name, std::map<int, std::string>&& broker_addrs)
: broker_name_(std::move(broker_name)), broker_addrs_(std::move(broker_addrs)) {}
bool operator<(const BrokerData& other) const { return broker_name_ < other.broker_name_; }
bool operator==(const BrokerData& other) const {
return broker_name_ == other.broker_name_ && broker_addrs_ == other.broker_addrs_;
}
bool operator!=(const BrokerData& other) const { return !operator==(other); }
public:
inline const std::string& broker_name() const { return broker_name_; }
inline void broker_name(const std::string& broker_name) { broker_name_ = broker_name; }
inline const std::map<int, std::string>& broker_addrs() const { return broker_addrs_; }
inline std::map<int, std::string>& broker_addrs() { return broker_addrs_; }
private:
std::string broker_name_;
std::map<int, std::string> broker_addrs_; // master:0; slave:1,2,3,etc.
};
class TopicRouteData;
typedef std::shared_ptr<TopicRouteData> TopicRouteDataPtr;
class TopicRouteData {
public:
static std::unique_ptr<TopicRouteData> Decode(const ByteArray& bodyData) {
Json::Value root = RemotingSerializable::fromJson(bodyData);
std::unique_ptr<TopicRouteData> trd(new TopicRouteData());
trd->set_order_topic_conf(root["orderTopicConf"].asString());
auto& qds = root["queueDatas"];
for (auto qd : qds) {
trd->queue_datas().emplace_back(qd["brokerName"].asString(), qd["readQueueNums"].asInt(),
qd["writeQueueNums"].asInt(), qd["perm"].asInt());
}
sort(trd->queue_datas().begin(), trd->queue_datas().end());
auto& bds = root["brokerDatas"];
for (auto bd : bds) {
std::string broker_name = bd["brokerName"].asString();
LOG_DEBUG_NEW("brokerName:{}", broker_name);
auto& bas = bd["brokerAddrs"];
Json::Value::Members members = bas.getMemberNames();
std::map<int, std::string> broker_addrs;
for (const auto& member : members) {
int id = std::stoi(member);
std::string addr = bas[member].asString();
broker_addrs.emplace(id, std::move(addr));
LOG_DEBUG_NEW("brokerId:{}, brokerAddr:{}", id, addr);
}
trd->broker_datas().emplace_back(std::move(broker_name), std::move(broker_addrs));
}
sort(trd->broker_datas().begin(), trd->broker_datas().end());
return trd;
}
/**
* Selects a (preferably master) broker address from the registered list.
* If the master's address cannot be found, a slave broker address is selected in a random manner.
*
* @return Broker address.
*/
std::string selectBrokerAddr() {
auto bdSize = broker_datas_.size();
if (bdSize > 0) {
auto bdIndex = std::rand() % bdSize;
const auto& bd = broker_datas_[bdIndex];
const auto& broker_addrs = bd.broker_addrs();
auto it = broker_addrs.find(MASTER_ID);
if (it == broker_addrs.end()) {
auto baSize = broker_addrs.size();
auto baIndex = std::rand() % baSize;
for (it = broker_addrs.begin(); baIndex > 0; baIndex--) {
it++;
}
}
return it->second;
}
return null;
}
bool operator==(const TopicRouteData& other) const {
return broker_datas_ == other.broker_datas_ && order_topic_conf_ == other.order_topic_conf_ &&
queue_datas_ == other.queue_datas_;
}
bool operator!=(const TopicRouteData& other) const { return !operator==(other); }
public:
inline const std::string& order_topic_conf() const { return order_topic_conf_; }
inline void set_order_topic_conf(const std::string& orderTopicConf) { order_topic_conf_ = orderTopicConf; }
inline std::vector<QueueData>& queue_datas() { return queue_datas_; }
inline std::vector<BrokerData>& broker_datas() { return broker_datas_; }
private:
std::string order_topic_conf_;
std::vector<QueueData> queue_datas_;
std::vector<BrokerData> broker_datas_;
};
} // namespace rocketmq
#endif // ROCKETMQ_PROTOCOL_TOPICROUTEDATA_HPP_