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 * Hot count is actually the elements size limit.
174 set_keep_hot_count(struct configuration *config,
175 const char *entry_name, int count)
177 struct configuration_entry *entry;
179 TRACE_IN(set_keep_hot_count);
181 assert(entry_name != NULL);
183 entry = find_create_entry(config, entry_name);
184 assert(entry != NULL);
185 entry->positive_cache_params.max_elemsize = count;
187 entry = find_create_entry(config, entry_name);
188 assert(entry != NULL);
189 entry->negative_cache_params.max_elemsize = count;
191 TRACE_OUT(set_keep_hot_count);
195 set_positive_policy(struct configuration *config,
196 const char *entry_name, enum cache_policy_t policy)
198 struct configuration_entry *entry;
200 TRACE_IN(set_positive_policy);
201 assert(entry_name != NULL);
203 entry = find_create_entry(config, entry_name);
204 assert(entry != NULL);
205 entry->positive_cache_params.policy = policy;
207 TRACE_OUT(set_positive_policy);
211 set_negative_policy(struct configuration *config,
212 const char *entry_name, enum cache_policy_t policy)
214 struct configuration_entry *entry;
216 TRACE_IN(set_negative_policy);
217 assert(entry_name != NULL);
219 entry = find_create_entry(config, entry_name);
220 assert(entry != NULL);
221 entry->negative_cache_params.policy = policy;
223 TRACE_OUT(set_negative_policy);
227 set_perform_actual_lookups(struct configuration *config,
228 const char *entry_name, int flag)
230 struct configuration_entry *entry;
232 TRACE_IN(set_perform_actual_lookups);
233 assert(entry_name != NULL);
235 entry = find_create_entry(config, entry_name);
236 assert(entry != NULL);
237 entry->perform_actual_lookups = flag;
239 TRACE_OUT(set_perform_actual_lookups);
243 set_suggested_size(struct configuration *config,
244 const char *entry_name, int size)
246 struct configuration_entry *entry;
248 TRACE_IN(set_suggested_size);
249 assert(config != NULL);
250 assert(entry_name != NULL);
253 entry = find_create_entry(config, entry_name);
254 assert(entry != NULL);
255 entry->positive_cache_params.cache_entries_size = size;
256 entry->negative_cache_params.cache_entries_size = size;
258 TRACE_OUT(set_suggested_size);
262 check_files(struct configuration *config, const char *entry_name, int flag)
265 TRACE_IN(check_files);
266 assert(entry_name != NULL);
267 TRACE_OUT(check_files);
271 get_yesno(const char *str)
274 if (strcmp(str, "yes") == 0)
276 else if (strcmp(str, "no") == 0)
283 get_number(const char *str, int low, int max)
292 res = strtol(str, &end, 10);
296 if (((res >= low) || (low == -1)) &&
297 ((res <= max) || (max == -1)))
303 static enum cache_policy_t
304 get_policy(const char *str)
307 if (strcmp(str, "fifo") == 0)
309 else if (strcmp(str, "lru") == 0)
311 else if (strcmp(str, "lfu") == 0)
318 check_cachename(const char *str)
322 return ((strlen(str) > 0) ? 0 : -1);
326 set_threads_num(struct configuration *config, int value)
329 assert(config != NULL);
330 config->threads_num = value;
334 * The main configuration routine. Its implementation is hugely inspired by the
335 * the same routine implementation in Solaris NSCD.
338 parse_config_file(struct configuration *config,
339 const char *fname, char const **error_str, int *error_line)
344 int field_count, line_num, value;
347 TRACE_IN(parse_config_file);
348 assert(config != NULL);
349 assert(fname != NULL);
351 fin = fopen(fname, "r");
353 TRACE_OUT(parse_config_file);
359 memset(buffer, 0, sizeof(buffer));
360 while ((res == 0) && (fgets(buffer, sizeof(buffer) - 1, fin) != NULL)) {
361 field_count = strbreak(buffer, fields, sizeof(fields));
364 if (field_count == 0)
367 switch (fields[0][0]) {
372 if ((field_count == 3) &&
373 (strcmp(fields[0], "enable-cache") == 0) &&
374 (check_cachename(fields[1]) == 0) &&
375 ((value = get_yesno(fields[2])) != -1)) {
376 enable_cache(config, fields[1], value);
381 if ((field_count == 2) &&
382 (strcmp(fields[0], "debug-level") == 0) &&
383 ((value = get_number(fields[1], 0, 10)) != -1)) {
388 if ((field_count == 3) &&
389 (strcmp(fields[0], "positive-time-to-live") == 0) &&
390 (check_cachename(fields[1]) == 0) &&
391 ((value = get_number(fields[2], 0, -1)) != -1)) {
392 set_positive_time_to_live(config,
395 } else if ((field_count == 3) &&
396 (strcmp(fields[0], "positive-policy") == 0) &&
397 (check_cachename(fields[1]) == 0) &&
398 ((value = get_policy(fields[2])) != -1)) {
399 set_positive_policy(config, fields[1], value);
401 } else if ((field_count == 3) &&
402 (strcmp(fields[0], "perform-actual-lookups") == 0) &&
403 (check_cachename(fields[1]) == 0) &&
404 ((value = get_yesno(fields[2])) != -1)) {
405 set_perform_actual_lookups(config, fields[1],
411 if ((field_count == 3) &&
412 (strcmp(fields[0], "negative-time-to-live") == 0) &&
413 (check_cachename(fields[1]) == 0) &&
414 ((value = get_number(fields[2], 0, -1)) != -1)) {
415 set_negative_time_to_live(config,
418 } else if ((field_count == 3) &&
419 (strcmp(fields[0], "negative-policy") == 0) &&
420 (check_cachename(fields[1]) == 0) &&
421 ((value = get_policy(fields[2])) != -1)) {
422 set_negative_policy(config,
428 if ((field_count == 3) &&
429 (strcmp(fields[0], "suggested-size") == 0) &&
430 (check_cachename(fields[1]) == 0) &&
431 ((value = get_number(fields[2], 1, -1)) != -1)) {
432 set_suggested_size(config, fields[1], value);
437 if ((field_count == 2) &&
438 (strcmp(fields[0], "threads") == 0) &&
439 ((value = get_number(fields[1], 1, -1)) != -1)) {
440 set_threads_num(config, value);
445 if ((field_count == 3) &&
446 (strcmp(fields[0], "keep-hot-count") == 0) &&
447 (check_cachename(fields[1]) == 0) &&
448 ((value = get_number(fields[2], 0, -1)) != -1)) {
449 set_keep_hot_count(config,
455 if ((field_count == 3) &&
456 (strcmp(fields[0], "check-files") == 0) &&
457 (check_cachename(fields[1]) == 0) &&
458 ((value = get_yesno(fields[2])) != -1)) {
468 LOG_ERR_2("config file parser", "error in file "
469 "%s on line %d", fname, line_num);
470 *error_str = "syntax error";
471 *error_line = line_num;
476 TRACE_OUT(parse_config_file);