root/src/noit_module.c

Revision 5bf243f7a20f4b0718b616e7bda35cccf609d095, 7.8 kB (checked in by Theo Schlossnagle <jesus@omniti.com>, 6 years ago)

Baby steps.

lua checks can now be written. Simple wrappers for check manipulation are
in place. I need to figure out how to make lua resume into a coroutine and
invoke lua_error on resumption (so we can force a timeout).

noit.sleep(number) was implemanted as a proof-of-concept coro... It works!

Need to do sockets next -- will be slightly more complicated, but I do not
see it being traumatic.

refs #28

  • Property mode set to 100644
Line 
1 /*
2  * Copyright (c) 2007, OmniTI Computer Consulting, Inc.
3  * All rights reserved.
4  */
5
6 #include "noit_defines.h"
7
8 #include <stdio.h>
9 #include <dlfcn.h>
10
11 #include "noit_module.h"
12 #include "noit_conf.h"
13 #include "utils/noit_hash.h"
14 #include "utils/noit_log.h"
15
16 static noit_module_t *
17 noit_load_module_image(noit_module_loader_t *loader,
18                        char *module_name,
19                        noit_conf_section_t section);
20
21 noit_module_loader_t __noit_image_loader = {
22   {
23     NOIT_LOADER_MAGIC,
24     NOIT_LOADER_ABI_VERSION,
25     "image",
26     "Basic binary image loader",
27     NULL
28   },
29   noit_load_module_image
30 };
31 struct __extended_image_data {
32   void *userdata;
33 };
34
35 static noit_hash_table loaders = NOIT_HASH_EMPTY;
36 static noit_hash_table modules = NOIT_HASH_EMPTY;
37
38 noit_module_loader_t * noit_loader_lookup(const char *name) {
39   noit_module_loader_t *loader;
40
41   if(noit_hash_retrieve(&loaders, name, strlen(name), (void **)&loader)) {
42     return loader;
43   }
44   return NULL;
45 }
46
47 noit_module_t * noit_module_lookup(const char *name) {
48   noit_module_t *module;
49
50   if(noit_hash_retrieve(&modules, name, strlen(name), (void **)&module)) {
51     return module;
52   }
53   return NULL;
54 }
55
56 static int noit_module_validate_magic(noit_image_t *obj) {
57   if (NOIT_IMAGE_MAGIC(obj) != NOIT_MODULE_MAGIC) return -1;
58   if (NOIT_IMAGE_VERSION(obj) != NOIT_MODULE_ABI_VERSION) return -1;
59   return 0;
60 }
61
62 static int noit_module_loader_validate_magic(noit_image_t *obj) {
63   if (NOIT_IMAGE_MAGIC(obj) != NOIT_LOADER_MAGIC) return -1;
64   if (NOIT_IMAGE_VERSION(obj) != NOIT_LOADER_ABI_VERSION) return -1;
65   return 0;
66 }
67
68 noit_module_t *noit_blank_module() {
69   noit_module_t *obj;
70   obj = calloc(1, sizeof(*obj));
71   obj->hdr.opaque_handle = calloc(1, sizeof(struct __extended_image_data));
72   return obj;
73 }
74
75 int noit_register_module(noit_module_t *mod) {
76   noit_hash_store(&modules, mod->hdr.name, strlen(mod->hdr.name), mod);
77   return 0;
78 }
79
80 int noit_load_image(const char *file, const char *name,
81                     noit_hash_table *registry,
82                     int (*validate)(noit_image_t *),
83                     size_t obj_size) {
84   char module_file[PATH_MAX];
85   char *base;
86   void *dlhandle;
87   void *dlsymbol;
88   noit_image_t *obj;
89
90   if(!noit_conf_get_string(NULL, "/noit/modules/@directory", &base))
91     base = strdup("");
92
93   if(file[0] == '/')
94     strlcpy(module_file, file, sizeof(module_file));
95   else
96     snprintf(module_file, sizeof(module_file), "%s/%s.%s",
97              base, file, MODULEEXT);
98   free(base);
99
100   dlhandle = dlopen(module_file, RTLD_LAZY | RTLD_GLOBAL);
101   if(!dlhandle) {
102     noitL(noit_stderr, "Cannot open image '%s': %s\n",
103           module_file, dlerror());
104     return -1;
105   }
106
107   dlsymbol = dlsym(dlhandle, name);
108   if(!dlsymbol) {
109     noitL(noit_stderr, "Cannot find '%s' in image '%s': %s\n",
110           name, module_file, dlerror());
111     dlclose(dlhandle);
112     return -1;
113   }
114
115   if(validate(dlsymbol) == -1) {
116     noitL(noit_stderr, "I can't understand image %s\n", name);
117     dlclose(dlhandle);
118     return -1;
119   }
120
121   obj = calloc(1, obj_size);
122   memcpy(obj, dlsymbol, obj_size);
123   obj->opaque_handle = calloc(1, sizeof(struct __extended_image_data));
124
125   if(obj->onload && obj->onload(obj)) {
126     free(obj);
127     return -1;
128   }
129   noit_hash_store(registry, obj->name, strlen(obj->name), obj);
130   return 0;
131 }
132
133 static noit_module_loader_t *
134 noit_load_loader_image(noit_module_loader_t *loader,
135                        char *loader_name,
136                        noit_conf_section_t section) {
137   char loader_file[PATH_MAX];
138
139   if(!noit_conf_get_stringbuf(section, "ancestor-or-self::node()/@image",
140                               loader_file, sizeof(loader_file))) {
141     noitL(noit_stderr, "No image defined for %s\n", loader_name);
142     return NULL;
143   }
144   if(noit_load_image(loader_file, loader_name, &loaders,
145                      noit_module_loader_validate_magic,
146                      sizeof(noit_module_loader_t))) {
147     noitL(noit_stderr, "Could not load %s:%s\n", loader_file, loader_name);
148     return NULL;
149   }
150   return noit_loader_lookup(loader_name);
151 }
152
153 static noit_module_t *
154 noit_load_module_image(noit_module_loader_t *loader,
155                        char *module_name,
156                        noit_conf_section_t section) {
157   char module_file[PATH_MAX];
158
159   if(!noit_conf_get_stringbuf(section, "ancestor-or-self::node()/@image",
160                               module_file, sizeof(module_file))) {
161     noitL(noit_stderr, "No image defined for %s\n", module_name);
162     return NULL;
163   }
164   if(noit_load_image(module_file, module_name, &modules,
165                      noit_module_validate_magic, sizeof(noit_module_t))) {
166     noitL(noit_stderr, "Could not load %s:%s\n", module_file, module_name);
167     return NULL;
168   }
169   return noit_module_lookup(module_name);
170 }
171
172 void noit_module_init() {
173   noit_conf_section_t *sections;
174   int i, cnt = 0;
175
176   /* Load our module loaders */
177   sections = noit_conf_get_sections(NULL, "/noit/modules//loader", &cnt);
178   for(i=0; i<cnt; i++) {
179     char loader_name[256];
180     noit_module_loader_t *loader;
181
182     if(!noit_conf_get_stringbuf(sections[i], "ancestor-or-self::node()/@name",
183                                 loader_name, sizeof(loader_name))) {
184       noitL(noit_stderr, "No name defined in loader stanza %d\n", i+1);
185       continue;
186     }
187     loader = noit_load_loader_image(&__noit_image_loader, loader_name,
188                                     sections[i]);
189     if(!loader) {
190       noitL(noit_stderr, "Failed to load loader %s\n", loader_name);
191       continue;
192     }
193   }
194   if(sections) free(sections);
195
196   /* Load the modules */
197   sections = noit_conf_get_sections(NULL, "/noit/modules//module", &cnt);
198   if(!sections) return;
199   for(i=0; i<cnt; i++) {
200     noit_module_loader_t *loader = &__noit_image_loader;
201     noit_hash_table *config;
202     noit_module_t *module;
203     char loader_name[256];
204     char module_name[256];
205
206     /* If no loader is specified, we should use the image loader */
207     if(!noit_conf_get_stringbuf(sections[i], "ancestor-or-self::node()/@name",
208                                 module_name, sizeof(module_name))) {
209       noitL(noit_stderr, "No name defined in module stanza %d\n", i+1);
210       continue;
211     }
212
213     if(noit_conf_get_stringbuf(sections[i], "ancestor-or-self::node()/@loader",
214                                 loader_name, sizeof(loader_name))) {
215       loader = noit_loader_lookup(loader_name);
216       if(!loader) {
217         noitL(noit_stderr, "No '%s' loader found.\n", loader_name);
218         continue;
219       }
220     } else {
221       strlcpy(loader_name, "image", sizeof(loader_name));
222     }
223
224     module = loader->load(loader, module_name, sections[i]);
225     if(!module) {
226       noitL(noit_stderr, "Loader '%s' failed to load '%s'.\n",
227             loader_name, module_name);
228       continue;
229     }
230     config = noit_conf_get_hash(sections[i], "config");
231     if(module->config) {
232       int rv;
233       rv = module->config(module, config);
234       if(rv == 0) {
235         /* Not an error,
236          * but the module didn't take responsibility for the config.
237          */
238         noit_hash_destroy(config, free, free);
239         free(config);
240       }
241       else if(rv < 0) {
242         noitL(noit_stderr,
243               "Configure failed on %s\n", module_name);
244         continue;
245       }
246     }
247     if(module->init && module->init(module)) {
248       noitL(noit_stderr,
249             "Initialized failed on %s\n", module_name);
250       continue;
251     }
252     noitL(noit_stderr, "Module %s successfully loaded.\n", module_name);
253   }
254   free(sections);
255 }
256
257 #define userdata_accessors(type, field) \
258 void *noit_##type##_get_userdata(noit_##type##_t *mod) { \
259   return ((struct __extended_image_data *)mod->field)->userdata; \
260 } \
261 void noit_##type##_set_userdata(noit_##type##_t *mod, void *newdata) { \
262   ((struct __extended_image_data *)mod->field)->userdata = newdata; \
263 }
264
265 userdata_accessors(image, opaque_handle)
266 userdata_accessors(module_loader, hdr.opaque_handle)
267 userdata_accessors(module, hdr.opaque_handle)
Note: See TracBrowser for help on using the browser.