2 /* $NetBSD: citrus_mapper.c,v 1.7 2008/07/25 14:05:25 christos Exp $ */
5 * Copyright (c)2003 Citrus Project,
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
11 * 1. Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in the
15 * documentation and/or other materials provided with the distribution.
17 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
18 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
21 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
30 #include <sys/cdefs.h>
31 #include <sys/types.h>
33 #include <sys/queue.h>
42 #include "citrus_namespace.h"
43 #include "citrus_types.h"
44 #include "citrus_region.h"
45 #include "citrus_lock.h"
46 #include "citrus_memstream.h"
47 #include "citrus_bcs.h"
48 #include "citrus_mmap.h"
49 #include "citrus_module.h"
50 #include "citrus_hash.h"
51 #include "citrus_mapper.h"
53 #define _CITRUS_MAPPER_DIR "mapper.dir"
55 #define CM_HASH_SIZE 101
56 #define REFCOUNT_PERSISTENT -1
58 static pthread_rwlock_t cm_lock = PTHREAD_RWLOCK_INITIALIZER;
60 struct _citrus_mapper_area {
61 _CITRUS_HASH_HEAD(, _citrus_mapper, CM_HASH_SIZE) ma_cache;
66 * _citrus_mapper_create_area:
71 _citrus_mapper_create_area(
72 struct _citrus_mapper_area *__restrict *__restrict rma,
73 const char *__restrict area)
75 struct _citrus_mapper_area *ma;
87 snprintf(path, (size_t)PATH_MAX, "%s/%s", area, _CITRUS_MAPPER_DIR);
89 ret = stat(path, &st);
93 ma = malloc(sizeof(*ma));
98 ma->ma_dir = strdup(area);
99 if (ma->ma_dir == NULL) {
104 _CITRUS_HASH_INIT(&ma->ma_cache, CM_HASH_SIZE);
116 * lookup_mapper_entry:
117 * lookup mapper.dir entry in the specified directory.
119 * line format of iconv.dir file:
121 * mapper : mapper name.
122 * module : mapper module name.
123 * arg : argument for the module (generally, description file name)
127 lookup_mapper_entry(const char *dir, const char *mapname, void *linebuf,
128 size_t linebufsize, const char **module, const char **variable)
131 struct _memstream ms;
138 /* create mapper.dir path */
139 snprintf(path, (size_t)PATH_MAX, "%s/%s", dir, _CITRUS_MAPPER_DIR);
141 /* open read stream */
142 ret = _map_file(&r, path);
146 _memstream_bind(&ms, &r);
148 /* search the line matching to the map name */
149 cp = _memstream_matchline(&ms, mapname, &len, 0);
154 if (!len || len > linebufsize - 1) {
160 /* get module name */
162 cq = _bcs_skip_nonws_len(cp, &len);
163 strlcpy(p, cp, (size_t)(cq - cp + 1));
168 cp = _bcs_skip_ws_len(cq, &len);
169 strlcpy(p, cp, len + 1);
180 * simply close a mapper. (without handling hash)
183 mapper_close(struct _citrus_mapper *cm)
188 (*cm->cm_ops->mo_uninit)(cm);
191 _citrus_unload_module(cm->cm_module);
199 * simply open a mapper. (without handling hash)
202 mapper_open(struct _citrus_mapper_area *__restrict ma,
203 struct _citrus_mapper * __restrict * __restrict rcm,
204 const char * __restrict module,
205 const char * __restrict variable)
207 struct _citrus_mapper *cm;
208 _citrus_mapper_getops_t getops;
211 /* initialize mapper handle */
212 cm = malloc(sizeof(*cm));
216 cm->cm_module = NULL;
218 cm->cm_closure = NULL;
219 cm->cm_traits = NULL;
224 ret = _citrus_load_module(&cm->cm_module, module);
229 getops = (_citrus_mapper_getops_t)
230 _citrus_find_getops(cm->cm_module, module, "mapper");
235 cm->cm_ops = malloc(sizeof(*cm->cm_ops));
240 ret = (*getops)(cm->cm_ops);
244 if (!cm->cm_ops->mo_init ||
245 !cm->cm_ops->mo_uninit ||
246 !cm->cm_ops->mo_convert ||
247 !cm->cm_ops->mo_init_state)
250 /* allocate traits structure */
251 cm->cm_traits = malloc(sizeof(*cm->cm_traits));
252 if (cm->cm_traits == NULL) {
256 /* initialize the mapper */
257 ret = (*cm->cm_ops->mo_init)(ma, cm, ma->ma_dir,
258 (const void *)variable, strlen(variable) + 1,
259 cm->cm_traits, sizeof(*cm->cm_traits));
273 * _citrus_mapper_open_direct:
277 _citrus_mapper_open_direct(struct _citrus_mapper_area *__restrict ma,
278 struct _citrus_mapper * __restrict * __restrict rcm,
279 const char * __restrict module, const char * __restrict variable)
282 return (mapper_open(ma, rcm, module, variable));
289 hash_func(const char *key)
292 return (_string_hash_func(key, CM_HASH_SIZE));
299 match_func(struct _citrus_mapper *cm, const char *key)
302 return (strcmp(cm->cm_key, key));
306 * _citrus_mapper_open:
307 * open a mapper with looking up "mapper.dir".
310 _citrus_mapper_open(struct _citrus_mapper_area *__restrict ma,
311 struct _citrus_mapper * __restrict * __restrict rcm,
312 const char * __restrict mapname)
314 struct _citrus_mapper *cm;
315 char linebuf[PATH_MAX];
316 const char *module, *variable;
323 /* search in the cache */
324 hashval = hash_func(mapname);
325 _CITRUS_HASH_SEARCH(&ma->ma_cache, cm, cm_entry, match_func, mapname,
335 /* search mapper entry */
336 ret = lookup_mapper_entry(ma->ma_dir, mapname, linebuf,
337 (size_t)PATH_MAX, &module, &variable);
343 ret = mapper_open(ma, &cm, module, variable);
347 cm->cm_key = strdup(mapname);
348 if (cm->cm_key == NULL) {
354 /* insert to the cache */
356 _CITRUS_HASH_INSERT(&ma->ma_cache, cm, cm_entry, hashval);
367 * _citrus_mapper_close:
368 * close the specified mapper.
371 _citrus_mapper_close(struct _citrus_mapper *cm)
376 if (cm->cm_refcount == REFCOUNT_PERSISTENT)
378 if (cm->cm_refcount > 0) {
379 if (--cm->cm_refcount > 0)
381 _CITRUS_HASH_REMOVE(cm, cm_entry);
393 * _citrus_mapper_set_persistent:
394 * set persistent count.
397 _citrus_mapper_set_persistent(struct _citrus_mapper * __restrict cm)
401 cm->cm_refcount = REFCOUNT_PERSISTENT;