1/* Copyright (c) 2002, 2010, Oracle and/or its affiliates. All rights reserved.
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 as published by
5 the Free Software Foundation; version 2 of the License.
6
7 This program is distributed in the hope that it will be useful,
8 but WITHOUT ANY WARRANTY; without even the implied warranty of
9 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10 GNU General Public License for more details.
11
12 You should have received a copy of the GNU General Public License
13 along with this program; if not, write to the Free Software
14 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */
15
16#include "mariadb.h"
17#include "keycaches.h"
18
19/****************************************************************************
20 Named list handling
21****************************************************************************/
22
23NAMED_ILIST key_caches;
24NAMED_ILIST rpl_filters;
25
26/**
27 ilink (intrusive list element) with a name
28*/
29class NAMED_ILINK :public ilink
30{
31public:
32 const char *name;
33 size_t name_length;
34 uchar* data;
35
36 NAMED_ILINK(I_List<NAMED_ILINK> *links, const char *name_arg,
37 size_t name_length_arg, uchar* data_arg)
38 :name_length(name_length_arg), data(data_arg)
39 {
40 name= my_strndup(name_arg, name_length, MYF(MY_WME));
41 links->push_back(this);
42 }
43 inline bool cmp(const char *name_cmp, size_t length)
44 {
45 return length == name_length && !memcmp(name, name_cmp, length);
46 }
47 ~NAMED_ILINK()
48 {
49 my_free((void *) name);
50 }
51};
52
53uchar* find_named(I_List<NAMED_ILINK> *list, const char *name, size_t length,
54 NAMED_ILINK **found)
55{
56 I_List_iterator<NAMED_ILINK> it(*list);
57 NAMED_ILINK *element;
58 while ((element= it++))
59 {
60 if (element->cmp(name, length))
61 {
62 if (found)
63 *found= element;
64 return element->data;
65 }
66 }
67 return 0;
68}
69
70
71bool NAMED_ILIST::delete_element(const char *name, size_t length, void (*free_element)(const char *name, uchar*))
72{
73 I_List_iterator<NAMED_ILINK> it(*this);
74 NAMED_ILINK *element;
75 DBUG_ENTER("NAMED_ILIST::delete_element");
76 while ((element= it++))
77 {
78 if (element->cmp(name, length))
79 {
80 (*free_element)(element->name, element->data);
81 delete element;
82 DBUG_RETURN(0);
83 }
84 }
85 DBUG_RETURN(1);
86}
87
88void NAMED_ILIST::delete_elements(void (*free_element)(const char *name, uchar*))
89{
90 NAMED_ILINK *element;
91 DBUG_ENTER("NAMED_ILIST::delete_elements");
92 while ((element= get()))
93 {
94 (*free_element)(element->name, element->data);
95 delete element;
96 }
97 DBUG_VOID_RETURN;
98}
99
100
101/* Key cache functions */
102
103LEX_CSTRING default_key_cache_base= {STRING_WITH_LEN("default")};
104
105KEY_CACHE zero_key_cache; ///< @@nonexistent_cache.param->value_ptr() points here
106
107KEY_CACHE *get_key_cache(const LEX_CSTRING *cache_name)
108{
109 if (!cache_name || ! cache_name->length)
110 cache_name= &default_key_cache_base;
111 return ((KEY_CACHE*) find_named(&key_caches,
112 cache_name->str, cache_name->length, 0));
113}
114
115KEY_CACHE *create_key_cache(const char *name, size_t length)
116{
117 KEY_CACHE *key_cache;
118 DBUG_ENTER("create_key_cache");
119 DBUG_PRINT("enter",("name: %.*s", (int)length, name));
120
121 if ((key_cache= (KEY_CACHE*) my_malloc(sizeof(KEY_CACHE),
122 MYF(MY_ZEROFILL | MY_WME))))
123 {
124 if (!new NAMED_ILINK(&key_caches, name, length, (uchar*) key_cache))
125 {
126 my_free(key_cache);
127 key_cache= 0;
128 }
129 else
130 {
131 /*
132 Set default values for a key cache
133 The values in dflt_key_cache_var is set by my_getopt() at startup
134
135 We don't set 'buff_size' as this is used to enable the key cache
136 */
137 key_cache->param_block_size= dflt_key_cache_var.param_block_size;
138 key_cache->param_division_limit= dflt_key_cache_var.param_division_limit;
139 key_cache->param_age_threshold= dflt_key_cache_var.param_age_threshold;
140 key_cache->param_partitions= dflt_key_cache_var.param_partitions;
141 }
142 }
143 DBUG_RETURN(key_cache);
144}
145
146
147KEY_CACHE *get_or_create_key_cache(const char *name, size_t length)
148{
149 LEX_CSTRING key_cache_name;
150 KEY_CACHE *key_cache;
151
152 key_cache_name.str= name;
153 key_cache_name.length= length;
154 if (!(key_cache= get_key_cache(&key_cache_name)))
155 key_cache= create_key_cache(name, length);
156 return key_cache;
157}
158
159
160void free_key_cache(const char *name, KEY_CACHE *key_cache)
161{
162 end_key_cache(key_cache, 1); // Can never fail
163 my_free(key_cache);
164}
165
166
167bool process_key_caches(process_key_cache_t func, void *param)
168{
169 I_List_iterator<NAMED_ILINK> it(key_caches);
170 NAMED_ILINK *element;
171 int res= 0;
172
173 while ((element= it++))
174 {
175 KEY_CACHE *key_cache= (KEY_CACHE *) element->data;
176 res |= func(element->name, key_cache, param);
177 }
178 return res != 0;
179}
180
181/* Rpl_filter functions */
182
183LEX_CSTRING default_rpl_filter_base= {STRING_WITH_LEN("")};
184
185Rpl_filter *get_rpl_filter(LEX_CSTRING *filter_name)
186{
187 if (!filter_name->length)
188 filter_name= &default_rpl_filter_base;
189 return ((Rpl_filter*) find_named(&rpl_filters,
190 filter_name->str, filter_name->length, 0));
191}
192
193Rpl_filter *create_rpl_filter(const char *name, size_t length)
194{
195 Rpl_filter *filter;
196 DBUG_ENTER("create_rpl_filter");
197 DBUG_PRINT("enter",("name: %.*s", (int)length, name));
198
199 filter= new Rpl_filter;
200 if (filter)
201 {
202 if (!new NAMED_ILINK(&rpl_filters, name, length, (uchar*) filter))
203 {
204 delete filter;
205 filter= 0;
206 }
207 }
208 DBUG_RETURN(filter);
209}
210
211
212Rpl_filter *get_or_create_rpl_filter(const char *name, size_t length)
213{
214 LEX_CSTRING rpl_filter_name;
215 Rpl_filter *filter;
216
217 rpl_filter_name.str= (char *) name;
218 rpl_filter_name.length= length;
219 if (!(filter= get_rpl_filter(&rpl_filter_name)))
220 filter= create_rpl_filter(name, length);
221 return filter;
222}
223
224void free_rpl_filter(const char *name, Rpl_filter *filter)
225{
226 delete filter;
227 filter= 0;
228}
229
230void free_all_rpl_filters()
231{
232 rpl_filters.delete_elements((void (*)(const char*, uchar*)) free_rpl_filter);
233}
234