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$");
39 static void enable_cache(struct configuration *,const char *, int);
40 static struct configuration_entry *find_create_entry(struct configuration *,
42 static int get_number(const char *, int, int);
43 static enum cache_policy_t get_policy(const char *);
44 static int get_yesno(const char *);
45 static int check_cachename(const char *);
46 static void check_files(struct configuration *, const char *, int);
47 static void set_keep_hot_count(struct configuration *, const char *, int);
48 static void set_negative_policy(struct configuration *, const char *,
50 static void set_negative_time_to_live(struct configuration *,
52 static void set_positive_policy(struct configuration *, const char *,
54 static void set_perform_actual_lookups(struct configuration *, const char *,
56 static void set_positive_time_to_live(struct configuration *,
58 static void set_suggested_size(struct configuration *, const char *,
60 static void set_threads_num(struct configuration *, int);
61 static int strbreak(char *, char **, int);
64 strbreak(char *str, char **fields, int fields_size)
73 strsep(i < fields_size ? &c : NULL, "\n\t ")) != NULL);
75 if ((*(*fields)) != '\0') {
85 * Tries to find the configuration entry with the specified name. If search
86 * fails, the new entry with the default parameters will be created.
88 static struct configuration_entry *
89 find_create_entry(struct configuration *config,
90 const char *entry_name)
92 struct configuration_entry *entry = NULL;
95 TRACE_IN(find_create_entry);
96 entry = configuration_find_entry(config, entry_name);
98 entry = create_def_configuration_entry(entry_name);
99 assert( entry != NULL);
100 res = add_configuration_entry(config, entry);
104 TRACE_OUT(find_create_entry);
109 * The vast majority of the functions below corresponds to the particular
110 * keywords in the configuration file.
113 enable_cache(struct configuration *config, const char *entry_name, int flag)
115 struct configuration_entry *entry;
117 TRACE_IN(enable_cache);
118 entry = find_create_entry(config, entry_name);
119 entry->enabled = flag;
120 TRACE_OUT(enable_cache);
124 set_positive_time_to_live(struct configuration *config,
125 const char *entry_name, int ttl)
127 struct configuration_entry *entry;
128 struct timeval lifetime;
130 TRACE_IN(set_positive_time_to_live);
132 assert(entry_name != NULL);
133 memset(&lifetime, 0, sizeof(struct timeval));
134 lifetime.tv_sec = ttl;
136 entry = find_create_entry(config, entry_name);
137 memcpy(&entry->positive_cache_params.max_lifetime,
138 &lifetime, sizeof(struct timeval));
139 memcpy(&entry->mp_cache_params.max_lifetime,
140 &lifetime, sizeof(struct timeval));
142 TRACE_OUT(set_positive_time_to_live);
146 set_negative_time_to_live(struct configuration *config,
147 const char *entry_name, int nttl)
149 struct configuration_entry *entry;
150 struct timeval lifetime;
152 TRACE_IN(set_negative_time_to_live);
154 assert(entry_name != NULL);
155 memset(&lifetime, 0, sizeof(struct timeval));
156 lifetime.tv_sec = nttl;
158 entry = find_create_entry(config, entry_name);
159 assert(entry != NULL);
160 memcpy(&entry->negative_cache_params.max_lifetime,
161 &lifetime, sizeof(struct timeval));
163 TRACE_OUT(set_negative_time_to_live);
167 * Hot count is actually the elements size limit.
170 set_keep_hot_count(struct configuration *config,
171 const char *entry_name, int count)
173 struct configuration_entry *entry;
175 TRACE_IN(set_keep_hot_count);
177 assert(entry_name != NULL);
179 entry = find_create_entry(config, entry_name);
180 assert(entry != NULL);
181 entry->positive_cache_params.max_elemsize = count;
183 entry = find_create_entry(config, entry_name);
184 assert(entry != NULL);
185 entry->negative_cache_params.max_elemsize = count;
187 TRACE_OUT(set_keep_hot_count);
191 set_positive_policy(struct configuration *config,
192 const char *entry_name, enum cache_policy_t policy)
194 struct configuration_entry *entry;
196 TRACE_IN(set_positive_policy);
197 assert(entry_name != NULL);
199 entry = find_create_entry(config, entry_name);
200 assert(entry != NULL);
201 entry->positive_cache_params.policy = policy;
203 TRACE_OUT(set_positive_policy);
207 set_negative_policy(struct configuration *config,
208 const char *entry_name, enum cache_policy_t policy)
210 struct configuration_entry *entry;
212 TRACE_IN(set_negative_policy);
213 assert(entry_name != NULL);
215 entry = find_create_entry(config, entry_name);
216 assert(entry != NULL);
217 entry->negative_cache_params.policy = policy;
219 TRACE_OUT(set_negative_policy);
223 set_perform_actual_lookups(struct configuration *config,
224 const char *entry_name, int flag)
226 struct configuration_entry *entry;
228 TRACE_IN(set_perform_actual_lookups);
229 assert(entry_name != NULL);
231 entry = find_create_entry(config, entry_name);
232 assert(entry != NULL);
233 entry->perform_actual_lookups = flag;
235 TRACE_OUT(set_perform_actual_lookups);
239 set_suggested_size(struct configuration *config,
240 const char *entry_name, int size)
242 struct configuration_entry *entry;
244 TRACE_IN(set_suggested_size);
245 assert(config != NULL);
246 assert(entry_name != NULL);
249 entry = find_create_entry(config, entry_name);
250 assert(entry != NULL);
251 entry->positive_cache_params.cache_entries_size = size;
252 entry->negative_cache_params.cache_entries_size = size;
254 TRACE_OUT(set_suggested_size);
258 check_files(struct configuration *config, const char *entry_name, int flag)
261 TRACE_IN(check_files);
262 assert(entry_name != NULL);
263 TRACE_OUT(check_files);
267 get_yesno(const char *str)
270 if (strcmp(str, "yes") == 0)
272 else if (strcmp(str, "no") == 0)
279 get_number(const char *str, int low, int max)
288 res = strtol(str, &end, 10);
292 if (((res >= low) || (low == -1)) &&
293 ((res <= max) || (max == -1)))
299 static enum cache_policy_t
300 get_policy(const char *str)
303 if (strcmp(str, "fifo") == 0)
305 else if (strcmp(str, "lru") == 0)
307 else if (strcmp(str, "lfu") == 0)
314 check_cachename(const char *str)
318 return ((strlen(str) > 0) ? 0 : -1);
322 set_threads_num(struct configuration *config, int value)
325 assert(config != NULL);
326 config->threads_num = value;
330 * The main configuration routine. Its implementation is hugely inspired by the
331 * the same routine implementation in Solaris NSCD.
334 parse_config_file(struct configuration *config,
335 const char *fname, char const **error_str, int *error_line)
340 int field_count, line_num, value;
343 TRACE_IN(parse_config_file);
344 assert(config != NULL);
345 assert(fname != NULL);
347 fin = fopen(fname, "r");
349 TRACE_OUT(parse_config_file);
355 memset(buffer, 0, sizeof(buffer));
356 while ((res == 0) && (fgets(buffer, sizeof(buffer) - 1, fin) != NULL)) {
357 field_count = strbreak(buffer, fields, sizeof(fields));
360 if (field_count == 0)
363 switch (fields[0][0]) {
368 if ((field_count == 3) &&
369 (strcmp(fields[0], "enable-cache") == 0) &&
370 (check_cachename(fields[1]) == 0) &&
371 ((value = get_yesno(fields[2])) != -1)) {
372 enable_cache(config, fields[1], value);
377 if ((field_count == 2) &&
378 (strcmp(fields[0], "debug-level") == 0) &&
379 ((value = get_number(fields[1], 0, 10)) != -1)) {
384 if ((field_count == 3) &&
385 (strcmp(fields[0], "positive-time-to-live") == 0) &&
386 (check_cachename(fields[1]) == 0) &&
387 ((value = get_number(fields[2], 0, -1)) != -1)) {
388 set_positive_time_to_live(config,
391 } else if ((field_count == 3) &&
392 (strcmp(fields[0], "positive-policy") == 0) &&
393 (check_cachename(fields[1]) == 0) &&
394 ((value = get_policy(fields[2])) != -1)) {
395 set_positive_policy(config, fields[1], value);
397 } else if ((field_count == 3) &&
398 (strcmp(fields[0], "perform-actual-lookups") == 0) &&
399 (check_cachename(fields[1]) == 0) &&
400 ((value = get_yesno(fields[2])) != -1)) {
401 set_perform_actual_lookups(config, fields[1],
407 if ((field_count == 3) &&
408 (strcmp(fields[0], "negative-time-to-live") == 0) &&
409 (check_cachename(fields[1]) == 0) &&
410 ((value = get_number(fields[2], 0, -1)) != -1)) {
411 set_negative_time_to_live(config,
414 } else if ((field_count == 3) &&
415 (strcmp(fields[0], "negative-policy") == 0) &&
416 (check_cachename(fields[1]) == 0) &&
417 ((value = get_policy(fields[2])) != -1)) {
418 set_negative_policy(config,
424 if ((field_count == 3) &&
425 (strcmp(fields[0], "suggested-size") == 0) &&
426 (check_cachename(fields[1]) == 0) &&
427 ((value = get_number(fields[2], 1, -1)) != -1)) {
428 set_suggested_size(config, fields[1], value);
433 if ((field_count == 2) &&
434 (strcmp(fields[0], "threads") == 0) &&
435 ((value = get_number(fields[1], 1, -1)) != -1)) {
436 set_threads_num(config, value);
441 if ((field_count == 3) &&
442 (strcmp(fields[0], "keep-hot-count") == 0) &&
443 (check_cachename(fields[1]) == 0) &&
444 ((value = get_number(fields[2], 0, -1)) != -1)) {
445 set_keep_hot_count(config,
451 if ((field_count == 3) &&
452 (strcmp(fields[0], "check-files") == 0) &&
453 (check_cachename(fields[1]) == 0) &&
454 ((value = get_yesno(fields[2])) != -1)) {
464 LOG_ERR_2("config file parser", "error in file "
465 "%s on line %d", fname, line_num);
466 *error_str = "syntax error";
467 *error_line = line_num;
472 TRACE_OUT(parse_config_file);