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