// Copyright (c) 2023, 2024, Oracle and/or its affiliates. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License, version 2.0, // as published by the Free Software Foundation. // // This program is designed to work with certain software (including // but not limited to OpenSSL) that is licensed under separate terms, // as designated in a particular file or component or in included license // documentation. The authors of MySQL hereby grant you an additional // permission to link the program and your derivative works with the // separately licensed software that they have either included with // the program or referenced in the documentation. // // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License, version 2.0, for more details. // // You should have received a copy of the GNU General Public License // along with this program; if not, write to the Free Software // Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA #ifndef MYSQL_GTID_TSID_H #define MYSQL_GTID_TSID_H #include "mysql/gtid/gtid_constants.h" #include "mysql/gtid/gtid_format.h" #include "mysql/gtid/tag.h" #include "mysql/gtid/tsid_plain.h" #include "mysql/gtid/uuid.h" /// @addtogroup GroupLibsMysqlGtid /// @{ namespace mysql::gtid { class Tsid; /// @brief Maximum TSID text length (without null character) inline constexpr auto tsid_max_length = Uuid::TEXT_LENGTH + 1 + tag_max_length; struct Tsid_plain; /// @brief Represents Transaction Source Identifier which is composed of source /// UUID and transaction tag. Transaction tag may be empty. class Tsid { public: /// @brief Constructs TSID from a given uuid and a tag /// @param[in] uuid UUID component /// @param[in] tag Tag component Tsid(const Uuid &uuid, const Tag &tag); /// @brief Constructs TSID from a given uuid, tag is empty /// @param[in] uuid UUID component Tsid(const Uuid &uuid); /// @brief Construct from Tsid_plain object /// @param arg Source to copy from explicit Tsid(const Tsid_plain &arg); /// @brief Constructs empty TSID Tsid() = default; Tsid(Tsid const &) = default; Tsid(Tsid &&) = default; Tsid &operator=(Tsid const &) = default; Tsid &operator=(Tsid &&) = default; /// @brief Returns textual representation of Transaction Source Identifier std::string to_string() const; /// @brief Obtains textual representation of TSID and writes it to out /// @param [out] out Output string /// @returns Number of characters written to out std::size_t to_string(char *out) const; /// @brief Obtains textual representation of TSID and writes it to out /// @details version with a custom tag-sid separator /// @param [out] out Output string /// @param [in] tag_sid_separator Tag-sid separator /// @returns Number of characters written to out std::size_t to_string(char *out, const char *tag_sid_separator) const; /// @brief Fills Tsid with data from text /// @param[in] text Encoded TSID representation terminated with null sign, /// GTID separator or UUID set separator if part of the GTID set encoding /// @return The number of bytes read, or 0 on error [[NODISCARD]] std::size_t from_cstring(const char *text); /// @brief Default TSID separator static constexpr auto tsid_separator = ":"; /// @brief Operator == /// @param other pattern to compare against /// @return Result of comparison == bool operator==(const Tsid &other) const; /// @brief Operator != /// @param other pattern to compare against /// @return Result of comparison != bool operator!=(const Tsid &other) const; /// @brief Operator < /// @details Compares uuid first. If uuids are equal, compares tags /// @param other pattern to compare against /// @return Result of comparison this < other bool operator<(const Tsid &other) const; /// @brief Tag accessor /// @return Const reference to Tag object const Tag &get_tag() const { return m_tag; } /// @brief Tag accessor, non const (serialization) /// @return Non-const Reference to Tag object Tag &get_tag_ref() { return m_tag; } /// @brief Sets internal tag to a given tag object /// @param tag Source to copy from void set_tag(const Tag &tag) { m_tag = tag; } /// @brief UUID accessor /// @return Const reference to UUID component of TSID const Uuid &get_uuid() const { return m_uuid; } /// @brief Non const getter is needed in some functions (copy data) /// @returns Reference to internal UUID Uuid &get_uuid() { return m_uuid; } /// @brief Checks whether this TSID contains tag /// @retval true This TSID contains tag /// @retval false This TSID contains empty tag bool is_tagged() const { return m_tag.is_defined(); } /// @brief Structure to compute hash function of a given Tag object struct Hash { /// @brief Computes hash of a given Tsid object /// @param arg Object handle for which hash will be calculated size_t operator()(const Tsid &arg) const { return Uuid_hash{}(arg.m_uuid) ^ Tag::Hash{}(arg.m_tag); } }; friend struct Hash; /// @brief Clears data - uuid and tag void clear(); /// @brief Obtains maximum length of encoded TSID (compile time) /// @return Maximum length of encoded tag in bytes static constexpr std::size_t get_max_encoded_length() { return Uuid::BYTE_LENGTH + Tag::get_max_encoded_length(); } /// @brief stores TSID in buffer /// @param buf Buffer to store bytes /// @return the number of bytes written into the buf /// @param gtid_format Format of encoded GTID. If tag is not defined for this /// GTID and tagged format is used, 0 will be encoded as length of the string. /// In case "untagged" format is requested, function won't encode additional /// tag information for untagged GTIDs. When using /// untagged, tag is required to be empty. std::size_t encode_tsid(unsigned char *buf, const Gtid_format >id_format) const; /// @brief reads TSID from the buffer /// @param stream Stream to read tsid from /// @param stream_len Length of the stream /// @param gtid_format Gtid format expected in the stream /// @return The number of bytes read or 0. 0 means that an error occurred /// (e.g. not enough bytes in the buffer to read the /// tsid - corrupted bytes in the buffer). [[NODISCARD]] std::size_t decode_tsid(const unsigned char *stream, std::size_t stream_len, const Gtid_format >id_format); private: Uuid m_uuid = {0}; ///< GTID UUID Tag m_tag; ///< GTID Tag }; } // namespace mysql::gtid /// @} #endif // MYSQL_GTID_TSID_H