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
);