1 /* Copyright (c) 2017, 2019, Oracle and/or its affiliates. All rights reserved.
2 This program is free software; you can redistribute it and/or modify
3 it under the terms of the GNU General Public License, version 2.0,
4 as published by the Free Software Foundation.
5
6 This program is also distributed with certain software (including
7 but not limited to OpenSSL) that is licensed under separate terms,
8 as designated in a particular file or component or in included license
9 documentation. The authors of MySQL hereby grant you an additional
10 permission to link the program and your derivative works with the
11 separately licensed software that they have included with MySQL.
12
13 This program is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License, version 2.0, for more details.
17
18 You should have received a copy of the GNU General Public License
19 along with this program; if not, write to the Free Software
20 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */
21
22 #include "sql/dd/dd_resource_group.h"
23
24 #include <memory>
25
26 #include "my_dbug.h" // DBUG_*
27 #include "mysqld_error.h" // ER_RESOURCE_GROUP_EXISTS
28 #include "sql/dd/cache/dictionary_client.h" // dd::cache::Dictionary_client
29 #include "sql/dd/dd.h" // dd::create_object
30 #include "sql/dd/types/resource_group.h" // dd::Resource_group
31 #include "sql/resourcegroups/resource_group.h" // resourcegroups::Resource_group
32 #include "sql/sql_class.h" // THD
33 #include "sql/thd_raii.h"
34 #include "sql/transaction.h" // trans_commit
35
36 namespace dd {
37
resource_group_exists(dd::cache::Dictionary_client * dd_client,const String_type & resource_group_name,bool * exists)38 bool resource_group_exists(dd::cache::Dictionary_client *dd_client,
39 const String_type &resource_group_name,
40 bool *exists) {
41 DBUG_TRACE;
42 DBUG_ASSERT(exists);
43
44 const dd::Resource_group *resource_group_ptr = nullptr;
45 dd::cache::Dictionary_client::Auto_releaser releaser(dd_client);
46 if (dd_client->acquire(resource_group_name, &resource_group_ptr)) {
47 // Error is reported by the dictionary subsystem.
48 return true;
49 }
50
51 *exists = resource_group_ptr != nullptr;
52
53 return false;
54 }
55
set_resource_group_attributes(dd::Resource_group * resource_group,const resourcegroups::Resource_group & res_grp_ref)56 static bool set_resource_group_attributes(
57 dd::Resource_group *resource_group,
58 const resourcegroups::Resource_group &res_grp_ref) {
59 DBUG_TRACE;
60
61 resource_group->set_name(res_grp_ref.name().c_str());
62 resource_group->set_resource_group_type(res_grp_ref.type());
63 resource_group->set_resource_group_enabled(res_grp_ref.enabled());
64
65 const resourcegroups::Thread_resource_control *thr_res_ctrl =
66 res_grp_ref.controller();
67 resource_group->set_cpu_id_mask(thr_res_ctrl->vcpu_vector());
68 resource_group->set_thread_priority(thr_res_ctrl->priority());
69
70 return false;
71 }
72
create_resource_group(THD * thd,const resourcegroups::Resource_group & res_grp_ref)73 bool create_resource_group(THD *thd,
74 const resourcegroups::Resource_group &res_grp_ref) {
75 DBUG_TRACE;
76
77 // Check if the same resource group already exists.
78 dd::cache::Dictionary_client::Auto_releaser releaser(thd->dd_client());
79 const dd::Resource_group *resource_group_ptr = nullptr;
80 if (thd->dd_client()->acquire(dd::String_type(res_grp_ref.name().c_str(),
81 res_grp_ref.name().length()),
82 &resource_group_ptr)) {
83 // Error is reported by the dictionary subsystem.
84 return true;
85 }
86
87 if (resource_group_ptr != nullptr) {
88 my_error(ER_RESOURCE_GROUP_EXISTS, MYF(0), res_grp_ref.name().c_str());
89 return true;
90 }
91
92 // Create new resource group.
93 std::unique_ptr<dd::Resource_group> resource_group(
94 dd::create_object<dd::Resource_group>());
95
96 // Set attributes of the resource group.
97 if (set_resource_group_attributes(resource_group.get(), res_grp_ref))
98 return true; // Error already logged.
99
100 Implicit_substatement_state_guard substatement_guard(thd);
101
102 // Write changes to dictionary.
103 if (thd->dd_client()->store(resource_group.get())) {
104 trans_rollback_stmt(thd);
105 // Full rollback in case we have THD::transaction_rollback_request.
106 trans_rollback(thd);
107 return true;
108 }
109
110 return trans_commit_stmt(thd) || trans_commit(thd);
111 }
112
update_resource_group(THD * thd,const String_type & resource_grp_name,const resourcegroups::Resource_group & res_grp_ref)113 bool update_resource_group(THD *thd, const String_type &resource_grp_name,
114 const resourcegroups::Resource_group &res_grp_ref) {
115 DBUG_TRACE;
116
117 dd::cache::Dictionary_client::Auto_releaser releaser(thd->dd_client());
118 dd::Resource_group *resource_group = nullptr;
119 if (thd->dd_client()->acquire_for_modification(resource_grp_name,
120 &resource_group)) {
121 // Error is reported by the dictionary subsystem.
122 return true;
123 }
124
125 if (resource_group == nullptr) {
126 my_error(ER_RESOURCE_GROUP_NOT_EXISTS, MYF(0), resource_grp_name.c_str());
127 return true;
128 }
129
130 // Set attributes of the resource group.
131 if (set_resource_group_attributes(resource_group, res_grp_ref))
132 return true; // Error already logged.
133
134 if (thd->dd_client()->update(resource_group)) {
135 trans_rollback_stmt(thd);
136 // Full rollback we have THD::transaction_rollback_request.
137 trans_rollback(thd);
138 return true;
139 }
140
141 return trans_commit_stmt(thd) || trans_commit(thd);
142 }
143
drop_resource_group(THD * thd,const String_type resource_grp_name)144 bool drop_resource_group(THD *thd, const String_type resource_grp_name) {
145 DBUG_TRACE;
146
147 // Acquire resource group.
148 dd::cache::Dictionary_client::Auto_releaser releaser(thd->dd_client());
149 const dd::Resource_group *resource_group = nullptr;
150 if (thd->dd_client()->acquire(resource_grp_name, &resource_group)) {
151 // Error is reported by the dictionary subsystem.
152 return true;
153 }
154 if (resource_group == nullptr) {
155 my_error(ER_RESOURCE_GROUP_NOT_EXISTS, MYF(0), resource_grp_name.c_str());
156 return true;
157 }
158
159 Implicit_substatement_state_guard substatement_guard(thd);
160
161 // Drop resource group.
162 if (thd->dd_client()->drop(resource_group)) {
163 trans_rollback_stmt(thd);
164 // Full rollback in case we have THD::transaction_rollback_request.
165 trans_rollback(thd);
166 return true;
167 }
168
169 return trans_commit_stmt(thd) || trans_commit(thd);
170 }
171 } // namespace dd
172