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(&regex_table_type);
244 }
245