121 lines
		
	
	
		
			4.0 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
			
		
		
	
	
			121 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: 2024-03-10
 | |
|  *
 | |
|  * 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 <iostream>
 | |
| #include <maxbase/host.hh>
 | |
| #include <maxscale/packet_tracker.hh>
 | |
| #include <maxscale/queryclassifier.hh>
 | |
| 
 | |
| 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;
 | |
| };
 | 
