1 /* Copyright (c) 2014, 2021, Oracle and/or its affiliates.
2
3 This program is free software; you can redistribute it and/or modify
4 it under the terms of the GNU General Public License, version 2.0,
5 as published by the Free Software Foundation.
6
7 This program is also distributed with certain software (including
8 but not limited to OpenSSL) that is licensed under separate terms,
9 as designated in a particular file or component or in included license
10 documentation. The authors of MySQL hereby grant you an additional
11 permission to link the program and your derivative works with the
12 separately licensed software that they have included with MySQL.
13
14 This program is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 GNU General Public License, version 2.0, for more details.
18
19 You should have received a copy of the GNU General Public License
20 along with this program; if not, write to the Free Software
21 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */
22
23 #include "sys_vars_resource_mgr.h"
24 #include <set_var.h>
25 #include "mysqld.h"
26
27 /**
28 Returns the member that contains the given key (address).
29
30 @parma key [IN] Key (address) to look for in the list.
31 @param length [IN] Length of the key.
32
33 @return
34 Success - Address of the member containing the specified key (address).
35 Failure - 0, key not found.
36 */
37
find(void * key,size_t length)38 uchar *Session_sysvar_resource_manager::find(void *key, size_t length)
39 {
40 return (my_hash_search(&m_sysvar_string_alloc_hash, (const uchar *) key,
41 length));
42 }
43
44
45 /**
46 Allocates memory for Sys_var_charptr session variable during session
47 initialization.
48
49 @param var [IN] The variable.
50 @param charset [IN] Character set information.
51
52 @return
53 Success - false
54 Failure - true
55 */
56
init(char ** var,const CHARSET_INFO * charset)57 bool Session_sysvar_resource_manager::init(char **var, const CHARSET_INFO * charset)
58 {
59 if (*var)
60 {
61 sys_var_ptr *element;
62 char *ptr;
63
64 if (!my_hash_inited(&m_sysvar_string_alloc_hash))
65 my_hash_init(&m_sysvar_string_alloc_hash,
66 const_cast<CHARSET_INFO *> (charset),
67 4, 0, 0, (my_hash_get_key) sysvars_mgr_get_key,
68 my_free, HASH_UNIQUE,
69 key_memory_THD_Session_sysvar_resource_manager);
70 /* Create a new node & add it to the hash. */
71 if ( !(element=
72 (sys_var_ptr *) my_malloc(key_memory_THD_Session_sysvar_resource_manager,
73 sizeof(sys_var_ptr), MYF(MY_WME))) ||
74 !(ptr=
75 (char *) my_memdup(key_memory_THD_Session_sysvar_resource_manager,
76 *var, strlen(*var) + 1, MYF(MY_WME))))
77 return true; /* Error */
78 element->data= (void *) ptr;
79 my_hash_insert(&m_sysvar_string_alloc_hash, (uchar *) element);
80
81 /* Update the variable to point to the newly alloced copy. */
82 *var= ptr;
83 }
84 return false;
85 }
86
87
88 /**
89 Frees the old alloced memory, memdup()'s the given val to a new memory
90 address & updated the session variable pointer.
91
92 @param var [IN] The variable.
93 @param val [IN] The new value.
94 @param val_len [IN] Length of the new value.
95
96 @return
97 Success - false
98 Failure - true
99 */
100
update(char ** var,char * val,size_t val_len)101 bool Session_sysvar_resource_manager::update(char **var, char *val,
102 size_t val_len)
103 {
104 sys_var_ptr *element= NULL;
105 char *ptr= NULL;
106 char *old_key= NULL;
107
108 /*
109 Memory allocation for the new value of the variable and
110 copying the value in it.
111 */
112 if (val)
113 {
114 if ( !(ptr=
115 (char *) my_memdup(PSI_NOT_INSTRUMENTED,
116 val, val_len + 1, MYF(MY_WME))))
117 return true;
118 ptr[val_len]= 0;
119 }
120
121 /* Get the handle for existing value in hash. */
122 if (*var)
123 {
124 element= (sys_var_ptr *) find(*var, strlen(*var));
125 if (element)
126 old_key= (char *) element->data;
127 }
128
129 /*
130 Update the value in hash when both the existing value
131 and the new value are not null.
132 */
133 if (val && *var)
134 {
135 /* Free the existing one & update the current address. */
136 element->data= ptr;
137 my_hash_update(&m_sysvar_string_alloc_hash, (uchar *) element,
138 (uchar *)old_key, strlen(old_key));
139 if (old_key)
140 my_free(old_key);
141 }
142
143 /*
144 Delete the existing value from the hash when the new value is NULL.
145 */
146 else if ((val == NULL) && *var)
147 {
148 if (element)
149 {
150 my_hash_delete(&m_sysvar_string_alloc_hash, (uchar *)element);
151 if (old_key)
152 my_free(old_key);
153 }
154 }
155
156 /*
157 Insert the new value into the hash when it is not NULL, but the
158 existing value is.
159 */
160 else if ((*var == NULL) && val)
161 {
162 /* Create a new node & add it to the list. */
163 if( !(element=
164 (sys_var_ptr*) my_malloc(key_memory_THD_Session_sysvar_resource_manager,
165 sizeof(sys_var_ptr), MYF(MY_WME))))
166 return true; /* Error */
167 element->data= ptr;
168 my_hash_insert(&m_sysvar_string_alloc_hash, (uchar *) element);
169 }
170
171 /*
172 Update the variable to point to the newly alloced copy.
173
174 When current value and the new value are both NULL,
175 the control directly reaches here. In that case this
176 function effectively does nothing.
177 */
178 *var= ptr;
179 return false;
180 }
181
claim_memory_ownership()182 void Session_sysvar_resource_manager::claim_memory_ownership()
183 {
184 /* Release Sys_var_charptr resources here. */
185 sys_var_ptr *ptr;
186 int i= 0;
187 while ((ptr= (sys_var_ptr*)my_hash_element(&m_sysvar_string_alloc_hash, i)))
188 {
189 if (ptr->data)
190 my_claim(ptr->data);
191 i++;
192 }
193
194 if (m_sysvar_string_alloc_hash.records)
195 {
196 my_hash_claim(&m_sysvar_string_alloc_hash);
197 }
198 }
199
200
201 /**
202 @brief Frees the memory allocated for Sys_var_charptr session variables.
203 */
204
deinit()205 void Session_sysvar_resource_manager::deinit()
206 {
207 /* Release Sys_var_charptr resources here. */
208 sys_var_ptr *ptr;
209 int i= 0;
210 while ((ptr= (sys_var_ptr*)my_hash_element(&m_sysvar_string_alloc_hash, i)))
211 {
212 if(ptr->data)
213 my_free(ptr->data);
214 i++;
215 }
216
217 if (m_sysvar_string_alloc_hash.records)
218 {
219 my_hash_free(&m_sysvar_string_alloc_hash);
220 }
221 }
222
sysvars_mgr_get_key(const char * entry,size_t * length,my_bool not_used MY_ATTRIBUTE ((unused)))223 uchar *Session_sysvar_resource_manager::sysvars_mgr_get_key(const char *entry,
224 size_t *length,
225 my_bool not_used MY_ATTRIBUTE((unused)))
226 {
227 char *key;
228 key= (char *) ((sys_var_ptr *) entry)->data;
229 *length= strlen(key);
230 return (uchar *) key;
231 }
232