254 lines
		
	
	
		
			9.3 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
			
		
		
	
	
			254 lines
		
	
	
		
			9.3 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
| /**
 | |
|  * Copyright (c) 2021 OceanBase
 | |
|  * OceanBase CE is licensed under Mulan PubL v2.
 | |
|  * You can use this software according to the terms and conditions of the Mulan PubL v2.
 | |
|  * You may obtain a copy of Mulan PubL v2 at:
 | |
|  *          http://license.coscl.org.cn/MulanPubL-2.0
 | |
|  * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
 | |
|  * EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
 | |
|  * MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
 | |
|  * See the Mulan PubL v2 for more details.
 | |
|  */
 | |
| 
 | |
| #ifndef OCEANBASE_SQL_OB_ROUTE_POLICY_H
 | |
| #define OCEANBASE_SQL_OB_ROUTE_POLICY_H
 | |
| #include "share/ob_define.h"
 | |
| #include "lib/net/ob_addr.h"
 | |
| #include "lib/container/ob_iarray.h"
 | |
| #include "lib/list/ob_list.h"
 | |
| #include "common/ob_zone_status.h"
 | |
| #include "common/ob_zone_type.h"
 | |
| #include "share/location_cache/ob_location_struct.h"
 | |
| #include "share/partition_table/ob_partition_location.h"
 | |
| #include "share/ob_server_locality_cache.h"
 | |
| #include "share/ob_server_status.h"
 | |
| namespace oceanbase
 | |
