122 lines
		
	
	
		
			4.0 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
			
		
		
	
	
			122 lines
		
	
	
		
			4.0 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
/*
 | 
						|
 * 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 <maxsql/packet_tracker.hh>
 | 
						|
#include <maxscale/queryclassifier.hh>
 | 
						|
#include <maxbase/host.hh>
 | 
						|
 | 
						|
#include <iostream>
 | 
						|
 | 
						|
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, MeasureQuery, CollectResults};
 | 
						|
 | 
						|
    /** 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<Cluster>;
 | 
						|
 | 
						|
    SmartRouterSession(SmartRouter*, MXS_SESSION* pSession, Clusters clusters);
 | 
						|
 | 
						|
    std::vector<maxbase::Host> 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, Mode mode);
 | 
						|
    bool write_split_packets(GWBUF* pBuf);
 | 
						|
 | 
						|
    void kill_all_others(const Cluster& cluster);
 | 
						|
 | 
						|
    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;
 | 
						|
 | 
						|
    SmartRouter& m_router;
 | 
						|
 | 
						|
    Mode   m_mode = Mode::Idle;
 | 
						|
    GWBUF* m_pDelayed_packet = nullptr;
 | 
						|
 | 
						|
    DCB*                 m_pClient_dcb;
 | 
						|
    Clusters             m_clusters;
 | 
						|
    mxs::QueryClassifier m_qc;
 | 
						|
    struct Measurement
 | 
						|
    {
 | 
						|
        maxbase::TimePoint start;
 | 
						|
        std::string        canonical;
 | 
						|
    };
 | 
						|
    Measurement m_measurement;
 | 
						|
};
 |