/** * 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_PLAN_CACHE_OB_PS_CACHE_ #define OCEANBASE_SQL_PLAN_CACHE_OB_PS_CACHE_ #include "lib/hash/ob_hashmap.h" #include "lib/atomic/ob_atomic.h" #include "lib/allocator/page_arena.h" #include "sql/plan_cache/ob_prepare_stmt_struct.h" namespace oceanbase { namespace share { namespace schema { class ObSchemaGetterGuard; } } // namespace share using common::ObPsStmtId; namespace sql { class ObPsCache { public: // sql -> stmt_id typedef common::hash::ObHashMap PsStmtIdMap; // stmt_id -> plan typedef common::hash::ObHashMap PsStmtInfoMap; typedef common::hash::ObHashMap PsSessionInfoMap; typedef common::ObSEArray, 1024> PsIdClosedTimePairs; ObPsCache(); virtual ~ObPsCache(); int init(const int64_t hash_bucket, const common::ObAddr addr, share::ObIPartitionLocationCache* location_cache, const uint64_t tenant_id); bool is_inited() const { return inited_; } bool is_valid() const { return valid_; } void set_valid(bool valid) { valid_ = valid; } int64_t inc_ref_count(); void dec_ref_count(); int64_t get_ref_count() const { return ref_count_; } int set_mem_conf(const ObPCMemPctConf& conf); public: // always make sure stmt_id is inner_stmt_id!!! int get_stmt_info_guard(const ObPsStmtId ps_stmt_id, ObPsStmtInfoGuard& guard); int ref_stmt_item(const uint64_t db_id, const common::ObString& ps_sql, ObPsStmtItem*& stmt_item); int ref_stmt_info(const ObPsStmtId stmt_id, ObPsStmtInfo*& ps_stmt_info); int deref_stmt_info(const ObPsStmtId stmt_id); int deref_all_ps_stmt(const ObIArray& ps_stmt_ids); int ref_stmt_item(const ObPsSqlKey& ps_sql_key, ObPsStmtItem*& ps_stmt_item); int deref_stmt_item(const ObPsSqlKey& ps_sql_key); int ref_ps_stmt(const ObPsStmtId stmt_id); int deref_ps_stmt(const ObPsStmtId stmt_id, bool erase_item = false); int get_or_add_stmt_item(const uint64_t db_id, const common::ObString& ps_sql, ObPsStmtItem*& ps_item_value); int get_or_add_stmt_info(const ObResultSet& result, int64_t param_cnt, ObSchemaGetterGuard& schema_guard, stmt::StmtType stmt_type, ObPsStmtItem* ps_item, ObPsStmtInfo*& ref_ps_info); int cache_evict(); int cache_evict_all_ps(); void dump_ps_cache(); inline void inc_access_count() { ATOMIC_INC(&access_count_); } inline uint64_t get_access_count() { return ATOMIC_LOAD(&access_count_); } inline uint64_t get_hit_count() { return ATOMIC_LOAD(&hit_count_); } inline void inc_access_and_hit_count() { ATOMIC_INC(&hit_count_); ATOMIC_INC(&access_count_); } int mem_total(int64_t& mem_total) const; inline int64_t get_stmt_id_map_size() { return stmt_id_map_.size(); } inline int64_t get_stmt_info_map_size() { return stmt_info_map_.size(); } int get_all_stmt_id(common::ObIArray *id_array); int check_schema_version(ObSchemaGetterGuard &schema_guard, ObPsStmtInfo &stmt_info, bool &is_expired); int erase_stmt_item(ObPsStmtId stmt_id, ObPsSqlKey &ps_key); private: int inner_cache_evict(bool is_evict_all); int fill_ps_stmt_info(const ObResultSet& result, int64_t param_cnt, ObPsStmtInfo& ps_stmt_info) const; int add_stmt_info(const ObPsStmtItem& ps_item, const ObPsStmtInfo& ps_info, ObPsStmtInfo*& ref_ps_info); inline ObPsStmtId gen_new_ps_stmt_id() { return __sync_add_and_fetch(&next_ps_stmt_id_, 1); } int64_t get_mem_limit() const { const double PS_EVICT_PERCENT_ON_PC = 0.5; const int64_t MAX_TENANT_MEM = ((int64_t)(1) << 40); // 1T int64_t tenant_mem = lib::get_tenant_memory_limit(tenant_id_); int64_t mem_limit = -1; if (OB_UNLIKELY(0 >= tenant_mem || tenant_mem >= MAX_TENANT_MEM)) { mem_limit = MAX_TENANT_MEM * PS_EVICT_PERCENT_ON_PC; } mem_limit = tenant_mem / 100 * get_mem_limit_pct() * PS_EVICT_PERCENT_ON_PC; return mem_limit; } int64_t get_mem_high() const { return get_mem_limit() / 100 * get_mem_high_pct(); } inline int64_t get_mem_limit_pct() const { return ATOMIC_LOAD(&mem_limit_pct_); } inline int64_t get_mem_high_pct() const { return ATOMIC_LOAD(&mem_high_pct_); } inline int64_t get_mem_low_pct() const { return ATOMIC_LOAD(&mem_low_pct_); } inline void set_mem_limit_pct(int64_t pct) { ATOMIC_STORE(&mem_limit_pct_, pct); } inline void set_mem_high_pct(int64_t pct) { ATOMIC_STORE(&mem_high_pct_, pct); } inline void set_mem_low_pct(int64_t pct) { ATOMIC_STORE(&mem_low_pct_, pct); } private: static const int64_t SLICE_SIZE = 1024; ObPsStmtId next_ps_stmt_id_; bool inited_; bool valid_; int64_t tenant_id_; common::ObAddr host_; share::ObIPartitionLocationCache* location_cache_; volatile int64_t ref_count_; PsStmtIdMap stmt_id_map_; PsStmtInfoMap stmt_info_map_; int64_t mem_limit_pct_; int64_t mem_high_pct_; // high water mark percentage int64_t mem_low_pct_; // low water mark percentage uint64_t hit_count_; uint64_t access_count_; lib::ObMutex mutex_; lib::MemoryContext mem_context_; common::ObIAllocator* inner_allocator_; }; } // end namespace sql } // end namespace oceanbase #endif // OCEANBASE_SQL_PLAN_CACHE_OB_PS_CACHE_