| {
 | |
| namespace sql
 | |
| {
 | |
| class ObCandiTabletLoc;
 | |
| class ObCandiTableLoc;
 | |
| enum ObRoutePolicyType
 | |
| {
 | |
|   INVALID_POLICY = 0,
 | |
|   READONLY_ZONE_FIRST = 1,
 | |
|   ONLY_READONLY_ZONE = 2,
 | |
|   UNMERGE_ZONE_FIRST = 3,
 | |
|   // 仅在非读写分离场景中有效, server端的路由规则和非读写分离下普通弱读相同,
 | |
|   // 即使客户端将请求路由到partition主上, 也在本地执行,
 | |
|   // 区别在于返回给OCJ && ObProxy的反馈不同;
 | |
|   UNMERGE_FOLLOWER_FIRST = 4,
 | |
|   POLICY_TYPE_MAX
 | |
| };
 | |
| 
 | |
| struct ObRoutePolicyCtx
 | |
| {
 | |
|   ObRoutePolicyCtx()
 | |
|     :policy_type_(POLICY_TYPE_MAX),
 | |
|      consistency_level_(common::INVALID_CONSISTENCY),
 | |
|      is_proxy_priority_hit_support_(false),
 | |
|      tenant_id_(OB_INVALID_TENANT_ID),
 | |
|      max_read_stale_time_(0)
 | |
|    {}
 | |
| 
 | |
|   TO_STRING_KV(K(policy_type_),
 | |
|                K(consistency_level_),
 | |
|                K(is_proxy_priority_hit_support_),
 | |
|                K(tenant_id_),
 | |
|                K(max_read_stale_time_));
 | |
| 
 | |
|   ObRoutePolicyType policy_type_;
 | |
|   common::ObConsistencyLevel consistency_level_;
 | |
|   bool is_proxy_priority_hit_support_;
 | |
|   uint64_t tenant_id_;
 | |
|   int64_t max_read_stale_time_;
 | |
| };
 | |
| 
 | |
| class ObRoutePolicy
 | |
| {
 | |
| public:
 | |
|   enum PositionType
 | |
|   {
 | |
|     SAME_SERVER = 0,
 | |
|     SAME_IDC = 1,
 | |
|     SAME_REGION = 2,
 | |
|     OTHER_REGION = 3,
 | |
|     POSITION_TYPE_MAX,
 | |
|   };
 | |
|   enum MergeStatus
 | |
|   {
 | |
|     MERGING,
 | |
|     NOMERGING,
 | |
|     MERGE_STATUS_MAX,
 | |
|   };
 | |
|   class ReplicaAttribute
 | |
|   {
 | |
|   public:
 | |
|   ReplicaAttribute()
 | |
|       :pos_type_(POSITION_TYPE_MAX),
 | |
|         merge_status_(MERGE_STATUS_MAX),
 | |
|         zone_status_(share::ObZoneStatus::UNKNOWN),
 | |
|         zone_type_(common::ZONE_TYPE_INVALID),
 | |
|         start_service_time_(0),
 | |
|         server_stop_time_(0),
 | |
|         server_status_(share::ObServerStatus::OB_DISPLAY_MAX)
 | |
|         {}
 | |
|     ~ReplicaAttribute(){}
 | |
|     bool operator==(const ReplicaAttribute &other_attr) const
 | |
|     {
 | |
|       bool bool_ret = false;
 | |
|       if (merge_status_ == other_attr.merge_status_
 | |
|           && zone_type_ == other_attr.zone_type_) {
 | |
|         if (pos_type_ == SAME_SERVER) {
 | |
|           bool_ret = (other_attr.pos_type_ == SAME_SERVER || other_attr.pos_type_ == SAME_IDC);
 | |
|         } else if (pos_type_ == SAME_IDC) {
 | |
|           bool_ret = (other_attr.pos_type_ == SAME_SERVER || other_attr.pos_type_ == SAME_IDC);
 | |
|         } else {
 | |
|           bool_ret = (pos_type_ == other_attr.pos_type_);
 | |
|         }
 | |
|       }
 | |
|       return bool_ret;
 | |
|     }
 | |
|     void reset()
 | |
|     {
 | |
|       pos_type_ = POSITION_TYPE_MAX;
 | |
|       merge_status_ = MERGE_STATUS_MAX;
 | |
|       zone_status_ = share::ObZoneStatus::UNKNOWN;
 | |
|       zone_type_ = common::ZONE_TYPE_INVALID;
 | |
|       start_service_time_ = 0;
 | |
|       server_stop_time_ = 0;
 | |
|       server_status_ = share::ObServerStatus::OB_DISPLAY_MAX;
 | |
|     }
 | |
|     TO_STRING_KV(K(pos_type_), K(merge_status_), K(zone_type_), K(zone_status_), K(start_service_time_), K(server_stop_time_), K(server_status_));
 | |
|     PositionType pos_type_;
 | |
|     MergeStatus merge_status_;
 | |
|     share::ObZoneStatus::Status zone_status_;
 | |
|     common::ObZoneType zone_type_;
 | |
|     int64_t start_service_time_;
 | |
|     int64_t server_stop_time_;
 | |
|     share::ObServerStatus::DisplayStatus server_status_;
 | |
|   };
 | |
|   class CandidateReplica final : public share::ObLSReplicaLocation
 | |
|   {
 | |
|   public:
 | |
|     CandidateReplica()
 | |
|       : ObLSReplicaLocation(),
 | |
|         attr_(),
 | |
|         is_filter_(false),
 | |
|         replica_idx_(common::OB_INVALID_INDEX)
 | |
|     {}
 | |
|    CandidateReplica(const share::ObLSReplicaLocation &replica_location)
 | |
|       : ObLSReplicaLocation(replica_location),
 | |
|         attr_(),
 | |
|         is_filter_(false),
 | |
|         replica_idx_(common::OB_INVALID_INDEX)
 | |
|     {}
 | |
|     bool is_usable() const { return is_filter_ == false; }
 | |
|     void reset()
 | |
|     {
 | |
|       ObLSReplicaLocation::reset();
 | |
|       attr_.reset();
 | |
|       is_filter_ = false;
 | |
|     }
 | |
|     int assign(CandidateReplica &other);
 | |
|     //to_string only outputs the key information that SQL execution is concerned with,
 | |
|     //and other information can be obtained through the corresponding virtual tables.
 | |
|     TO_STRING_KV(K_(server),
 | |
|                  K_(role),
 | |
|                  K_(sql_port),
 | |
|                  K_(is_filter));
 | |
|   public:
 | |
|     ReplicaAttribute attr_;
 | |
|     bool is_filter_;
 | |
|     int64_t replica_idx_;//invalid
 | |
|   };
 | |
| public:
 | |
|   ObRoutePolicy(const common::ObAddr &addr)
 | |
|       :local_addr_(addr),
 | |
|       local_locality_(),
 | |
|       server_locality_array_(),
 | |
|       has_refresh_locality_(false),
 | |
|       has_readonly_zone_(false),
 | |
|       is_inited_(false)
 | |
|   {}
 | |
|   ~ObRoutePolicy() {}
 | |
|   int init();
 | |
|   int calculate_replica_priority(const ObAddr &local_server,
 | |
|                                  const share::ObLSID &ls_id,
 | |
|                                  common::ObIArray<CandidateReplica>& candi_replicas,
 | |
|                                  ObRoutePolicyCtx &ctx);
 | |
|   int init_candidate_replicas(common::ObIArray<CandidateReplica> &candi_replicas);
 | |
|   int select_replica_with_priority(const ObRoutePolicyCtx &route_policy_ctx,
 | |
|                                    const common::ObIArray<CandidateReplica> &replica_array,
 | |
|                                    ObCandiTabletLoc &phy_part_loc_info);
 | |
|   int select_intersect_replica(ObRoutePolicyCtx &route_policy_ctx,
 | |
|                                common::ObIArray<ObCandiTableLoc*> &phy_tbl_loc_info_list,
 | |
|                                common::ObList<ObRoutePolicy::CandidateReplica, common::ObArenaAllocator> &intersect_server_list,
 | |
|                                bool &is_proxy_hit);
 | |
| 
 | |
|   TO_STRING_KV(K(local_addr_),
 | |
|                K(local_locality_),
 | |
|                K(server_locality_array_),
 | |
|                K(has_refresh_locality_),
 | |
|                K(has_readonly_zone_),
 | |
|                K(is_inited_));
 | |
| 
 | |
|   inline bool is_follower_first_route_policy_type(const ObRoutePolicyCtx &ctx) const
 | |
|   {
 | |
|     return !has_readonly_zone_ && (UNMERGE_FOLLOWER_FIRST == ctx.policy_type_);
 | |
|   }
 | |
| 
 | |
|   static int get_server_locality(const common::ObAddr &addr,
 | |
|                                  const common::ObIArray<share::ObServerLocality> &server_locality_array,
 | |
|                                  share::ObServerLocality &svr_locality);
 | |
|   static bool is_same_idc(const share::ObServerLocality &locality1,
 | |
|                           const share::ObServerLocality &locality2);
 | |
|   static bool is_same_region(const share::ObServerLocality &locality1,
 | |
|                              const share::ObServerLocality &locality2);
 | |
| 
 | |
| protected:
 | |
|   int init_candidate_replica(const common::ObIArray<share::ObServerLocality> &server_locality_array,
 | |
|                              CandidateReplica &candi_replica);
 | |
|   int calc_position_type(const share::ObServerLocality &candi_locality,
 | |
|                          CandidateReplica &candi_replica);
 | |
|   int calc_intersect_repllica(const common::ObIArray<ObCandiTableLoc*> &phy_tbl_loc_info_list,
 | |
|                               common::ObList<ObRoutePolicy::CandidateReplica, common::ObArenaAllocator> &intersect_server_list);
 | |
|   int get_merge_status(const share::ObServerLocality &candi_locality, CandidateReplica &candi_replica);
 | |
|   int get_zone_status(const share::ObServerLocality &candi_locality, CandidateReplica &candi_replica);
 | |
| 
 | |
|   int filter_replica(const ObAddr &local_server,
 | |
|                      const share::ObLSID &ls_id,
 | |
|                      common::ObIArray<CandidateReplica>& candi_replicas,
 | |
|                      ObRoutePolicyCtx &ctx);
 | |
|   int weak_sort_replicas(common::ObIArray<CandidateReplica>& candi_replicas, ObRoutePolicyCtx &ctx);
 | |
|   int strong_sort_replicas(common::ObIArray<CandidateReplica>& candi_replicas, ObRoutePolicyCtx &ctx);
 | |
|   inline ObRoutePolicyType get_calc_route_policy_type(const ObRoutePolicyCtx &ctx) const
 | |
|   {
 | |
|     // 集群为读写zone时,忽略ob_route_policy系统变量的值,按照READONLY_ZONE_FIRST处理
 | |
|     // 集群为读写zone时, 且ob_route_policy为UNMERGE_FOLLOWER_FIRST时,同样按照READONLY_ZONE_FIRST处理, 但会增加反馈内容
 | |
|     // 集群为有只读zone时,且ob_route_policy为UNMERGE_FOLLOWER_FIRST时, 同样按照READONLY_ZONE_FIRST处理,此时不会增加反馈内容
 | |
|     ObRoutePolicyType type = INVALID_POLICY;
 | |
|     if (has_readonly_zone_) {
 | |
|       if (UNMERGE_FOLLOWER_FIRST == ctx.policy_type_) {
 | |
|         type = READONLY_ZONE_FIRST;
 | |
|       } else {
 | |
|         type = ctx.policy_type_;
 | |
|       }
 | |
|     } else {
 | |
|       type = READONLY_ZONE_FIRST;
 | |
|     }
 | |
|     return type;
 | |
|   }
 | |
| protected:
 | |
|   common::ObAddr local_addr_;
 | |
|   share::ObServerLocality local_locality_;
 | |
|   common::ObSEArray<share::ObServerLocality, 32> server_locality_array_;
 | |
|   bool has_refresh_locality_;
 | |
|   bool has_readonly_zone_;
 | |
|   bool is_inited_;
 | |
| };
 | |
| 
 | |
| }//sql
 | |
| }//oceanbase
 | |
| #endif
 | 
