192 lines
6.6 KiB
C++
192 lines
6.6 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_USER_RESOURCE_MGR_H_
|
|
#define OCEANBASE_SQL_USER_RESOURCE_MGR_H_
|
|
|
|
#include "lib/hash/ob_link_hashmap.h"
|
|
#include "share/schema/ob_schema_struct.h"
|
|
#include "lib/task/ob_timer.h"
|
|
#include "share/schema/ob_schema_getter_guard.h"
|
|
#include "share/schema/ob_multi_version_schema_service.h"
|
|
|
|
namespace oceanbase {
|
|
namespace sql {
|
|
class ObSQLSessionInfo;
|
|
class ObTenantUserKey {
|
|
public:
|
|
ObTenantUserKey() : tenant_id_(0), user_id_(0)
|
|
{}
|
|
ObTenantUserKey(const uint64_t tenant_id, const uint64_t user_id) :
|
|
tenant_id_(tenant_id), user_id_(user_id)
|
|
{}
|
|
uint64_t hash() const
|
|
{
|
|
return common::murmurhash(&user_id_, sizeof(user_id_), tenant_id_);
|
|
};
|
|
int hash(uint64_t &hash_val) const
|
|
{
|
|
hash_val = hash();
|
|
return OB_SUCCESS;
|
|
};
|
|
int compare(const ObTenantUserKey& r) const
|
|
{
|
|
int cmp = 0;
|
|
if (tenant_id_ < r.tenant_id_) {
|
|
cmp = -1;
|
|
} else if (tenant_id_ == r.tenant_id_) {
|
|
if (user_id_ < r.user_id_) {
|
|
cmp = -1;
|
|
} else if (user_id_ == r.user_id_) {
|
|
cmp = 0;
|
|
} else {
|
|
cmp = 1;
|
|
}
|
|
} else {
|
|
cmp = 1;
|
|
}
|
|
return cmp;
|
|
}
|
|
bool operator== (const ObTenantUserKey &other) const { return 0 == compare(other); }
|
|
bool operator!=(const ObTenantUserKey &other) const { return !operator==(other); }
|
|
bool operator<(const ObTenantUserKey &other) const { return -1 == compare(other); }
|
|
TO_STRING_KV(K_(tenant_id), K(user_id_));
|
|
|
|
public:
|
|
uint64_t tenant_id_;
|
|
uint64_t user_id_;
|
|
};
|
|
|
|
typedef common::LinkHashNode<ObTenantUserKey> ObConnectResHashNode;
|
|
typedef common::LinkHashValue<ObTenantUserKey> ObConnectResHashValue;
|
|
|
|
class ObConnectResource : public ObConnectResHashValue {
|
|
public:
|
|
ObConnectResource()
|
|
: rwlock_(), cur_connections_(0), history_connections_(0), start_time_(0)
|
|
{
|
|
}
|
|
ObConnectResource(uint64_t cur_connections, uint64_t history_connections, int64_t cur_time)
|
|
: rwlock_(), cur_connections_(cur_connections),
|
|
history_connections_(history_connections),
|
|
start_time_(cur_time)
|
|
{
|
|
}
|
|
virtual ~ObConnectResource()
|
|
{}
|
|
TO_STRING_KV(K_(cur_connections), K_(history_connections), K_(start_time));
|
|
common::ObLatch rwlock_;
|
|
uint64_t cur_connections_;
|
|
uint64_t history_connections_;
|
|
// From start_time_ to now, count of connections is history_connections_.
|
|
// According to MySQL, we don't have to record time of all connections in the previous hour.
|
|
// At start_time_ + 1 hour, history_connections_ is reset to zero.
|
|
// For example, max_connections_per_hour is 3,
|
|
// we create one connection at 1:00, 1:10 and 1:20, then we can't create a connection until 2:00.
|
|
// At 2:00, we can create 3 connections, so we only have to record start_time_ = 1:00 and
|
|
// number of connections from this time, and don't have to record 1:10 or 1:20.
|
|
int64_t start_time_;
|
|
// TODO: count of update and query in one hour.
|
|
};
|
|
|
|
class ObConnectResAlloc {
|
|
public:
|
|
ObConnectResAlloc()
|
|
{}
|
|
~ObConnectResAlloc()
|
|
{}
|
|
ObConnectResource* alloc_value();
|
|
void free_value(ObConnectResource* conn_res);
|
|
|
|
ObConnectResHashNode* alloc_node(ObConnectResource* value);
|
|
void free_node(ObConnectResHashNode* node);
|
|
};
|
|
|
|
typedef common::ObLinkHashMap<ObTenantUserKey, ObConnectResource, ObConnectResAlloc> ObConnResMap;
|
|
|
|
class ObConnectResourceMgr {
|
|
public:
|
|
ObConnectResourceMgr();
|
|
virtual ~ObConnectResourceMgr();
|
|
int init(share::schema::ObMultiVersionSchemaService &schema_service);
|
|
// ask for tenant connection resource.
|
|
int apply_for_tenant_conn_resource(const uint64_t tenant_id, const ObPrivSet &priv,
|
|
const uint64_t max_tenant_connections);
|
|
void release_tenant_conn_resource(const uint64_t tenant_id);
|
|
int get_tenant_cur_connections(const uint64_t tenant_id,
|
|
bool &tenant_exists,
|
|
uint64_t &cur_connections);
|
|
int get_or_insert_user_resource(
|
|
const uint64_t tenant_id,
|
|
const uint64_t user_id,
|
|
const uint64_t max_user_connections,
|
|
const uint64_t max_connections_per_hour,
|
|
ObConnectResource *&user_res, bool &has_insert, bool &user_conn_increased);
|
|
int increase_user_connections_count(
|
|
const uint64_t max_user_connections,
|
|
const uint64_t max_connections_per_hour,
|
|
const ObString &user_name,
|
|
ObConnectResource *user_res,
|
|
bool &user_conn_increased);
|
|
int on_user_connect(const uint64_t tenant_id,
|
|
const uint64_t user_id,
|
|
const ObPrivSet &priv,
|
|
const ObString &user_name,
|
|
const uint64_t max_connections_per_hour,
|
|
const uint64_t max_user_connections,
|
|
const uint64_t max_global_connections,
|
|
ObSQLSessionInfo& session);
|
|
int on_user_disconnect(ObSQLSessionInfo &session);
|
|
private:
|
|
class CleanUpConnResourceFunc
|
|
{
|
|
public:
|
|
CleanUpConnResourceFunc(share::schema::ObSchemaGetterGuard &schema_guard,
|
|
ObConnResMap &conn_res_map, const bool is_user)
|
|
: schema_guard_(schema_guard), conn_res_map_(conn_res_map), is_user_(is_user)
|
|
{}
|
|
bool operator() (ObTenantUserKey key, ObConnectResource *user_res);
|
|
private:
|
|
share::schema::ObSchemaGetterGuard &schema_guard_;
|
|
ObConnResMap &conn_res_map_;
|
|
const bool is_user_;
|
|
};
|
|
class ConnResourceCleanUpTask : public common::ObTimerTask
|
|
{
|
|
public:
|
|
ConnResourceCleanUpTask(ObConnectResourceMgr &conn_res_mgr)
|
|
: conn_res_mgr_(conn_res_mgr) {}
|
|
int init(ObConnectResourceMgr *tz_mgr);
|
|
virtual ~ConnResourceCleanUpTask() {}
|
|
void runTimerTask(void) override;
|
|
|
|
ObConnectResourceMgr &conn_res_mgr_;
|
|
static const uint64_t SLEEP_USECONDS = 3600000000; // one hour
|
|
};
|
|
friend class ConnResourceCleanUpTask;
|
|
friend class CleanUpUserResourceFunc;
|
|
private:
|
|
bool inited_;
|
|
ObConnResMap user_res_map_;
|
|
ObConnResMap tenant_res_map_;
|
|
share::schema::ObMultiVersionSchemaService *schema_service_;
|
|
ConnResourceCleanUpTask cleanup_task_;
|
|
DISALLOW_COPY_AND_ASSIGN(ObConnectResourceMgr);
|
|
};
|
|
|
|
|
|
|
|
} // end namespace sql
|
|
} // end namespace oceanbase
|
|
|
|
#endif /* OCEANBASE_SQL_USER_RESOURCE_MGR_H_ */
|