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>
41 static void enable_cache(struct configuration *,const char *, int);
42 static struct configuration_entry *find_create_entry(struct configuration *,
44 static int get_number(const char *, int, int);
45 static enum cache_policy_t get_policy(const char *);
46 static int get_yesno(const char *);
47 static int check_cachename(const char *);
48 static void check_files(struct configuration *, const char *, int);
49 static void set_keep_hot_count(struct configuration *, const char *, int);
50 static void set_negative_policy(struct configuration *, const char *,
52 static void set_negative_time_to_live(struct configuration *,
54 static void set_positive_policy(struct configuration *, const char *,
56 static void set_perform_actual_lookups(struct configuration *, const char *,
58 static void set_positive_time_to_live(struct configuration *,
60 static void set_suggested_size(struct configuration *, const char *,
62 static void set_threads_num(struct configuration *, int);
63 static int strbreak(char *, char **, int);
66 strbreak(char *str, char **fields, int fields_size)
75 strsep(i < fields_size ? &c : NULL, "\n\t ")) != NULL);
77 if ((*(*fields)) != '\0') {
87 * Tries to find the configuration entry with the specified name. If search
88 * fails, the new entry with the default parameters will be created.
90 static struct configuration_entry *
91 find_create_entry(struct configuration *config,
92 const char *entry_name)
94 struct configuration_entry *entry = NULL;
97 TRACE_IN(find_create_entry);
98 entry = configuration_find_entry(config, entry_name);
100 entry = create_def_configuration_entry(entry_name);
101 assert( entry != NULL);
102 res = add_configuration_entry(config, entry);
106 TRACE_OUT(find_create_entry);
111 * The vast majority of the functions below corresponds to the particular
112 * keywords in the configuration file.
115 enable_cache(struct configuration *config, const char *entry_name, int flag)
117 struct configuration_entry *entry;
119 TRACE_IN(enable_cache);
120 entry = find_create_entry(config, entry_name);
121 entry->enabled = flag;
122 TRACE_OUT(enable_cache);
126 set_positive_time_to_live(struct configuration *config,
127 const char *entry_name, int ttl)
129 struct configuration_entry *entry;
130 struct timeval lifetime;
132 TRACE_IN(set_positive_time_to_live);
134 assert(entry_name != NULL);
135 memset(&lifetime, 0, sizeof(struct timeval));
136 lifetime.tv_sec = ttl;
138 entry = find_create_entry(config, entry_name);
139 memcpy(&entry->positive_cache_params.max_lifetime,
140 &lifetime, sizeof(struct timeval));
141 memcpy(&entry->mp_cache_params.max_lifetime,
142 &lifetime, sizeof(struct timeval));
144 TRACE_OUT(set_positive_time_to_live);
148 set_negative_time_to_live(struct configuration *config,
149 const char *entry_name, int nttl)
151 struct configuration_entry *entry;
152 struct timeval lifetime;
154 TRACE_IN(set_negative_time_to_live);
156 assert(entry_name != NULL);
157 memset(&lifetime, 0, sizeof(struct timeval));
158 lifetime.tv_sec = nttl;
160 entry = find_create_entry(config, entry_name);
161 assert(entry != NULL);
162 memcpy(&entry->negative_cache_params.max_lifetime,
163 &lifetime, sizeof(struct timeval));
165 TRACE_OUT(set_negative_time_to_live);
169 set_positive_confidence_threshold(struct configuration *config,
170 const char *entry_name, int conf_thresh)
172 struct configuration_entry *entry;
174 TRACE_IN(set_positive_conf_thresh);
175 assert(conf_thresh > 0);
176 assert(entry_name != NULL);
178 entry = find_create_entry(config, entry_name);
179 assert(entry != NULL);
180 entry->positive_cache_params.confidence_threshold = conf_thresh;
182 TRACE_OUT(set_positive_conf_thresh);
186 set_negative_confidence_threshold(struct configuration *config,
187 const char *entry_name, int conf_thresh)
189 struct configuration_entry *entry;
191 TRACE_IN(set_negative_conf_thresh);
192 assert(conf_thresh > 0);
193 assert(entry_name != NULL);
194 entry = find_create_entry(config, entry_name);
195 assert(entry != NULL);
196 entry->negative_cache_params.confidence_threshold = conf_thresh;
197 TRACE_OUT(set_negative_conf_thresh);
201 * Hot count is actually the elements size limit.
204 set_keep_hot_count(struct configuration *config,
205 const char *entry_name, int count)
207 struct configuration_entry *entry;
209 TRACE_IN(set_keep_hot_count);
211 assert(entry_name != NULL);
213 entry = find_create_entry(config, entry_name);
214 assert(entry != NULL);
215 entry->positive_cache_params.max_elemsize = count;
217 entry = find_create_entry(config, entry_name);
218 assert(entry != NULL);
219 entry->negative_cache_params.max_elemsize = count;
221 TRACE_OUT(set_keep_hot_count);
225 set_positive_policy(struct configuration *config,
226 const char *entry_name, enum cache_policy_t policy)
228 struct configuration_entry *entry;
230 TRACE_IN(set_positive_policy);
231 assert(entry_name != NULL);
233 entry = find_create_entry(config, entry_name);
234 assert(entry != NULL);
235 entry->positive_cache_params.policy = policy;
237 TRACE_OUT(set_positive_policy);
241 set_negative_policy(struct configuration *config,
242 const char *entry_name, enum cache_policy_t policy)
244 struct configuration_entry *entry;
246 TRACE_IN(set_negative_policy);
247 assert(entry_name != NULL);
249 entry = find_create_entry(config, entry_name);
250 assert(entry != NULL);
251 entry->negative_cache_params.policy = policy;
253 TRACE_OUT(set_negative_policy);
257 set_perform_actual_lookups(struct configuration *config,
258 const char *entry_name, int flag)
260 struct configuration_entry *entry;
262 TRACE_IN(set_perform_actual_lookups);
263 assert(entry_name != NULL);
265 entry = find_create_entry(config, entry_name);
266 assert(entry != NULL);
267 entry->perform_actual_lookups = flag;
269 TRACE_OUT(set_perform_actual_lookups);
273 set_suggested_size(struct configuration *config,
274 const char *entry_name, int size)
276 struct configuration_entry *entry;
278 TRACE_IN(set_suggested_size);
279 assert(config != NULL);
280 assert(entry_name != NULL);
283 entry = find_create_entry(config, entry_name);
284 assert(entry != NULL);
285 entry->positive_cache_params.cache_entries_size = size;
286 entry->negative_cache_params.cache_entries_size = size;
288 TRACE_OUT(set_suggested_size);
292 check_files(struct configuration *config, const char *entry_name, int flag)
295 TRACE_IN(check_files);
296 assert(entry_name != NULL);
297 TRACE_OUT(check_files);
301 get_yesno(const char *str)
304 if (strcmp(str, "yes") == 0)
306 else if (strcmp(str, "no") == 0)
313 get_number(const char *str, int low, int max)
322 res = strtol(str, &end, 10);
326 if (((res >= low) || (low == -1)) &&
327 ((res <= max) || (max == -1)))
333 static enum cache_policy_t
334 get_policy(const char *str)
337 if (strcmp(str, "fifo") == 0)
339 else if (strcmp(str, "lru") == 0)
341 else if (strcmp(str, "lfu") == 0)
348 check_cachename(const char *str)
352 return ((strlen(str) > 0) ? 0 : -1);
356 set_threads_num(struct configuration *config, int value)
359 assert(config != NULL);
360 config->threads_num = value;
364 * The main configuration routine. Its implementation is hugely inspired by the
365 * the same routine implementation in Solaris NSCD.
368 parse_config_file(struct configuration *config,
369 const char *fname, char const **error_str, int *error_line)
374 int field_count, line_num, value;
378 TRACE_IN(parse_config_file);
379 assert(config != NULL);
380 assert(fname != NULL);
382 fin = fopen(fname, "r");
384 TRACE_OUT(parse_config_file);
391 memset(buffer, 0, sizeof(buffer));
392 while ((res == 0) && (fgets(buffer, sizeof(buffer) - 1, fin) != NULL)) {
393 field_count = strbreak(buffer, fields, sizeof(fields));
396 if (field_count == 0)
399 switch (fields[0][0]) {
404 if ((field_count == 3) &&
405 (strcmp(fields[0], "enable-cache") == 0) &&
406 (check_cachename(fields[1]) == 0) &&
407 ((value = get_yesno(fields[2])) != -1)) {
408 enable_cache(config, fields[1], value);
413 if ((field_count == 2) &&
414 (strcmp(fields[0], "debug-level") == 0) &&
415 ((value = get_number(fields[1], 0, 10)) != -1)) {
420 if ((field_count == 3) &&
421 (strcmp(fields[0], "positive-time-to-live") == 0) &&
422 (check_cachename(fields[1]) == 0) &&
423 ((value = get_number(fields[2], 0, -1)) != -1)) {
428 set_positive_time_to_live(config,
431 } else if ((field_count == 3) &&
432 (strcmp(fields[0], "positive-confidence-threshold") == 0) &&
433 ((value = get_number(fields[2], 1, -1)) != -1)) {
438 set_positive_confidence_threshold(config,
441 } else if ((field_count == 3) &&
442 (strcmp(fields[0], "positive-policy") == 0) &&
443 (check_cachename(fields[1]) == 0) &&
444 ((value = get_policy(fields[2])) != -1)) {
445 set_positive_policy(config, fields[1], value);
447 } else if ((field_count == 3) &&
448 (strcmp(fields[0], "perform-actual-lookups") == 0) &&
449 (check_cachename(fields[1]) == 0) &&
450 ((value = get_yesno(fields[2])) != -1)) {
451 set_perform_actual_lookups(config, fields[1],
457 if ((field_count == 3) &&
458 (strcmp(fields[0], "negative-time-to-live") == 0) &&
459 (check_cachename(fields[1]) == 0) &&
460 ((value = get_number(fields[2], 0, -1)) != -1)) {
465 set_negative_time_to_live(config,
468 } else if ((field_count == 3) &&
469 (strcmp(fields[0], "negative-confidence-threshold") == 0) &&
470 ((value = get_number(fields[2], 1, -1)) != -1)) {
475 set_negative_confidence_threshold(config,
478 } else if ((field_count == 3) &&
479 (strcmp(fields[0], "negative-policy") == 0) &&
480 (check_cachename(fields[1]) == 0) &&
481 ((value = get_policy(fields[2])) != -1)) {
482 set_negative_policy(config,
488 if ((field_count == 3) &&
489 (strcmp(fields[0], "suggested-size") == 0) &&
490 (check_cachename(fields[1]) == 0) &&
491 ((value = get_number(fields[2], 1, -1)) != -1)) {
496 set_suggested_size(config, fields[1], value);
501 if ((field_count == 2) &&
502 (strcmp(fields[0], "threads") == 0) &&
503 ((value = get_number(fields[1], 1, -1)) != -1)) {
504 set_threads_num(config, value);
509 if ((field_count == 3) &&
510 (strcmp(fields[0], "keep-hot-count") == 0) &&
511 (check_cachename(fields[1]) == 0) &&
512 ((value = get_number(fields[2], 0, -1)) != -1)) {
517 set_keep_hot_count(config,
523 if ((field_count == 3) &&
524 (strcmp(fields[0], "check-files") == 0) &&
525 (check_cachename(fields[1]) == 0) &&
526 ((value = get_yesno(fields[2])) != -1)) {
536 if (invalid_value != 0) {
537 LOG_ERR_2("Invalid value for parameter",
538 "error in file %s on line %d",
540 *error_str = "invalid value";
542 LOG_ERR_2("config file parser", "error in file "
543 "%s on line %d", fname, line_num);
544 *error_str = "syntax error";
546 *error_line = line_num;
551 TRACE_OUT(parse_config_file);