* Copyright (c) 2020 Huawei Technologies Co.,Ltd.
*
* openGauss is licensed under Mulan PSL v2.
* You can use this software according to the terms and conditions of the Mulan PSL v2.
* You may obtain a copy of Mulan PSL v2 at:
*
* http://license.coscl.org.cn/MulanPSL2
*
* 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 PSL v2 for more details.
* ---------------------------------------------------------------------------------------
*
* workload.h
* definitions for workload manager
*
* IDENTIFICATION
* src/include/workload/workload.h
*
* ---------------------------------------------------------------------------------------
*/
#ifndef WORKLOAD_H
#define WORKLOAD_H
#include "postgres.h"
#include "knl/knl_variable.h"
#include "gs_threadlocal.h"
#include "nodes/parsenodes.h"
#include "nodes/nodes.h"
#include "nodes/plannodes.h"
#include "utils/datetime.h"
#include "utils/portal.h"
#include "utils/palloc.h"
#include "postmaster/postmaster.h"
#include "workload/gscgroup.h"
#include "workload/ctxctl.h"
#include "workload/parctl.h"
#include "workload/statctl.h"
#include "workload/memctl.h"
#include "workload/dywlm_client.h"
#include "workload/dywlm_server.h"
#include "workload/ioschdl.h"
#include "workload/cpwlm.h"
#define FULL_PERCENT 100
#define OTHER_USED_PERCENT 60
#define STATEMENT_MIN_MEM 256
#define STATEMETN_MIN_MODIFY_MEM 2 * 1024
#define MEM_THRESHOLD 32
#define SIMPLE_THRESHOLD (32 * 1024)
#define HOLD_NODE_GROUP(group) gs_lock_test_and_set((int*)&group->used, 1)
#define RESUME_NODE_GROUP(group) gs_lock_test_and_set((int*)&group->used, 0)
#define NodeGroupIsDefault(group) (NULL == (void*)group || *group == '\0' || strcmp(group, "installation") == 0)
#define ENABLE_WORKLOAD_CONTROL \
(u_sess->attr.attr_resource.use_workload_manager || u_sess->attr.attr_resource.bypass_workload_manager)
#define DY_MEM_ADJ(stmt) \
g_instance.wlm_cxt->dynamic_workload_inited&& t_thrd.wlm_cxt.parctl_state.enqueue && \
(stmt)->query_mem[0] >= MEM_THRESHOLD * 1024L
#define ASSIGNED_QUERY_MEM(mem, max_mem) ((max_mem) > 0 ? Min((mem), (max_mem)) : (mem))
#define VALID_QUERY_MEM() \
(ASSIGNED_QUERY_MEM(u_sess->attr.attr_sql.statement_mem, u_sess->attr.attr_sql.statement_max_mem) > 0)
extern THR_LOCAL bool log_workload_manager;
typedef enum CGSwitchState { CG_ORIGINAL = 0, CG_USERSET, CG_USING, CG_RESPOOL } CGSwitchState;
typedef enum DataSpaceType { SP_PERM = 0, SP_TEMP, SP_SPILL } DataSpaceType;
typedef struct UserData {
Oid userid;
bool is_super;
bool is_dirty;
unsigned char adjust;
unsigned char keepdata;
int64 totalspace;
int64 global_totalspace;
int64 reAdjustPermSpace;
int64 spacelimit;
bool spaceUpdate;
int64 tmpSpace;
int64 globalTmpSpace;
int64 reAdjustTmpSpace;
int64 tmpSpaceLimit;
int64 spillSpace;
int64 globalSpillSpace;
int64 spillSpaceLimit;
Oid rpoid;
int memsize;
int usedCpuCnt;
int totalCpuCnt;
volatile int referenceCnt;
ResourcePool* respool;
UserData* parent;
List* childlist;
WLMUserInfo* infoptr;
int query_count;
WLMIoGeninfo ioinfo;
pthread_mutex_t mutex;
List* entry_list;
int compare(const Oid* userid)
{
if (this->userid == *userid)
return 0;
return ((this->userid < *userid) ? 1 : -1);
}
} UserData;
typedef struct TmpUserData {
Oid userid;
Oid puid;
bool is_super;
bool is_dirty;
int64 spacelimit;
int64 tmpSpaceLimit;
int64 spillSpaceLimit;
Oid rpoid;
ResourcePool *respool;
} TmpUserData;
typedef struct UserResourceData {
Oid userid;
int total_memory;
int used_memory;
int total_cpuset;
int used_cpuset;
int64 total_space;
int64 used_space;
int64 total_temp_space;
int64 used_temp_space;
int64 total_spill_space;
int64 used_spill_space;
int mincurr_iops;
int maxcurr_iops;
int minpeak_iops;
int maxpeak_iops;
int iops_limits;
int io_priority;
int curr_iops_limit;
uint64 read_bytes;
uint64 write_bytes;
uint64 read_counts;
uint64 write_counts;
uint64 read_speed;
uint64 write_speed;
} UserResourceData;
typedef struct WLMNodeGroupInfo {
char group_name[NAMEDATALEN];
int used_memory;
int total_memory;
int estimate_memory;
int min_freesize;
unsigned int used;
ClientDynamicManager climgr;
ServerDynamicManager srvmgr;
ParctlManager parctl;
gscgroup_grp_t* vaddr[GSCGROUP_ALLNUM];
HTAB* cgroups_htab;
pthread_mutex_t cgroups_mutex;
List* node_list;
ResourcePool* foreignrp;
bool is_dirty;
} WLMNodeGroupInfo;
typedef struct WLMDebugInfo {
WLMGeneralParam* wparams;
ExceptionManager* statctl;
WLMCollectInfo* colinfo;
ParctlState* pstate;
ParctlManager* parctl;
ClientDynamicManager* climgr;
ServerDynamicManager* srvmgr;
int active_statement;
bool* reserved_in_transaction;
} WLMDebugInfo;
typedef struct knl_g_wlm_context {
WLMNodeGroupInfo MyDefaultNodeGroup;
WLMNodeGroupInfo* local_dn_nodegroup;
MemoryContext workload_manager_mcxt;
MemoryContext query_resource_track_mcxt;
MemoryContext oper_resource_track_mcxt;
WLMStatManager stat_manager;
WLMInstanceStatManager instance_manager;
HTAB* resource_pool_hashtbl;
bool dynamic_workload_inited;
bool dynamic_memory_collected = false;
int parctl_process_memory;
int gscgroup_init_done;
int gscgroup_config_parsed;
int gscgroup_cpucnt;
char local_dn_ngname[NAMEDATALEN];
gscgroup_grp_t* gscgroup_vaddr[GSCGROUP_ALLNUM];
struct cgroup* gscgroup_vaccg;
struct cgroup* gscgroup_bkdcg;
struct cgroup* gscgroup_rootcg;
struct cgroup* gscgroup_defwdcg;
struct cgroup* gscgroup_deftopwdcg;
WLMIOContext io_context;
struct DNState* cluster_state;
int dnnum_in_cluster_state;
bool is_ccn;
int ccn_idx;
int rp_number_in_dn;
} knl_g_wlm_context;
typedef struct knl_u_wlm_context {
char control_group[NAMEDATALEN];
CGSwitchState cgroup_state;
gscgroup_stmt_t cgroup_stmt;
gscgroup_stmt_t cgroup_last_stmt;
bool session_respool_switch;
bool session_respool_initialize;
bool respool_is_foreign;
bool wlmcatalog_update_user;
bool cancel_from_wlm;
bool cancel_from_space_limit;
bool cancel_from_defaultXact_readOnly;
char session_respool[NAMEDATALEN];
Oid respool_create_oid;
Oid respool_alter_oid;
Oid respool_old_oid;
List* respool_delete_list;
int respool_foreign_mempct;
int respool_foreign_actpct;
Oid respool_parentid;
int32 respool_io_limit_update;
char respool_io_pri_update[NAMEDATALEN];
char respool_nodegroup[NAMEDATALEN];
char respool_controlgroup[NAMEDATALEN];
WLMNodeGroupInfo* respool_node_group;
ResourcePool* local_foreign_respool;
WLMDebugInfo wlm_debug_info;
WLMGeneralParam wlm_params;
int wlm_num_streams;
char group_keyname[GPNAME_LEN];
bool is_reserved_in_transaction;
bool is_active_statements_reset;
bool forced_running;
bool query_count_record;
bool cp_task_running;
int reserved_in_active_statements;
int reserved_in_group_statements;
int reserved_in_group_statements_simple;
int reserved_in_respool_waiting;
int reserved_in_central_waiting;
UserData* spmgr_userdata;
HTAB* TmptableCacheHash;
CPRuntimeInfo* cp_runtime_info;
uint64 spmgr_space_bytes;
bool spill_limit_error;
int64 wlm_userpl;
char reserved_debug_query[1024];
unsigned char stroedproc_rp_reserve;
unsigned char stroedproc_rp_release;
unsigned char stroedproc_release;
unsigned char parctl_state_control;
unsigned char parctl_state_exit;
} knl_u_wlm_context;
extern void dywlm_client_init(WLMNodeGroupInfo*);
extern void dywlm_server_init(WLMNodeGroupInfo*);
extern void WLMParctlInit(WLMNodeGroupInfo*);
extern void InitializeWorkloadManager(void);
extern void SetCpuAffinity(int64 setting);
extern void WLMSetControlGroup(const char* cgname);
extern gscgroup_stmt_t WLMIsSpecialCommand(const Node* parsetree, const Portal);
extern bool WLMIsSimpleQuery(const QueryDesc* queryDesc, bool force_control, bool isQueryDesc);
extern bool WLMNeedTrackResource(const QueryDesc* queryDesc);
extern bool WLMIsSpecialQuery(const char* query);
extern unsigned char WLMCheckToAttachCgroup(const QueryDesc* queryDesc);
extern void WLMSetUserInfo();
extern void GetCurrentCgroup(char* cgroup, const char* curr_group, int len);
extern void WLMSwitchCGroup(void);
extern char* GetMemorySizeWithUnit(char* memory, int size, int memsize);
extern bool CheckWLMSessionInfoTableValid(const char* tablename);
extern WLMUserInfo* WLMGetUserInfo(Oid userid, WLMUserInfo* info);
extern int ParseUserInfoConfigFile(void);
extern UserData* GetUserDataFromHTab(Oid roleid, bool is_noexcept);
extern bool BuildUserRPHash(void);
extern void* WLMGetAllUserData(int* num);
extern void WLMReAdjustUserSpace(UserData* userdata, bool isForce = false);
extern char* GenerateResourcePoolStmt(CreateResourcePoolStmt* stmt, const char* origin_query);
extern void CreateResourcePool(CreateResourcePoolStmt* stmt);
extern void AlterResourcePool(AlterResourcePoolStmt* stmt);
extern void RemoveResourcePool(Oid pool_oid);
extern void DropResourcePool(DropResourcePoolStmt* stmt);
extern void CreateWorkloadGroup(CreateWorkloadGroupStmt* stmt);
extern void AlterWorkloadGroup(AlterWorkloadGroupStmt* stmt);
extern void RemoveWorkloadGroup(Oid group_oid);
extern void DropWorkloadGroup(DropWorkloadGroupStmt* stmt);
extern void CreateAppWorkloadGroupMapping(CreateAppWorkloadGroupMappingStmt* stmt);
extern void AlterAppWorkloadGroupMapping(AlterAppWorkloadGroupMappingStmt* stmt);
extern void RemoveAppWorkloadGroupMapping(Oid app_oid);
extern void DropAppWorkloadGroupMapping(DropAppWorkloadGroupMappingStmt* stmt);
extern bool UsersInOneGroup(UserData* user1, UserData* user2);
extern void CheckUserRelation(Oid roleid, Oid parentid, Oid rpoid, bool isDefault, int issuper);
extern int UserGetChildRoles(Oid roleid, DropRoleStmt* stmt);
extern void GetUserDataFromCatalog(Oid userid, Oid* rpoid, Oid* parentid, bool* issuper, int64* spacelimit,
int64* tmpspacelimit, int64* spillspacelimit, char* groupname = NULL, int lenNgroup = 0);
extern bool GetUserChildlistFromCatalog(Oid userid, List** childlist, bool findall);
extern UserResourceData* GetUserResourceData(const char* username);
extern void CheckUserSpaceLimit(Oid roleid, Oid parentid, int64 spacelimit, int64 tmpspacelimit,
int64 spillspacelimit, bool is_default, bool changed, bool tmpchanged, bool spillchanged);
extern ResourcePool* GetRespoolFromHTab(Oid rpoid, bool is_noexcept = true);
extern void perm_space_increase(Oid ownerID, uint64 size, DataSpaceType type);
extern void perm_space_decrease(Oid ownerID, uint64 size, DataSpaceType type);
extern void perm_space_value_reset(void);
extern bool SearchUsedSpace(Oid userID, int64* permSpace, int64* tempSpace);
extern void UpdateUsedSpace(Oid userID, int64 permSpace, int64 tempSpace);
extern int128* find_tmptable_cache_autoinc(Oid relNode);
extern int128 tmptable_autoinc_nextval(Oid relnode, int128 *autoinc_next);
extern void tmptable_autoinc_setval(Oid relnode, int128 *autoinc_next, int128 value, bool iscalled);
extern void tmptable_autoinc_reset(Oid relnode, int128 value);
extern void make_tmptable_cache_key(Oid relNode);
extern void CheckUserInfoHash();
extern void UpdateWlmCatalogInfoHash(void);
extern void ResetWlmCatalogFlag(void);
extern unsigned int GetRPMemorySize(int pct, Oid parentid);
extern void WLMCheckSessionRespool(const char* respool);
extern void WLMSetSessionRespool(const char* respool);
extern int WLMGetUserMemory(UserData* userdata);
extern void WLMCheckSpaceLimit(void);
extern WLMNodeGroupInfo* WLMGetNodeGroupFromHTAB(const char* group_name);
extern WLMNodeGroupInfo* WLMMustGetNodeGroupFromHTAB(const char* group_name);
extern WLMNodeGroupInfo* WLMGetNodeGroupByUserId(Oid userid);
extern WLMNodeGroupInfo* CreateNodeGroupInfoInHTAB(const char* group_name);
extern void RemoveNodeGroupInfoInHTAB(const char* group_name);
extern void WLMInitNodeGroupInfo(WLMNodeGroupInfo* info);
extern void WLMGetDebugInfo(StringInfo strinfo, WLMDebugInfo* debug_info);
extern void gscgroup_init(void);
extern void gscgroup_free(void);
extern int gscgroup_get_percent(WLMNodeGroupInfo* ng, const char* gname);
extern void gscgroup_attach_task(WLMNodeGroupInfo* ng, const char* gname);
extern int gscgroup_attach_task_batch(WLMNodeGroupInfo* ng, const char* gname, pid_t tid, int* is_first);
extern int gscgroup_attach_backend_task(const char* gname, bool is_noexcept);
extern int gscgroup_check_group_name(WLMNodeGroupInfo* ng, const char* gname);
extern int gscgroup_check_group_percent(WLMNodeGroupInfo* ng, const char* gname);
extern bool WLMAjustCGroupByCNSessid(WLMNodeGroupInfo* ng, uint64 sess_id, const char* cgroup);
char* gsutil_get_cgroup_name(struct cgroup* cg);
extern gscgroup_grp_t* gscgroup_get_grpconf(WLMNodeGroupInfo* ng, const char* gname);
extern int gscgroup_is_class(WLMNodeGroupInfo* ng, const char* gname);
extern void gscgroup_switch_topwd(WLMNodeGroupInfo* ng);
extern void gscgroup_switch_vacuum(void);
extern void gscgroup_update_hashtbl(WLMNodeGroupInfo* ng, const char* keyname);
extern gscgroup_entry_t* gscgroup_lookup_hashtbl(WLMNodeGroupInfo* ng, const char* name);
extern int gscgroup_get_next_group(WLMNodeGroupInfo* ng, char* gname);
extern char* gscgroup_get_top_group_name(WLMNodeGroupInfo* ng, char* gname, int len);
extern struct cgroup* gscgroup_lookup_cgroup(WLMNodeGroupInfo* ng, const char* gname, bool* found = NULL);
extern void gscgroup_update_hashtbl_cpuinfo(WLMNodeGroupInfo* ng);
extern gscgroup_info_t* gscgroup_get_cgroup_info(int* num);
extern void gscgroup_get_cpuinfo(gscgroup_entry_t* entry);
extern int gscgroup_get_cpu_usage_percent(WLMNodeGroupInfo* ng, const char* gname);
extern bool gscgroup_is_brother_group(const char* cgroup1, const char* cgroup2);
extern bool gscgroup_is_child_group(const char* parentcg, const char* childcg);
extern int gscgroup_is_timeshare(const char* gname);
extern char* gscgroup_convert_cgroup(char* gname);
extern int WLMCheckCgroupPercent(WLMNodeGroupInfo* ng, const char*);
extern void WLMMoveNodeToList(WLMNodeGroupInfo* ng, ThreadId tid, const char* cgroup);
extern void WLMReleaseAtThreadExit();
#endif