1 /*
2 * Copyright (C) 2004-2010 Christos Tsantilas
3 *
4 * This program is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Lesser General Public
6 * License as published by the Free Software Foundation; either
7 * version 2.1 of the License, or (at your option) any later version.
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Lesser General Public License for more details.
13 *
14 * You should have received a copy of the GNU Lesser General Public
15 * License along with this library; if not, write to the Free Software
16 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
17 * MA 02110-1301 USA.
18 */
19
20 #include "common.h"
21 #include "lookup_table.h"
22 #include "debug.h"
23 #include "mem.h"
24
25
26 /***********************************************************/
27 /* Global variables */
28
29 /*we can support up to 128 lookup table types, looks enough*/
30 const struct ci_lookup_table_type *lookup_tables_types[128];
31 int lookup_tables_types_num = 0;
32
33 /*********************************************************************/
34 /*Lookuptable library functions */
35
ci_lookup_table_type_register(struct ci_lookup_table_type * lt_type)36 struct ci_lookup_table_type *ci_lookup_table_type_register( struct ci_lookup_table_type *lt_type)
37 {
38 if (lookup_tables_types_num >= 128) {
39 ci_debug_printf(1,"c-icap does not support more than 128 loookup table types");
40 return NULL;
41 }
42 lookup_tables_types[lookup_tables_types_num++] = lt_type;
43 return lt_type;
44 }
45
ci_lookup_table_type_unregister(struct ci_lookup_table_type * lt_type)46 void ci_lookup_table_type_unregister( struct ci_lookup_table_type *lt_type)
47 {
48 int i;
49 for (i = 0; lookup_tables_types[i] != lt_type && i < lookup_tables_types_num; i++);
50
51 if (i<lookup_tables_types_num) {
52 lookup_tables_types_num--;
53 for (; i < lookup_tables_types_num; i++)
54 lookup_tables_types[i] = lookup_tables_types[i+1];
55 }
56 }
57
ci_lookup_table_type_search(const char * type)58 const struct ci_lookup_table_type *ci_lookup_table_type_search(const char *type)
59 {
60 int i;
61 for (i = 0; i<lookup_tables_types_num; i++) {
62 if (strcmp(type,lookup_tables_types[i]->type) == 0)
63 return lookup_tables_types[i];
64 }
65 return NULL;
66 }
67
68 static const void * lookup_table_get_row(struct ci_lookup_table *table, const void *key, const char *columns[], void ***vals);
ci_lookup_table_create_ext(const char * table,const ci_type_ops_t * key_ops,const ci_type_ops_t * val_ops,ci_mem_allocator_t * allocator)69 struct ci_lookup_table *ci_lookup_table_create_ext(const char *table,
70 const ci_type_ops_t *key_ops,
71 const ci_type_ops_t *val_ops,
72 ci_mem_allocator_t *allocator)
73 {
74 char *ttype,*path,*args,*s;
75 const struct ci_lookup_table_type *lt_type;
76 struct ci_lookup_table *lt;
77 char *stable = strdup(table);
78 if (!stable) {
79 /*A debug message.....*/
80 return NULL;
81 }
82
83 /*Normaly the table has the form tabletype:/path/{args}*/
84 s = index(stable,':');
85
86 if (!s) { /*Then it is a simple text file*/
87 ttype = "file";
88 path = stable;
89 args = NULL;
90 } else {
91 ttype = stable;
92 path = s+1;
93 *s = '\0';
94 s = index(path,'{');
95 if (s) {
96 *s = '\0'; /* path ends here */
97 args = s+1; /*args start here */
98
99 if ((s = index(args,'}'))) *s = '\0'; /*else args is all the remains string */
100 } else /*No args*/
101 args = NULL;
102 }
103 lt_type = ci_lookup_table_type_search(ttype);
104 if (!lt_type || !lt_type->open) {
105 ci_debug_printf(1,"Not lookuptable of type :%s!!!\n", ttype);
106 free(stable);
107 return NULL;
108 }
109
110 lt = malloc(sizeof(struct ci_lookup_table));
111 if (!lt) {
112 ci_debug_printf(1,"memory allocation error!!");
113 free(stable);
114 return NULL;
115 }
116
117 lt->path = strdup(path);
118 if (args)
119 lt->args = strdup(args);
120 else
121 lt->args = NULL;
122
123 free(stable);
124
125
126 lt->cols = -1;
127 lt->key_ops = key_ops;
128 lt->val_ops = val_ops;
129 lt->type = lt_type->type;
130 lt->open = lt_type->open;
131 lt->close = lt_type->close;
132 lt->search = lt_type->search;
133 lt->get_row = lookup_table_get_row;
134 lt->release_result = lt_type->release_result;
135 lt->allocator = allocator;
136 lt->_lt_type = lt_type;
137 lt->data = NULL;
138
139 return lt;
140 }
141
ci_lookup_table_create(const char * table)142 struct ci_lookup_table *ci_lookup_table_create(const char *table)
143 {
144 ci_mem_allocator_t *allocator;
145 struct ci_lookup_table *lt;
146 allocator = ci_create_os_allocator();
147 if (!allocator)
148 return NULL;
149
150 lt = ci_lookup_table_create_ext(table, &ci_str_ops, &ci_str_ops, allocator);
151 if (!lt)
152 ci_mem_allocator_destroy(allocator);
153 return lt;
154 }
155
ci_lookup_table_destroy(struct ci_lookup_table * lt)156 void ci_lookup_table_destroy(struct ci_lookup_table *lt)
157 {
158 if (!lt)
159 return;
160
161 lt->close(lt);
162 free(lt->path);
163 if (lt->args)
164 free(lt->args);
165 if (lt->allocator)
166 ci_mem_allocator_destroy(lt->allocator);
167 free(lt);
168 }
169
ci_lookup_table_open(struct ci_lookup_table * table)170 void * ci_lookup_table_open(struct ci_lookup_table *table)
171 {
172 if (!table->_lt_type || !table->open) {
173 ci_debug_printf(1, "lookup_table of type %s is corrupted (\"open\" method missing)!\n", table->type);
174 return NULL;
175 }
176 return table->open(table);
177 }
178
ci_lookup_table_search(struct ci_lookup_table * table,const char * key,char *** vals)179 const char * ci_lookup_table_search(struct ci_lookup_table *table, const char *key, char ***vals)
180 {
181 if (!table->_lt_type || !table->search) {
182 ci_debug_printf(1, "lookup_table of type %s is corrupted (\"search\" method missing)!\n", table->type);
183 return NULL;
184 }
185
186 if (!ci_type_ops_is_string(table->key_ops) || !ci_type_ops_is_string(table->val_ops)) {
187 ci_debug_printf(1, "lookup_table of type %s does not support search with string like keys!\n", table->type);
188 return NULL;
189 }
190
191 return table->search(table, (void *)key, (void ***)vals);
192 }
193
ci_lookup_table_release_result(struct ci_lookup_table * table,void ** val)194 void ci_lookup_table_release_result(struct ci_lookup_table *table, void **val)
195 {
196 if (!table->_lt_type || !table->release_result) {
197 ci_debug_printf(1, "lookup_table of type %s is corrupted (\"release_result\" method missing)!\n", table->type);
198 return;
199 }
200 return table->release_result(table, (void **)val);
201 }
202
lookup_table_get_row(struct ci_lookup_table * table,const void * key,const char * columns[],void *** vals)203 const void * lookup_table_get_row(struct ci_lookup_table *table, const void *key, const char *columns[], void ***vals)
204 {
205 int i;
206 if (!table->_lt_type) {
207 ci_debug_printf(1, "lookup_table of type %s is corrupted!\n", table->type);
208 return NULL;
209 }
210
211 if (!table->col_names || !table->_lt_type->get_row) {
212 ci_debug_printf(1, "lookup_table :%s does not support lookup on named columns\n", table->type);
213 return NULL;
214 }
215
216 for (i = 0; i < 1024 && columns[i] != NULL; i++) {
217 if (NULL == ci_str_vector_search(table->col_names, columns[i])) {
218 ci_debug_printf(1, "lookup_table :%s does not has column %s\n", table->type, columns[i]);
219 return NULL;
220 }
221 }
222
223 return table->_lt_type->get_row(table, key, columns, vals);
224 }
225
ci_lookup_table_get_row(struct ci_lookup_table * table,const char * key,const char * columns[],char *** vals)226 const char * ci_lookup_table_get_row(struct ci_lookup_table *table, const char *key, const char *columns[], char ***vals)
227 {
228 if ( !ci_type_ops_is_string(table->key_ops) || !ci_type_ops_is_string(table->val_ops)) {
229 ci_debug_printf(1, "lookup_table of type %s does not support search with string like keys!\n", table->type);
230 return NULL;
231 }
232
233 return (const char *) lookup_table_get_row(table, (const void *)key, columns, (void ***)vals);
234 }
235
236 extern struct ci_lookup_table_type file_table_type;
237 extern struct ci_lookup_table_type hash_table_type;
238 extern struct ci_lookup_table_type regex_table_type;
init_internal_lookup_tables()239 CI_DECLARE_FUNC(void) init_internal_lookup_tables()
240 {
241 ci_lookup_table_type_register(&file_table_type);
242 ci_lookup_table_type_register(&hash_table_type);
243 ci_lookup_table_type_register(®ex_table_type);
244 }
245