/* * Copyright (c) 2019 MariaDB Corporation Ab * * Use of this software is governed by the Business Source License included * in the LICENSE.TXT file and at www.mariadb.com/bsl11. * * Change Date: 2022-01-01 * * On the date above, in accordance with the Business Source License, use * of this software will be governed by version 2 or later of the General * Public License. */ #pragma once #include "smartrouter.hh" #include #include #include #include class SmartRouter; /** Currently SmartRouter is configured like this (star means many): * SmartRouter -*> ServerAsService -> MaxscaleRouter -*> Server * For the time being the limitation is that the tail router must be RWSplit. * This will change once we implement it so that SmartRouter can call the tail router directly. * Although the assumption is one RowServer and one ColumnServer, the code does not assume that, * it simply forces you to state which Cluster is the master. * Currently SmartRouter fails if any Cluster fails. That need not be the case, Clusters could * be marked "is_critical" meaning non-crititcal non-masters, could be allowed to fail. */ class SmartRouterSession : public mxs::RouterSession, private mxs::QueryClassifier::Handler { public: static SmartRouterSession* create(SmartRouter* pRouter, MXS_SESSION* pSession); virtual ~SmartRouterSession(); SmartRouterSession(const SmartRouterSession&) = delete; SmartRouterSession& operator=(const SmartRouterSession&) = delete; int routeQuery(GWBUF* pBuf); void close(); void clientReply(GWBUF* pPacket, DCB* pDcb); void handleError(GWBUF* pPacket, DCB* pProblem, mxs_error_action_t action, bool* pSuccess); private: enum class Mode {Idle, Query, CollectResults}; // MeasureQuery /** struct Cluster represents a cluster of mariadb servers as a Maxscale internal Server. * TODO In the next iteration a directly callable "Thing" should be implemented (Router, Backend * Server - the terms are overused and confusing, maybe a new thing called MariaDB). */ struct Cluster { Cluster(SERVER_REF* b, DCB* pDcb, bool is_master) : host {b->server->address, b->server->port} , pBackend(b) , pDcb(pDcb) , is_master(is_master) { } Cluster(const Cluster&) = delete; Cluster& operator=(const Cluster&) = delete; Cluster(Cluster&&) = default; Cluster& operator=(Cluster&&) = default; maxbase::Host host; SERVER_REF* pBackend; DCB* pDcb; bool is_master; bool is_replying_to_client; maxsql::PacketTracker tracker; }; using Clusters = std::vector; SmartRouterSession(SmartRouter*, MXS_SESSION* pSession, Clusters clusters); std::vector hosts() const; // The write functions initialize Cluster flags and Cluster::ProtocolTracker. bool write_to_host(const maxbase::Host& host, GWBUF* pBuf); bool write_to_master(GWBUF* pBuf); bool write_to_all(GWBUF* pBuf); bool write_split_packets(GWBUF* pBuf); bool expecting_request_packets() const; bool expecting_response_packets() const; bool all_clusters_are_idle() const; // no clusters expect packets // QueryClassifier::Handler overrides, not used. bool lock_to_master() override; bool is_locked_to_master() const override; bool supports_hint(HINT_TYPE hint_type) const override; Mode m_mode = Mode::Idle; GWBUF* m_pDelayed_packet = nullptr; DCB* m_pClient_dcb; Clusters m_clusters; mxs::QueryClassifier m_qc; };