2 * Copyright (c) 2005 Michael Bushkov <bushman@rsu.ru>
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
14 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
15 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
18 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
28 #include <sys/cdefs.h>
29 __FBSDID("$FreeBSD$");
43 static void enable_cache(struct configuration *,const char *, int);
44 static struct configuration_entry *find_create_entry(struct configuration *,
46 static int get_number(const char *, int, int);
47 static enum cache_policy_t get_policy(const char *);
48 static int get_yesno(const char *);
49 static int check_cachename(const char *);
50 static void check_files(struct configuration *, const char *, int);
51 static void set_keep_hot_count(struct configuration *, const char *, int);
52 static void set_negative_policy(struct configuration *, const char *,
54 static void set_negative_time_to_live(struct configuration *,
56 static void set_positive_policy(struct configuration *, const char *,
58 static void set_perform_actual_lookups(struct configuration *, const char *,
60 static void set_positive_time_to_live(struct configuration *,
62 static void set_suggested_size(struct configuration *, const char *,
64 static void set_threads_num(struct configuration *, int);
65 static int strbreak(char *, char **, int);
68 strbreak(char *str, char **fields, int fields_size)
77 strsep(i < fields_size ? &c : NULL, "\n\t ")) != NULL);
79 if ((*(*fields)) != '\0') {
89 * Tries to find the configuration entry with the specified name. If search
90 * fails, the new entry with the default parameters will be created.
92 static struct configuration_entry *
93 find_create_entry(struct configuration *config,
94 const char *entry_name)
96 struct configuration_entry *entry = NULL;
99 TRACE_IN(find_create_entry);
100 entry = configuration_find_entry(config, entry_name);
102 entry = create_def_configuration_entry(entry_name);
103 assert( entry != NULL);
104 res = add_configuration_entry(config, entry);
108 TRACE_OUT(find_create_entry);
113 * The vast majority of the functions below corresponds to the particular
114 * keywords in the configuration file.
117 enable_cache(struct configuration *config, const char *entry_name, int flag)
119 struct configuration_entry *entry;
121 TRACE_IN(enable_cache);
122 entry = find_create_entry(config, entry_name);
123 entry->enabled = flag;
124 TRACE_OUT(enable_cache);
128 set_positive_time_to_live(struct configuration *config,
129 const char *entry_name, int ttl)
131 struct configuration_entry *entry;
132 struct timeval lifetime;
134 TRACE_IN(set_positive_time_to_live);
136 assert(entry_name != NULL);
137 memset(&lifetime, 0, sizeof(struct timeval));
138 lifetime.tv_sec = ttl;
140 entry = find_create_entry(config, entry_name);
141 memcpy(&entry->positive_cache_params.max_lifetime,
142 &lifetime, sizeof(struct timeval));
143 memcpy(&entry->mp_cache_params.max_lifetime,
144 &lifetime, sizeof(struct timeval));
146 TRACE_OUT(set_positive_time_to_live);
150 set_negative_time_to_live(struct configuration *config,
151 const char *entry_name, int nttl)
153 struct configuration_entry *entry;
154 struct timeval lifetime;
156 TRACE_IN(set_negative_time_to_live);
158 assert(entry_name != NULL);
159 memset(&lifetime, 0, sizeof(struct timeval));
160 lifetime.tv_sec = nttl;
162 entry = find_create_entry(config, entry_name);
163 assert(entry != NULL);
164 memcpy(&entry->negative_cache_params.max_lifetime,
165 &lifetime, sizeof(struct timeval));
167 TRACE_OUT(set_negative_time_to_live);
171 set_positive_confidence_threshold(struct configuration *config,
172 const char *entry_name, int conf_thresh)
174 struct configuration_entry *entry;
176 TRACE_IN(set_positive_conf_thresh);
177 assert(conf_thresh > 0);
178 assert(entry_name != NULL);
180 entry = find_create_entry(config, entry_name);
181 assert(entry != NULL);
182 entry->positive_cache_params.confidence_threshold = conf_thresh;
184 TRACE_OUT(set_positive_conf_thresh);
188 set_negative_confidence_threshold(struct configuration *config,
189 const char *entry_name, int conf_thresh)
191 struct configuration_entry *entry;
193 TRACE_IN(set_negative_conf_thresh);
194 assert(conf_thresh > 0);
195 assert(entry_name != NULL);
196 entry = find_create_entry(config, entry_name);
197 assert(entry != NULL);
198 entry->negative_cache_params.confidence_threshold = conf_thresh;
199 TRACE_OUT(set_negative_conf_thresh);
203 * Hot count is actually the elements size limit.
206 set_keep_hot_count(struct configuration *config,
207 const char *entry_name, int count)
209 struct configuration_entry *entry;
211 TRACE_IN(set_keep_hot_count);
213 assert(entry_name != NULL);
215 entry = find_create_entry(config, entry_name);
216 assert(entry != NULL);
217 entry->positive_cache_params.max_elemsize = count;
219 entry = find_create_entry(config, entry_name);
220 assert(entry != NULL);
221 entry->negative_cache_params.max_elemsize = count;
223 TRACE_OUT(set_keep_hot_count);
227 set_positive_policy(struct configuration *config,
228 const char *entry_name, enum cache_policy_t policy)
230 struct configuration_entry *entry;
232 TRACE_IN(set_positive_policy);
233 assert(entry_name != NULL);
235 entry = find_create_entry(config, entry_name);
236 assert(entry != NULL);
237 entry->positive_cache_params.policy = policy;
239 TRACE_OUT(set_positive_policy);
243 set_negative_policy(struct configuration *config,
244 const char *entry_name, enum cache_policy_t policy)
246 struct configuration_entry *entry;
248 TRACE_IN(set_negative_policy);
249 assert(entry_name != NULL);
251 entry = find_create_entry(config, entry_name);
252 assert(entry != NULL);
253 entry->negative_cache_params.policy = policy;
255 TRACE_OUT(set_negative_policy);
259 set_perform_actual_lookups(struct configuration *config,
260 const char *entry_name, int flag)
262 struct configuration_entry *entry;
264 TRACE_IN(set_perform_actual_lookups);
265 assert(entry_name != NULL);
267 entry = find_create_entry(config, entry_name);
268 assert(entry != NULL);
269 entry->perform_actual_lookups = flag;
271 TRACE_OUT(set_perform_actual_lookups);
275 set_suggested_size(struct configuration *config,
276 const char *entry_name, int size)
278 struct configuration_entry *entry;
280 TRACE_IN(set_suggested_size);
281 assert(config != NULL);
282 assert(entry_name != NULL);
285 entry = find_create_entry(config, entry_name);
286 assert(entry != NULL);
287 entry->positive_cache_params.cache_entries_size = size;
288 entry->negative_cache_params.cache_entries_size = size;
290 TRACE_OUT(set_suggested_size);
294 check_files(struct configuration *config, const char *entry_name, int flag)
297 TRACE_IN(check_files);
298 assert(entry_name != NULL);
299 TRACE_OUT(check_files);
303 get_yesno(const char *str)
306 if (strcmp(str, "yes") == 0)
308 else if (strcmp(str, "no") == 0)
315 get_number(const char *str, int low, int max)
324 res = strtol(str, &end, 10);
328 if (((res >= low) || (low == -1)) &&
329 ((res <= max) || (max == -1)))
335 static enum cache_policy_t
336 get_policy(const char *str)
339 if (strcmp(str, "fifo") == 0)
341 else if (strcmp(str, "lru") == 0)
343 else if (strcmp(str, "lfu") == 0)
350 check_cachename(const char *str)
354 return ((strlen(str) > 0) ? 0 : -1);
358 set_threads_num(struct configuration *config, int value)
361 assert(config != NULL);
362 config->threads_num = value;
366 * The main configuration routine. Its implementation is hugely inspired by the
367 * the same routine implementation in Solaris NSCD.
370 parse_config_file(struct configuration *config,
371 const char *fname, char const **error_str, int *error_line)
376 int field_count, line_num, value;
380 TRACE_IN(parse_config_file);
381 assert(config != NULL);
382 assert(fname != NULL);
384 fin = fopen(fname, "r");
386 TRACE_OUT(parse_config_file);
393 memset(buffer, 0, sizeof(buffer));
394 while ((res == 0) && (fgets(buffer, sizeof(buffer) - 1, fin) != NULL)) {
395 field_count = strbreak(buffer, fields, sizeof(fields));
398 if (field_count == 0)
401 switch (fields[0][0]) {
406 if ((field_count == 3) &&
407 (strcmp(fields[0], "enable-cache") == 0) &&
408 (check_cachename(fields[1]) == 0) &&
409 ((value = get_yesno(fields[2])) != -1)) {
410 enable_cache(config, fields[1], value);
415 if ((field_count == 2) &&
416 (strcmp(fields[0], "debug-level") == 0) &&
417 ((value = get_number(fields[1], 0, 10)) != -1)) {
422 if ((field_count == 3) &&
423 (strcmp(fields[0], "positive-time-to-live") == 0) &&
424 (check_cachename(fields[1]) == 0) &&
425 ((value = get_number(fields[2], 0, -1)) != -1)) {
430 set_positive_time_to_live(config,
433 } else if ((field_count == 3) &&
434 (strcmp(fields[0], "positive-confidence-threshold") == 0) &&
435 ((value = get_number(fields[2], 1, -1)) != -1)) {
440 set_positive_confidence_threshold(config,
443 } else if ((field_count == 3) &&
444 (strcmp(fields[0], "positive-policy") == 0) &&
445 (check_cachename(fields[1]) == 0) &&
446 ((value = get_policy(fields[2])) != -1)) {
447 set_positive_policy(config, fields[1], value);
449 } else if ((field_count == 3) &&
450 (strcmp(fields[0], "perform-actual-lookups") == 0) &&
451 (check_cachename(fields[1]) == 0) &&
452 ((value = get_yesno(fields[2])) != -1)) {
453 set_perform_actual_lookups(config, fields[1],
459 if ((field_count == 3) &&
460 (strcmp(fields[0], "negative-time-to-live") == 0) &&
461 (check_cachename(fields[1]) == 0) &&
462 ((value = get_number(fields[2], 0, -1)) != -1)) {
467 set_negative_time_to_live(config,
470 } else if ((field_count == 3) &&
471 (strcmp(fields[0], "negative-confidence-threshold") == 0) &&
472 ((value = get_number(fields[2], 1, -1)) != -1)) {
477 set_negative_confidence_threshold(config,
480 } else if ((field_count == 3) &&
481 (strcmp(fields[0], "negative-policy") == 0) &&
482 (check_cachename(fields[1]) == 0) &&
483 ((value = get_policy(fields[2])) != -1)) {
484 set_negative_policy(config,
490 if ((field_count == 3) &&
491 (strcmp(fields[0], "suggested-size") == 0) &&
492 (check_cachename(fields[1]) == 0) &&
493 ((value = get_number(fields[2], 1, -1)) != -1)) {
498 set_suggested_size(config, fields[1], value);
503 if ((field_count == 2) &&
504 (strcmp(fields[0], "threads") == 0) &&
505 ((value = get_number(fields[1], 1, -1)) != -1)) {
506 set_threads_num(config, value);
511 if ((field_count == 3) &&
512 (strcmp(fields[0], "keep-hot-count") == 0) &&
513 (check_cachename(fields[1]) == 0) &&
514 ((value = get_number(fields[2], 0, -1)) != -1)) {
519 set_keep_hot_count(config,
525 if ((field_count == 3) &&
526 (strcmp(fields[0], "check-files") == 0) &&
527 (check_cachename(fields[1]) == 0) &&
528 ((value = get_yesno(fields[2])) != -1)) {
538 if (invalid_value != 0) {
539 LOG_ERR_2("Invalid value for parameter",
540 "error in file %s on line %d",
542 *error_str = "invalid value";
544 LOG_ERR_2("config file parser", "error in file "
545 "%s on line %d", fname, line_num);
546 *error_str = "syntax error";
548 *error_line = line_num;
553 TRACE_OUT(parse_config_file);