| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159 | 
							- // Copyright Takatoshi Kondo 2020
 
- //
 
- // Distributed under the Boost Software License, Version 1.0.
 
- // (See accompanying file LICENSE_1_0.txt or copy at
 
- // http://www.boost.org/LICENSE_1_0.txt)
 
- #if !defined(MQTT_TOPIC_ALIAS_SEND_HPP)
 
- #define MQTT_TOPIC_ALIAS_SEND_HPP
 
- #include <string>
 
- #include <unordered_map>
 
- #include <array>
 
- #include <boost/multi_index_container.hpp>
 
- #include <boost/multi_index/ordered_index.hpp>
 
- #include <boost/multi_index/member.hpp>
 
- #include <boost/multi_index/mem_fun.hpp>
 
- #include <mqtt/namespace.hpp>
 
- #include <mqtt/string_view.hpp>
 
- #include <mqtt/constant.hpp>
 
- #include <mqtt/type.hpp>
 
- #include <mqtt/move.hpp>
 
- #include <mqtt/log.hpp>
 
- #include <mqtt/time_point_t.hpp>
 
- #include <mqtt/optional.hpp>
 
- #include <mqtt/value_allocator.hpp>
 
- namespace MQTT_NS {
 
- namespace mi = boost::multi_index;
 
- class topic_alias_send {
 
- public:
 
-     topic_alias_send(topic_alias_t max)
 
-         :max_{max}, va_{min_, max_} {}
 
-     void insert_or_update(string_view topic, topic_alias_t alias) {
 
-         MQTT_LOG("mqtt_impl", trace)
 
-             << MQTT_ADD_VALUE(address, this)
 
-             << "topic_alias_send insert"
 
-             << " topic:" << topic
 
-             << " alias:" << alias;
 
-         BOOST_ASSERT(!topic.empty() && alias >= min_ && alias <= max_);
 
-         va_.use(alias);
 
-         auto& idx = aliases_.get<tag_alias>();
 
-         auto it = idx.lower_bound(alias);
 
-         if (it == idx.end() || it->alias != alias) {
 
-             idx.emplace_hint(it, std::string(topic), alias, std::chrono::steady_clock::now());
 
-         }
 
-         else {
 
-             idx.modify(
 
-                 it,
 
-                 [&](entry& e) {
 
-                     e.topic = std::string{topic};
 
-                     e.tp = std::chrono::steady_clock::now();
 
-                 },
 
-                 [](auto&) { BOOST_ASSERT(false); }
 
-             );
 
-         }
 
-     }
 
-     std::string find(topic_alias_t alias) {
 
-         MQTT_LOG("mqtt_impl", trace)
 
-             << MQTT_ADD_VALUE(address, this)
 
-             << "find_topic_by_alias"
 
-             << " alias:" << alias;
 
-         BOOST_ASSERT(alias >= min_ && alias <= max_);
 
-         auto& idx = aliases_.get<tag_alias>();
 
-         auto it = idx.find(alias);
 
-         if (it == idx.end()) return std::string();
 
-         idx.modify(
 
-             it,
 
-             [&](entry& e) {
 
-                 e.tp = std::chrono::steady_clock::now();
 
-             },
 
-             [](auto&) { BOOST_ASSERT(false); }
 
-         );
 
-         return it->topic;
 
-     }
 
-     optional<topic_alias_t> find(string_view topic) const {
 
-         MQTT_LOG("mqtt_impl", trace)
 
-             << MQTT_ADD_VALUE(address, this)
 
-             << "find_alias_by_topic"
 
-             << " topic:" << topic;
 
-         auto& idx = aliases_.get<tag_topic_name>();
 
-         auto it = idx.find(topic);
 
-         if (it == idx.end()) return nullopt;
 
-         return it->alias;
 
-     }
 
-     void clear() {
 
-         MQTT_LOG("mqtt_impl", info)
 
-             << MQTT_ADD_VALUE(address, this)
 
-             << "clear_topic_alias";
 
-         aliases_.clear();
 
-         va_.clear();
 
-     }
 
-     topic_alias_t get_lru_alias() const {
 
-         BOOST_ASSERT(max_ > 0);
 
-         if (auto alias_opt = va_.first_vacant()) {
 
-             return alias_opt.value();
 
-         }
 
-         auto& idx = aliases_.get<tag_tp>();
 
-         return idx.begin()->alias;
 
-     }
 
-     topic_alias_t max() const { return max_; }
 
- private:
 
-     static constexpr topic_alias_t min_ = 1;
 
-     topic_alias_t max_;
 
-     struct entry {
 
-         entry(std::string topic, topic_alias_t alias, time_point_t tp)
 
-             : topic{force_move(topic)}, alias{alias}, tp{force_move(tp)} {}
 
-         string_view get_topic_as_view() const {
 
-             return topic;
 
-         }
 
-         std::string topic;
 
-         topic_alias_t alias;
 
-         time_point_t tp;
 
-     };
 
-     struct tag_tp {};
 
-     struct tag_alias {};
 
-     struct tag_topic_name {};
 
-     using mi_topic_alias = mi::multi_index_container<
 
-         entry,
 
-         mi::indexed_by<
 
-             mi::ordered_unique<
 
-                 mi::tag<tag_alias>,
 
-                 BOOST_MULTI_INDEX_MEMBER(entry, topic_alias_t, alias)
 
-             >,
 
-             mi::ordered_unique<
 
-                 mi::tag<tag_topic_name>,
 
-                 BOOST_MULTI_INDEX_CONST_MEM_FUN(entry, string_view, get_topic_as_view)
 
-             >,
 
-             mi::ordered_non_unique<
 
-                 mi::tag<tag_tp>,
 
-                 BOOST_MULTI_INDEX_MEMBER(entry, time_point_t, tp)
 
-             >
 
-         >
 
-     >;
 
-     mi_topic_alias aliases_;
 
-     value_allocator<topic_alias_t> va_;
 
- };
 
- } // namespace MQTT_NS
 
- #endif // MQTT_TOPIC_ALIAS_SEND_HPP
 
 
  |