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