1*86d7f5d3SJohn Marino /*-
2*86d7f5d3SJohn Marino * Copyright (c) 2005 Michael Bushkov <bushman@rsu.ru>
3*86d7f5d3SJohn Marino * All rights reserved.
4*86d7f5d3SJohn Marino *
5*86d7f5d3SJohn Marino * Redistribution and use in source and binary forms, with or without
6*86d7f5d3SJohn Marino * modification, are permitted provided that the following conditions
7*86d7f5d3SJohn Marino * are met:
8*86d7f5d3SJohn Marino * 1. Redistributions of source code must retain the above copyright
9*86d7f5d3SJohn Marino * notice, this list of conditions and the following disclaimer.
10*86d7f5d3SJohn Marino * 2. Redistributions in binary form must reproduce the above copyright
11*86d7f5d3SJohn Marino * notice, this list of conditions and the following disclaimer in the
12*86d7f5d3SJohn Marino * documentation and/or other materials provided with the distribution.
13*86d7f5d3SJohn Marino *
14*86d7f5d3SJohn Marino * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
15*86d7f5d3SJohn Marino * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16*86d7f5d3SJohn Marino * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17*86d7f5d3SJohn Marino * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
18*86d7f5d3SJohn Marino * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19*86d7f5d3SJohn Marino * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20*86d7f5d3SJohn Marino * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21*86d7f5d3SJohn Marino * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22*86d7f5d3SJohn Marino * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23*86d7f5d3SJohn Marino * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24*86d7f5d3SJohn Marino * SUCH DAMAGE.
25*86d7f5d3SJohn Marino *
26*86d7f5d3SJohn Marino * $FreeBSD: src/usr.sbin/nscd/config.c,v 1.3 2008/10/12 00:44:27 delphij Exp $
27*86d7f5d3SJohn Marino */
28*86d7f5d3SJohn Marino
29*86d7f5d3SJohn Marino #include <assert.h>
30*86d7f5d3SJohn Marino #include <math.h>
31*86d7f5d3SJohn Marino #include <stdio.h>
32*86d7f5d3SJohn Marino #include <stdlib.h>
33*86d7f5d3SJohn Marino #include <string.h>
34*86d7f5d3SJohn Marino #include "config.h"
35*86d7f5d3SJohn Marino #include "debug.h"
36*86d7f5d3SJohn Marino #include "log.h"
37*86d7f5d3SJohn Marino
38*86d7f5d3SJohn Marino /*
39*86d7f5d3SJohn Marino * Default entries, which always exist in the configuration
40*86d7f5d3SJohn Marino */
41*86d7f5d3SJohn Marino const char *c_default_entries[6] = {
42*86d7f5d3SJohn Marino NSDB_PASSWD,
43*86d7f5d3SJohn Marino NSDB_GROUP,
44*86d7f5d3SJohn Marino NSDB_HOSTS,
45*86d7f5d3SJohn Marino NSDB_SERVICES,
46*86d7f5d3SJohn Marino NSDB_PROTOCOLS,
47*86d7f5d3SJohn Marino NSDB_RPC
48*86d7f5d3SJohn Marino };
49*86d7f5d3SJohn Marino
50*86d7f5d3SJohn Marino static int configuration_entry_cmp(const void *, const void *);
51*86d7f5d3SJohn Marino static int configuration_entry_sort_cmp(const void *, const void *);
52*86d7f5d3SJohn Marino static int configuration_entry_cache_mp_sort_cmp(const void *, const void *);
53*86d7f5d3SJohn Marino static int configuration_entry_cache_mp_cmp(const void *, const void *);
54*86d7f5d3SJohn Marino static int configuration_entry_cache_mp_part_cmp(const void *, const void *);
55*86d7f5d3SJohn Marino static struct configuration_entry *create_configuration_entry(const char *,
56*86d7f5d3SJohn Marino struct timeval const *, struct timeval const *,
57*86d7f5d3SJohn Marino struct common_cache_entry_params const *,
58*86d7f5d3SJohn Marino struct common_cache_entry_params const *,
59*86d7f5d3SJohn Marino struct mp_cache_entry_params const *);
60*86d7f5d3SJohn Marino
61*86d7f5d3SJohn Marino static int
configuration_entry_sort_cmp(const void * e1,const void * e2)62*86d7f5d3SJohn Marino configuration_entry_sort_cmp(const void *e1, const void *e2)
63*86d7f5d3SJohn Marino {
64*86d7f5d3SJohn Marino return (strcmp((*((struct configuration_entry **)e1))->name,
65*86d7f5d3SJohn Marino (*((struct configuration_entry **)e2))->name
66*86d7f5d3SJohn Marino ));
67*86d7f5d3SJohn Marino }
68*86d7f5d3SJohn Marino
69*86d7f5d3SJohn Marino static int
configuration_entry_cmp(const void * e1,const void * e2)70*86d7f5d3SJohn Marino configuration_entry_cmp(const void *e1, const void *e2)
71*86d7f5d3SJohn Marino {
72*86d7f5d3SJohn Marino return (strcmp((const char *)e1,
73*86d7f5d3SJohn Marino (*((struct configuration_entry **)e2))->name
74*86d7f5d3SJohn Marino ));
75*86d7f5d3SJohn Marino }
76*86d7f5d3SJohn Marino
77*86d7f5d3SJohn Marino static int
configuration_entry_cache_mp_sort_cmp(const void * e1,const void * e2)78*86d7f5d3SJohn Marino configuration_entry_cache_mp_sort_cmp(const void *e1, const void *e2)
79*86d7f5d3SJohn Marino {
80*86d7f5d3SJohn Marino return (strcmp((*((cache_entry *)e1))->params->entry_name,
81*86d7f5d3SJohn Marino (*((cache_entry *)e2))->params->entry_name
82*86d7f5d3SJohn Marino ));
83*86d7f5d3SJohn Marino }
84*86d7f5d3SJohn Marino
85*86d7f5d3SJohn Marino static int
configuration_entry_cache_mp_cmp(const void * e1,const void * e2)86*86d7f5d3SJohn Marino configuration_entry_cache_mp_cmp(const void *e1, const void *e2)
87*86d7f5d3SJohn Marino {
88*86d7f5d3SJohn Marino return (strcmp((const char *)e1,
89*86d7f5d3SJohn Marino (*((cache_entry *)e2))->params->entry_name
90*86d7f5d3SJohn Marino ));
91*86d7f5d3SJohn Marino }
92*86d7f5d3SJohn Marino
93*86d7f5d3SJohn Marino static int
configuration_entry_cache_mp_part_cmp(const void * e1,const void * e2)94*86d7f5d3SJohn Marino configuration_entry_cache_mp_part_cmp(const void *e1, const void *e2)
95*86d7f5d3SJohn Marino {
96*86d7f5d3SJohn Marino return (strncmp((const char *)e1,
97*86d7f5d3SJohn Marino (*((cache_entry *)e2))->params->entry_name,
98*86d7f5d3SJohn Marino strlen((const char *)e1)
99*86d7f5d3SJohn Marino ));
100*86d7f5d3SJohn Marino }
101*86d7f5d3SJohn Marino
102*86d7f5d3SJohn Marino static struct configuration_entry *
create_configuration_entry(const char * name,struct timeval const * common_timeout,struct timeval const * mp_timeout,struct common_cache_entry_params const * positive_params,struct common_cache_entry_params const * negative_params,struct mp_cache_entry_params const * mp_params)103*86d7f5d3SJohn Marino create_configuration_entry(const char *name,
104*86d7f5d3SJohn Marino struct timeval const *common_timeout,
105*86d7f5d3SJohn Marino struct timeval const *mp_timeout,
106*86d7f5d3SJohn Marino struct common_cache_entry_params const *positive_params,
107*86d7f5d3SJohn Marino struct common_cache_entry_params const *negative_params,
108*86d7f5d3SJohn Marino struct mp_cache_entry_params const *mp_params)
109*86d7f5d3SJohn Marino {
110*86d7f5d3SJohn Marino struct configuration_entry *retval;
111*86d7f5d3SJohn Marino size_t size;
112*86d7f5d3SJohn Marino int res;
113*86d7f5d3SJohn Marino
114*86d7f5d3SJohn Marino TRACE_IN(create_configuration_entry);
115*86d7f5d3SJohn Marino assert(name != NULL);
116*86d7f5d3SJohn Marino assert(positive_params != NULL);
117*86d7f5d3SJohn Marino assert(negative_params != NULL);
118*86d7f5d3SJohn Marino assert(mp_params != NULL);
119*86d7f5d3SJohn Marino
120*86d7f5d3SJohn Marino retval = (struct configuration_entry *)calloc(1,
121*86d7f5d3SJohn Marino sizeof(struct configuration_entry));
122*86d7f5d3SJohn Marino assert(retval != NULL);
123*86d7f5d3SJohn Marino
124*86d7f5d3SJohn Marino res = pthread_mutex_init(&retval->positive_cache_lock, NULL);
125*86d7f5d3SJohn Marino if (res != 0) {
126*86d7f5d3SJohn Marino free(retval);
127*86d7f5d3SJohn Marino LOG_ERR_2("create_configuration_entry",
128*86d7f5d3SJohn Marino "can't create positive cache lock");
129*86d7f5d3SJohn Marino TRACE_OUT(create_configuration_entry);
130*86d7f5d3SJohn Marino return (NULL);
131*86d7f5d3SJohn Marino }
132*86d7f5d3SJohn Marino
133*86d7f5d3SJohn Marino res = pthread_mutex_init(&retval->negative_cache_lock, NULL);
134*86d7f5d3SJohn Marino if (res != 0) {
135*86d7f5d3SJohn Marino pthread_mutex_destroy(&retval->positive_cache_lock);
136*86d7f5d3SJohn Marino free(retval);
137*86d7f5d3SJohn Marino LOG_ERR_2("create_configuration_entry",
138*86d7f5d3SJohn Marino "can't create negative cache lock");
139*86d7f5d3SJohn Marino TRACE_OUT(create_configuration_entry);
140*86d7f5d3SJohn Marino return (NULL);
141*86d7f5d3SJohn Marino }
142*86d7f5d3SJohn Marino
143*86d7f5d3SJohn Marino res = pthread_mutex_init(&retval->mp_cache_lock, NULL);
144*86d7f5d3SJohn Marino if (res != 0) {
145*86d7f5d3SJohn Marino pthread_mutex_destroy(&retval->positive_cache_lock);
146*86d7f5d3SJohn Marino pthread_mutex_destroy(&retval->negative_cache_lock);
147*86d7f5d3SJohn Marino free(retval);
148*86d7f5d3SJohn Marino LOG_ERR_2("create_configuration_entry",
149*86d7f5d3SJohn Marino "can't create negative cache lock");
150*86d7f5d3SJohn Marino TRACE_OUT(create_configuration_entry);
151*86d7f5d3SJohn Marino return (NULL);
152*86d7f5d3SJohn Marino }
153*86d7f5d3SJohn Marino
154*86d7f5d3SJohn Marino memcpy(&retval->positive_cache_params, positive_params,
155*86d7f5d3SJohn Marino sizeof(struct common_cache_entry_params));
156*86d7f5d3SJohn Marino memcpy(&retval->negative_cache_params, negative_params,
157*86d7f5d3SJohn Marino sizeof(struct common_cache_entry_params));
158*86d7f5d3SJohn Marino memcpy(&retval->mp_cache_params, mp_params,
159*86d7f5d3SJohn Marino sizeof(struct mp_cache_entry_params));
160*86d7f5d3SJohn Marino
161*86d7f5d3SJohn Marino size = strlen(name);
162*86d7f5d3SJohn Marino retval->name = (char *)calloc(1, size + 1);
163*86d7f5d3SJohn Marino assert(retval->name != NULL);
164*86d7f5d3SJohn Marino memcpy(retval->name, name, size);
165*86d7f5d3SJohn Marino
166*86d7f5d3SJohn Marino memcpy(&retval->common_query_timeout, common_timeout,
167*86d7f5d3SJohn Marino sizeof(struct timeval));
168*86d7f5d3SJohn Marino memcpy(&retval->mp_query_timeout, mp_timeout,
169*86d7f5d3SJohn Marino sizeof(struct timeval));
170*86d7f5d3SJohn Marino
171*86d7f5d3SJohn Marino asprintf(&retval->positive_cache_params.entry_name, "%s+", name);
172*86d7f5d3SJohn Marino assert(retval->positive_cache_params.entry_name != NULL);
173*86d7f5d3SJohn Marino
174*86d7f5d3SJohn Marino asprintf(&retval->negative_cache_params.entry_name, "%s-", name);
175*86d7f5d3SJohn Marino assert(retval->negative_cache_params.entry_name != NULL);
176*86d7f5d3SJohn Marino
177*86d7f5d3SJohn Marino asprintf(&retval->mp_cache_params.entry_name, "%s*", name);
178*86d7f5d3SJohn Marino assert(retval->mp_cache_params.entry_name != NULL);
179*86d7f5d3SJohn Marino
180*86d7f5d3SJohn Marino TRACE_OUT(create_configuration_entry);
181*86d7f5d3SJohn Marino return (retval);
182*86d7f5d3SJohn Marino }
183*86d7f5d3SJohn Marino
184*86d7f5d3SJohn Marino /*
185*86d7f5d3SJohn Marino * Creates configuration entry and fills it with default values
186*86d7f5d3SJohn Marino */
187*86d7f5d3SJohn Marino struct configuration_entry *
create_def_configuration_entry(const char * name)188*86d7f5d3SJohn Marino create_def_configuration_entry(const char *name)
189*86d7f5d3SJohn Marino {
190*86d7f5d3SJohn Marino struct common_cache_entry_params positive_params, negative_params;
191*86d7f5d3SJohn Marino struct mp_cache_entry_params mp_params;
192*86d7f5d3SJohn Marino struct timeval default_common_timeout, default_mp_timeout;
193*86d7f5d3SJohn Marino
194*86d7f5d3SJohn Marino struct configuration_entry *res = NULL;
195*86d7f5d3SJohn Marino
196*86d7f5d3SJohn Marino TRACE_IN(create_def_configuration_entry);
197*86d7f5d3SJohn Marino memset(&positive_params, 0,
198*86d7f5d3SJohn Marino sizeof(struct common_cache_entry_params));
199*86d7f5d3SJohn Marino positive_params.entry_type = CET_COMMON;
200*86d7f5d3SJohn Marino positive_params.cache_entries_size = DEFAULT_CACHE_HT_SIZE;
201*86d7f5d3SJohn Marino positive_params.max_elemsize = DEFAULT_POSITIVE_ELEMENTS_SIZE;
202*86d7f5d3SJohn Marino positive_params.satisf_elemsize = DEFAULT_POSITIVE_ELEMENTS_SIZE / 2;
203*86d7f5d3SJohn Marino positive_params.max_lifetime.tv_sec = DEFAULT_POSITIVE_LIFETIME;
204*86d7f5d3SJohn Marino positive_params.policy = CPT_LRU;
205*86d7f5d3SJohn Marino
206*86d7f5d3SJohn Marino memcpy(&negative_params, &positive_params,
207*86d7f5d3SJohn Marino sizeof(struct common_cache_entry_params));
208*86d7f5d3SJohn Marino negative_params.max_elemsize = DEFAULT_NEGATIVE_ELEMENTS_SIZE;
209*86d7f5d3SJohn Marino negative_params.satisf_elemsize = DEFAULT_NEGATIVE_ELEMENTS_SIZE / 2;
210*86d7f5d3SJohn Marino negative_params.max_lifetime.tv_sec = DEFAULT_NEGATIVE_LIFETIME;
211*86d7f5d3SJohn Marino negative_params.policy = CPT_FIFO;
212*86d7f5d3SJohn Marino
213*86d7f5d3SJohn Marino memset(&default_common_timeout, 0, sizeof(struct timeval));
214*86d7f5d3SJohn Marino default_common_timeout.tv_sec = DEFAULT_COMMON_ENTRY_TIMEOUT;
215*86d7f5d3SJohn Marino
216*86d7f5d3SJohn Marino memset(&default_mp_timeout, 0, sizeof(struct timeval));
217*86d7f5d3SJohn Marino default_mp_timeout.tv_sec = DEFAULT_MP_ENTRY_TIMEOUT;
218*86d7f5d3SJohn Marino
219*86d7f5d3SJohn Marino memset(&mp_params, 0,
220*86d7f5d3SJohn Marino sizeof(struct mp_cache_entry_params));
221*86d7f5d3SJohn Marino mp_params.entry_type = CET_MULTIPART;
222*86d7f5d3SJohn Marino mp_params.max_elemsize = DEFAULT_MULTIPART_ELEMENTS_SIZE;
223*86d7f5d3SJohn Marino mp_params.max_sessions = DEFAULT_MULITPART_SESSIONS_SIZE;
224*86d7f5d3SJohn Marino mp_params.max_lifetime.tv_sec = DEFAULT_MULITPART_LIFETIME;
225*86d7f5d3SJohn Marino
226*86d7f5d3SJohn Marino res = create_configuration_entry(name, &default_common_timeout,
227*86d7f5d3SJohn Marino &default_mp_timeout, &positive_params, &negative_params,
228*86d7f5d3SJohn Marino &mp_params);
229*86d7f5d3SJohn Marino
230*86d7f5d3SJohn Marino TRACE_OUT(create_def_configuration_entry);
231*86d7f5d3SJohn Marino return (res);
232*86d7f5d3SJohn Marino }
233*86d7f5d3SJohn Marino
234*86d7f5d3SJohn Marino void
destroy_configuration_entry(struct configuration_entry * entry)235*86d7f5d3SJohn Marino destroy_configuration_entry(struct configuration_entry *entry)
236*86d7f5d3SJohn Marino {
237*86d7f5d3SJohn Marino TRACE_IN(destroy_configuration_entry);
238*86d7f5d3SJohn Marino assert(entry != NULL);
239*86d7f5d3SJohn Marino pthread_mutex_destroy(&entry->positive_cache_lock);
240*86d7f5d3SJohn Marino pthread_mutex_destroy(&entry->negative_cache_lock);
241*86d7f5d3SJohn Marino pthread_mutex_destroy(&entry->mp_cache_lock);
242*86d7f5d3SJohn Marino free(entry->name);
243*86d7f5d3SJohn Marino free(entry->positive_cache_params.entry_name);
244*86d7f5d3SJohn Marino free(entry->negative_cache_params.entry_name);
245*86d7f5d3SJohn Marino free(entry->mp_cache_params.entry_name);
246*86d7f5d3SJohn Marino free(entry->mp_cache_entries);
247*86d7f5d3SJohn Marino free(entry);
248*86d7f5d3SJohn Marino TRACE_OUT(destroy_configuration_entry);
249*86d7f5d3SJohn Marino }
250*86d7f5d3SJohn Marino
251*86d7f5d3SJohn Marino int
add_configuration_entry(struct configuration * config,struct configuration_entry * entry)252*86d7f5d3SJohn Marino add_configuration_entry(struct configuration *config,
253*86d7f5d3SJohn Marino struct configuration_entry *entry)
254*86d7f5d3SJohn Marino {
255*86d7f5d3SJohn Marino TRACE_IN(add_configuration_entry);
256*86d7f5d3SJohn Marino assert(entry != NULL);
257*86d7f5d3SJohn Marino assert(entry->name != NULL);
258*86d7f5d3SJohn Marino if (configuration_find_entry(config, entry->name) != NULL) {
259*86d7f5d3SJohn Marino TRACE_OUT(add_configuration_entry);
260*86d7f5d3SJohn Marino return (-1);
261*86d7f5d3SJohn Marino }
262*86d7f5d3SJohn Marino
263*86d7f5d3SJohn Marino if (config->entries_size == config->entries_capacity) {
264*86d7f5d3SJohn Marino struct configuration_entry **new_entries;
265*86d7f5d3SJohn Marino
266*86d7f5d3SJohn Marino config->entries_capacity *= 2;
267*86d7f5d3SJohn Marino new_entries = (struct configuration_entry **)calloc(1,
268*86d7f5d3SJohn Marino sizeof(struct configuration_entry *) *
269*86d7f5d3SJohn Marino config->entries_capacity);
270*86d7f5d3SJohn Marino assert(new_entries != NULL);
271*86d7f5d3SJohn Marino memcpy(new_entries, config->entries,
272*86d7f5d3SJohn Marino sizeof(struct configuration_entry *) *
273*86d7f5d3SJohn Marino config->entries_size);
274*86d7f5d3SJohn Marino
275*86d7f5d3SJohn Marino free(config->entries);
276*86d7f5d3SJohn Marino config->entries = new_entries;
277*86d7f5d3SJohn Marino }
278*86d7f5d3SJohn Marino
279*86d7f5d3SJohn Marino config->entries[config->entries_size++] = entry;
280*86d7f5d3SJohn Marino qsort(config->entries, config->entries_size,
281*86d7f5d3SJohn Marino sizeof(struct configuration_entry *),
282*86d7f5d3SJohn Marino configuration_entry_sort_cmp);
283*86d7f5d3SJohn Marino
284*86d7f5d3SJohn Marino TRACE_OUT(add_configuration_entry);
285*86d7f5d3SJohn Marino return (0);
286*86d7f5d3SJohn Marino }
287*86d7f5d3SJohn Marino
288*86d7f5d3SJohn Marino size_t
configuration_get_entries_size(struct configuration * config)289*86d7f5d3SJohn Marino configuration_get_entries_size(struct configuration *config)
290*86d7f5d3SJohn Marino {
291*86d7f5d3SJohn Marino TRACE_IN(configuration_get_entries_size);
292*86d7f5d3SJohn Marino assert(config != NULL);
293*86d7f5d3SJohn Marino TRACE_OUT(configuration_get_entries_size);
294*86d7f5d3SJohn Marino return (config->entries_size);
295*86d7f5d3SJohn Marino }
296*86d7f5d3SJohn Marino
297*86d7f5d3SJohn Marino struct configuration_entry *
configuration_get_entry(struct configuration * config,size_t index)298*86d7f5d3SJohn Marino configuration_get_entry(struct configuration *config, size_t index)
299*86d7f5d3SJohn Marino {
300*86d7f5d3SJohn Marino TRACE_IN(configuration_get_entry);
301*86d7f5d3SJohn Marino assert(config != NULL);
302*86d7f5d3SJohn Marino assert(index < config->entries_size);
303*86d7f5d3SJohn Marino TRACE_OUT(configuration_get_entry);
304*86d7f5d3SJohn Marino return (config->entries[index]);
305*86d7f5d3SJohn Marino }
306*86d7f5d3SJohn Marino
307*86d7f5d3SJohn Marino struct configuration_entry *
configuration_find_entry(struct configuration * config,const char * name)308*86d7f5d3SJohn Marino configuration_find_entry(struct configuration *config,
309*86d7f5d3SJohn Marino const char *name)
310*86d7f5d3SJohn Marino {
311*86d7f5d3SJohn Marino struct configuration_entry **retval;
312*86d7f5d3SJohn Marino
313*86d7f5d3SJohn Marino TRACE_IN(configuration_find_entry);
314*86d7f5d3SJohn Marino
315*86d7f5d3SJohn Marino retval = bsearch(name, config->entries, config->entries_size,
316*86d7f5d3SJohn Marino sizeof(struct configuration_entry *), configuration_entry_cmp);
317*86d7f5d3SJohn Marino TRACE_OUT(configuration_find_entry);
318*86d7f5d3SJohn Marino
319*86d7f5d3SJohn Marino return ((retval != NULL) ? *retval : NULL);
320*86d7f5d3SJohn Marino }
321*86d7f5d3SJohn Marino
322*86d7f5d3SJohn Marino /*
323*86d7f5d3SJohn Marino * All multipart cache entries are stored in the configuration_entry in the
324*86d7f5d3SJohn Marino * sorted array (sorted by names). The 3 functions below manage this array.
325*86d7f5d3SJohn Marino */
326*86d7f5d3SJohn Marino
327*86d7f5d3SJohn Marino int
configuration_entry_add_mp_cache_entry(struct configuration_entry * config_entry,cache_entry c_entry)328*86d7f5d3SJohn Marino configuration_entry_add_mp_cache_entry(struct configuration_entry *config_entry,
329*86d7f5d3SJohn Marino cache_entry c_entry)
330*86d7f5d3SJohn Marino {
331*86d7f5d3SJohn Marino cache_entry *new_mp_entries, *old_mp_entries;
332*86d7f5d3SJohn Marino
333*86d7f5d3SJohn Marino TRACE_IN(configuration_entry_add_mp_cache_entry);
334*86d7f5d3SJohn Marino ++config_entry->mp_cache_entries_size;
335*86d7f5d3SJohn Marino new_mp_entries = (cache_entry *)malloc(sizeof(cache_entry) *
336*86d7f5d3SJohn Marino config_entry->mp_cache_entries_size);
337*86d7f5d3SJohn Marino assert(new_mp_entries != NULL);
338*86d7f5d3SJohn Marino new_mp_entries[0] = c_entry;
339*86d7f5d3SJohn Marino
340*86d7f5d3SJohn Marino if (config_entry->mp_cache_entries_size - 1 > 0) {
341*86d7f5d3SJohn Marino memcpy(new_mp_entries + 1,
342*86d7f5d3SJohn Marino config_entry->mp_cache_entries,
343*86d7f5d3SJohn Marino (config_entry->mp_cache_entries_size - 1) *
344*86d7f5d3SJohn Marino sizeof(cache_entry));
345*86d7f5d3SJohn Marino }
346*86d7f5d3SJohn Marino
347*86d7f5d3SJohn Marino old_mp_entries = config_entry->mp_cache_entries;
348*86d7f5d3SJohn Marino config_entry->mp_cache_entries = new_mp_entries;
349*86d7f5d3SJohn Marino free(old_mp_entries);
350*86d7f5d3SJohn Marino
351*86d7f5d3SJohn Marino qsort(config_entry->mp_cache_entries,
352*86d7f5d3SJohn Marino config_entry->mp_cache_entries_size,
353*86d7f5d3SJohn Marino sizeof(cache_entry),
354*86d7f5d3SJohn Marino configuration_entry_cache_mp_sort_cmp);
355*86d7f5d3SJohn Marino
356*86d7f5d3SJohn Marino TRACE_OUT(configuration_entry_add_mp_cache_entry);
357*86d7f5d3SJohn Marino return (0);
358*86d7f5d3SJohn Marino }
359*86d7f5d3SJohn Marino
360*86d7f5d3SJohn Marino cache_entry
configuration_entry_find_mp_cache_entry(struct configuration_entry * config_entry,const char * mp_name)361*86d7f5d3SJohn Marino configuration_entry_find_mp_cache_entry(
362*86d7f5d3SJohn Marino struct configuration_entry *config_entry, const char *mp_name)
363*86d7f5d3SJohn Marino {
364*86d7f5d3SJohn Marino cache_entry *result;
365*86d7f5d3SJohn Marino
366*86d7f5d3SJohn Marino TRACE_IN(configuration_entry_find_mp_cache_entry);
367*86d7f5d3SJohn Marino result = bsearch(mp_name, config_entry->mp_cache_entries,
368*86d7f5d3SJohn Marino config_entry->mp_cache_entries_size,
369*86d7f5d3SJohn Marino sizeof(cache_entry), configuration_entry_cache_mp_cmp);
370*86d7f5d3SJohn Marino
371*86d7f5d3SJohn Marino if (result == NULL) {
372*86d7f5d3SJohn Marino TRACE_OUT(configuration_entry_find_mp_cache_entry);
373*86d7f5d3SJohn Marino return (NULL);
374*86d7f5d3SJohn Marino } else {
375*86d7f5d3SJohn Marino TRACE_OUT(configuration_entry_find_mp_cache_entry);
376*86d7f5d3SJohn Marino return (*result);
377*86d7f5d3SJohn Marino }
378*86d7f5d3SJohn Marino }
379*86d7f5d3SJohn Marino
380*86d7f5d3SJohn Marino /*
381*86d7f5d3SJohn Marino * Searches for all multipart entries with names starting with mp_name.
382*86d7f5d3SJohn Marino * Needed for cache flushing.
383*86d7f5d3SJohn Marino */
384*86d7f5d3SJohn Marino int
configuration_entry_find_mp_cache_entries(struct configuration_entry * config_entry,const char * mp_name,cache_entry ** start,cache_entry ** finish)385*86d7f5d3SJohn Marino configuration_entry_find_mp_cache_entries(
386*86d7f5d3SJohn Marino struct configuration_entry *config_entry, const char *mp_name,
387*86d7f5d3SJohn Marino cache_entry **start, cache_entry **finish)
388*86d7f5d3SJohn Marino {
389*86d7f5d3SJohn Marino cache_entry *result;
390*86d7f5d3SJohn Marino
391*86d7f5d3SJohn Marino TRACE_IN(configuration_entry_find_mp_cache_entries);
392*86d7f5d3SJohn Marino result = bsearch(mp_name, config_entry->mp_cache_entries,
393*86d7f5d3SJohn Marino config_entry->mp_cache_entries_size,
394*86d7f5d3SJohn Marino sizeof(cache_entry), configuration_entry_cache_mp_part_cmp);
395*86d7f5d3SJohn Marino
396*86d7f5d3SJohn Marino if (result == NULL) {
397*86d7f5d3SJohn Marino TRACE_OUT(configuration_entry_find_mp_cache_entries);
398*86d7f5d3SJohn Marino return (-1);
399*86d7f5d3SJohn Marino }
400*86d7f5d3SJohn Marino
401*86d7f5d3SJohn Marino *start = result;
402*86d7f5d3SJohn Marino *finish = result + 1;
403*86d7f5d3SJohn Marino
404*86d7f5d3SJohn Marino while (*start != config_entry->mp_cache_entries) {
405*86d7f5d3SJohn Marino if (configuration_entry_cache_mp_part_cmp(mp_name, *start - 1) == 0)
406*86d7f5d3SJohn Marino *start = *start - 1;
407*86d7f5d3SJohn Marino else
408*86d7f5d3SJohn Marino break;
409*86d7f5d3SJohn Marino }
410*86d7f5d3SJohn Marino
411*86d7f5d3SJohn Marino while (*finish != config_entry->mp_cache_entries +
412*86d7f5d3SJohn Marino config_entry->mp_cache_entries_size) {
413*86d7f5d3SJohn Marino
414*86d7f5d3SJohn Marino if (configuration_entry_cache_mp_part_cmp(
415*86d7f5d3SJohn Marino mp_name, *finish) == 0)
416*86d7f5d3SJohn Marino *finish = *finish + 1;
417*86d7f5d3SJohn Marino else
418*86d7f5d3SJohn Marino break;
419*86d7f5d3SJohn Marino }
420*86d7f5d3SJohn Marino
421*86d7f5d3SJohn Marino TRACE_OUT(configuration_entry_find_mp_cache_entries);
422*86d7f5d3SJohn Marino return (0);
423*86d7f5d3SJohn Marino }
424*86d7f5d3SJohn Marino
425*86d7f5d3SJohn Marino /*
426*86d7f5d3SJohn Marino * Configuration entry uses rwlock to handle access to its fields.
427*86d7f5d3SJohn Marino */
428*86d7f5d3SJohn Marino void
configuration_lock_rdlock(struct configuration * config)429*86d7f5d3SJohn Marino configuration_lock_rdlock(struct configuration *config)
430*86d7f5d3SJohn Marino {
431*86d7f5d3SJohn Marino TRACE_IN(configuration_lock_rdlock);
432*86d7f5d3SJohn Marino pthread_rwlock_rdlock(&config->rwlock);
433*86d7f5d3SJohn Marino TRACE_OUT(configuration_lock_rdlock);
434*86d7f5d3SJohn Marino }
435*86d7f5d3SJohn Marino
436*86d7f5d3SJohn Marino void
configuration_lock_wrlock(struct configuration * config)437*86d7f5d3SJohn Marino configuration_lock_wrlock(struct configuration *config)
438*86d7f5d3SJohn Marino {
439*86d7f5d3SJohn Marino TRACE_IN(configuration_lock_wrlock);
440*86d7f5d3SJohn Marino pthread_rwlock_wrlock(&config->rwlock);
441*86d7f5d3SJohn Marino TRACE_OUT(configuration_lock_wrlock);
442*86d7f5d3SJohn Marino }
443*86d7f5d3SJohn Marino
444*86d7f5d3SJohn Marino void
configuration_unlock(struct configuration * config)445*86d7f5d3SJohn Marino configuration_unlock(struct configuration *config)
446*86d7f5d3SJohn Marino {
447*86d7f5d3SJohn Marino TRACE_IN(configuration_unlock);
448*86d7f5d3SJohn Marino pthread_rwlock_unlock(&config->rwlock);
449*86d7f5d3SJohn Marino TRACE_OUT(configuration_unlock);
450*86d7f5d3SJohn Marino }
451*86d7f5d3SJohn Marino
452*86d7f5d3SJohn Marino /*
453*86d7f5d3SJohn Marino * Configuration entry uses 3 mutexes to handle cache operations. They are
454*86d7f5d3SJohn Marino * acquired by configuration_lock_entry and configuration_unlock_entry
455*86d7f5d3SJohn Marino * functions.
456*86d7f5d3SJohn Marino */
457*86d7f5d3SJohn Marino void
configuration_lock_entry(struct configuration_entry * entry,enum config_entry_lock_type lock_type)458*86d7f5d3SJohn Marino configuration_lock_entry(struct configuration_entry *entry,
459*86d7f5d3SJohn Marino enum config_entry_lock_type lock_type)
460*86d7f5d3SJohn Marino {
461*86d7f5d3SJohn Marino TRACE_IN(configuration_lock_entry);
462*86d7f5d3SJohn Marino assert(entry != NULL);
463*86d7f5d3SJohn Marino
464*86d7f5d3SJohn Marino switch (lock_type) {
465*86d7f5d3SJohn Marino case CELT_POSITIVE:
466*86d7f5d3SJohn Marino pthread_mutex_lock(&entry->positive_cache_lock);
467*86d7f5d3SJohn Marino break;
468*86d7f5d3SJohn Marino case CELT_NEGATIVE:
469*86d7f5d3SJohn Marino pthread_mutex_lock(&entry->negative_cache_lock);
470*86d7f5d3SJohn Marino break;
471*86d7f5d3SJohn Marino case CELT_MULTIPART:
472*86d7f5d3SJohn Marino pthread_mutex_lock(&entry->mp_cache_lock);
473*86d7f5d3SJohn Marino break;
474*86d7f5d3SJohn Marino default:
475*86d7f5d3SJohn Marino /* should be unreachable */
476*86d7f5d3SJohn Marino break;
477*86d7f5d3SJohn Marino }
478*86d7f5d3SJohn Marino TRACE_OUT(configuration_lock_entry);
479*86d7f5d3SJohn Marino }
480*86d7f5d3SJohn Marino
481*86d7f5d3SJohn Marino void
configuration_unlock_entry(struct configuration_entry * entry,enum config_entry_lock_type lock_type)482*86d7f5d3SJohn Marino configuration_unlock_entry(struct configuration_entry *entry,
483*86d7f5d3SJohn Marino enum config_entry_lock_type lock_type)
484*86d7f5d3SJohn Marino {
485*86d7f5d3SJohn Marino TRACE_IN(configuration_unlock_entry);
486*86d7f5d3SJohn Marino assert(entry != NULL);
487*86d7f5d3SJohn Marino
488*86d7f5d3SJohn Marino switch (lock_type) {
489*86d7f5d3SJohn Marino case CELT_POSITIVE:
490*86d7f5d3SJohn Marino pthread_mutex_unlock(&entry->positive_cache_lock);
491*86d7f5d3SJohn Marino break;
492*86d7f5d3SJohn Marino case CELT_NEGATIVE:
493*86d7f5d3SJohn Marino pthread_mutex_unlock(&entry->negative_cache_lock);
494*86d7f5d3SJohn Marino break;
495*86d7f5d3SJohn Marino case CELT_MULTIPART:
496*86d7f5d3SJohn Marino pthread_mutex_unlock(&entry->mp_cache_lock);
497*86d7f5d3SJohn Marino break;
498*86d7f5d3SJohn Marino default:
499*86d7f5d3SJohn Marino /* should be unreachable */
500*86d7f5d3SJohn Marino break;
501*86d7f5d3SJohn Marino }
502*86d7f5d3SJohn Marino TRACE_OUT(configuration_unlock_entry);
503*86d7f5d3SJohn Marino }
504*86d7f5d3SJohn Marino
505*86d7f5d3SJohn Marino struct configuration *
init_configuration(void)506*86d7f5d3SJohn Marino init_configuration(void)
507*86d7f5d3SJohn Marino {
508*86d7f5d3SJohn Marino struct configuration *retval;
509*86d7f5d3SJohn Marino
510*86d7f5d3SJohn Marino TRACE_IN(init_configuration);
511*86d7f5d3SJohn Marino retval = (struct configuration *)calloc(1, sizeof(struct configuration));
512*86d7f5d3SJohn Marino assert(retval != NULL);
513*86d7f5d3SJohn Marino
514*86d7f5d3SJohn Marino retval->entries_capacity = INITIAL_ENTRIES_CAPACITY;
515*86d7f5d3SJohn Marino retval->entries = (struct configuration_entry **)calloc(1,
516*86d7f5d3SJohn Marino sizeof(struct configuration_entry *) *
517*86d7f5d3SJohn Marino retval->entries_capacity);
518*86d7f5d3SJohn Marino assert(retval->entries != NULL);
519*86d7f5d3SJohn Marino
520*86d7f5d3SJohn Marino pthread_rwlock_init(&retval->rwlock, NULL);
521*86d7f5d3SJohn Marino
522*86d7f5d3SJohn Marino TRACE_OUT(init_configuration);
523*86d7f5d3SJohn Marino return (retval);
524*86d7f5d3SJohn Marino }
525*86d7f5d3SJohn Marino
526*86d7f5d3SJohn Marino void
fill_configuration_defaults(struct configuration * config)527*86d7f5d3SJohn Marino fill_configuration_defaults(struct configuration *config)
528*86d7f5d3SJohn Marino {
529*86d7f5d3SJohn Marino size_t len, i;
530*86d7f5d3SJohn Marino
531*86d7f5d3SJohn Marino TRACE_IN(fill_configuration_defaults);
532*86d7f5d3SJohn Marino assert(config != NULL);
533*86d7f5d3SJohn Marino
534*86d7f5d3SJohn Marino if (config->socket_path != NULL)
535*86d7f5d3SJohn Marino free(config->socket_path);
536*86d7f5d3SJohn Marino
537*86d7f5d3SJohn Marino len = strlen(DEFAULT_SOCKET_PATH);
538*86d7f5d3SJohn Marino config->socket_path = (char *)calloc(1, len + 1);
539*86d7f5d3SJohn Marino assert(config->socket_path != NULL);
540*86d7f5d3SJohn Marino memcpy(config->socket_path, DEFAULT_SOCKET_PATH, len);
541*86d7f5d3SJohn Marino
542*86d7f5d3SJohn Marino len = strlen(DEFAULT_PIDFILE_PATH);
543*86d7f5d3SJohn Marino config->pidfile_path = (char *)calloc(1, len + 1);
544*86d7f5d3SJohn Marino assert(config->pidfile_path != NULL);
545*86d7f5d3SJohn Marino memcpy(config->pidfile_path, DEFAULT_PIDFILE_PATH, len);
546*86d7f5d3SJohn Marino
547*86d7f5d3SJohn Marino config->socket_mode = S_IFSOCK | S_IRUSR | S_IWUSR |
548*86d7f5d3SJohn Marino S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH;
549*86d7f5d3SJohn Marino config->force_unlink = 1;
550*86d7f5d3SJohn Marino
551*86d7f5d3SJohn Marino config->query_timeout = DEFAULT_QUERY_TIMEOUT;
552*86d7f5d3SJohn Marino config->threads_num = DEFAULT_THREADS_NUM;
553*86d7f5d3SJohn Marino
554*86d7f5d3SJohn Marino for (i = 0; i < config->entries_size; ++i)
555*86d7f5d3SJohn Marino destroy_configuration_entry(config->entries[i]);
556*86d7f5d3SJohn Marino config->entries_size = 0;
557*86d7f5d3SJohn Marino
558*86d7f5d3SJohn Marino TRACE_OUT(fill_configuration_defaults);
559*86d7f5d3SJohn Marino }
560*86d7f5d3SJohn Marino
561*86d7f5d3SJohn Marino void
destroy_configuration(struct configuration * config)562*86d7f5d3SJohn Marino destroy_configuration(struct configuration *config)
563*86d7f5d3SJohn Marino {
564*86d7f5d3SJohn Marino int i;
565*86d7f5d3SJohn Marino TRACE_IN(destroy_configuration);
566*86d7f5d3SJohn Marino assert(config != NULL);
567*86d7f5d3SJohn Marino free(config->pidfile_path);
568*86d7f5d3SJohn Marino free(config->socket_path);
569*86d7f5d3SJohn Marino
570*86d7f5d3SJohn Marino for (i = 0; i < config->entries_size; ++i)
571*86d7f5d3SJohn Marino destroy_configuration_entry(config->entries[i]);
572*86d7f5d3SJohn Marino free(config->entries);
573*86d7f5d3SJohn Marino
574*86d7f5d3SJohn Marino pthread_rwlock_destroy(&config->rwlock);
575*86d7f5d3SJohn Marino free(config);
576*86d7f5d3SJohn Marino TRACE_OUT(destroy_configuration);
577*86d7f5d3SJohn Marino }
578