00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035 #include "module.h"
00036 #include "mutex.h"
00037 #include "options.h"
00038 #include "service.h"
00039 #include "settings.h"
00040 #include <biosphere_module.h>
00041 #include <list.h>
00042 #include <io.h>
00043 #include <str.h>
00044 #include <xml.h>
00045
00046 #include <assert.h>
00047 #include <string.h>
00048 #include <stdio.h>
00049 #include <apr_dso.h>
00050 #include <apr_time.h>
00051 #include <apr_strings.h>
00052 #include <apr_file_io.h>
00053
00054 extern apr_pool_t *global_mp;
00055
00058 static bs_list *modules;
00059
00060
00068 static bs_status set_definitions(module_info *modinfo, apr_pool_t *mp)
00069 {
00070 bs_status rv;
00071 char *xmlbuf, *moddir, *wsdlpath;
00072 bs_uint64 len;
00073 unsigned type;
00074 void *object;
00075
00076
00077 lock_option_mux();
00078 if (global_modules_dir) moddir = global_modules_dir;
00079 else moddir = BIOSPHERED_MODULES_DIR;
00080 wsdlpath = apr_pstrcat(mp, moddir, modinfo->def->services_definition, NULL);
00081 unlock_option_mux();
00082
00083
00084 rv = read_file_into_buf(wsdlpath, &xmlbuf, &len, mp);
00085 if (rv != BS_OK) return rv;
00086
00087
00088 rv = xlate_from_xml(xmlbuf, len, &object, &type, mp);
00089 if (rv != BS_OK || type != SERVICE_DEF_FROM_XML) return rv;
00090 modinfo->services = (bs_definition *) object;
00091 return BS_OK;
00092 }
00093
00094
00095 bs_status load_module(const char *name)
00096 {
00097 apr_status_t rv;
00098 bs_status rv2;
00099 apr_dso_handle_t *modh;
00100 module_info *modinfo;
00101 char *fullpath;
00102
00103
00104 if (module_is_loaded(name)) {
00105 fprintf(stderr, "Module already loaded: %s\n", name);
00106 return BS_ERROR;
00107 }
00108
00109
00110 printf("Loading module: %s\n", name);
00111 lock_pool_mux();
00112 fullpath = apr_pstrdup(global_mp, name);
00113 unlock_pool_mux();
00114 if (fullpath && fullpath[0] != '/') {
00115 char *moddir = BIOSPHERED_MODULES_DIR;
00116 lock_option_mux();
00117 if (global_modules_dir) moddir = global_modules_dir;
00118 unlock_option_mux();
00119 lock_pool_mux();
00120 fullpath = apr_pstrcat(global_mp, moddir, name, NULL);
00121 unlock_pool_mux();
00122 }
00123
00124
00125 lock_pool_mux();
00126 if ((rv = apr_dso_load(&modh, fullpath, global_mp)) != APR_SUCCESS) {
00127 char err[256];
00128 apr_strerror(rv, err, sizeof(err));
00129 fprintf(stderr, "Failure to load module '%s': %s\n", name, err);
00130 unlock_pool_mux();
00131 return BS_ERROR;
00132 }
00133
00134
00135 modinfo = (module_info *) apr_palloc(global_mp, sizeof(module_info));
00136 modinfo->name = apr_pstrdup(global_mp, name);
00137 modinfo->modh = modh;
00138 modinfo->time_loaded = apr_time_now();
00139 rv = apr_dso_sym((apr_dso_handle_sym_t*) &modinfo->def, modh,
00140 "bsmod_symtable");
00141 if (rv != APR_SUCCESS) {
00142 char err[256];
00143 apr_strerror(rv, err, sizeof(err));
00144 fprintf(stderr, "Failure to load module symtable: %s\n", err);
00145 unlock_pool_mux();
00146 return BS_ERROR;
00147 }
00148 rv2 = set_definitions(modinfo, global_mp);
00149 if (rv2 != BS_OK) {
00150 fprintf(stderr, "Failure to parse WSDL file of module: %s\n", name);
00151 unlock_pool_mux();
00152 return BS_ERROR;
00153 }
00154 unlock_pool_mux();
00155
00156
00157
00158 modinfo->def->syshandler = handle_service_request;
00159 rv2 = modinfo->def->init();
00160 if (rv2 != BS_OK) return rv2;
00161 printf("Successfully loaded module: %s\n", modinfo->def->name);
00162 rv2 = add_service(modinfo->services, modinfo->def->handler);
00163 if (rv2 != BS_OK) {
00164 fprintf(stderr, "Failure to add module services: %s\n", name);
00165 return BS_ERROR;
00166 }
00167
00168
00169 lock_module_mux();
00170 list_append(modules, modinfo);
00171 unlock_module_mux();
00172 return BS_OK;
00173 }
00174
00175
00176 bs_status unload_module(const char *name)
00177 {
00178 unsigned i;
00179 printf("Unloading module %s...", name);
00180
00181
00182 lock_module_mux();
00183 for (i = 0; i < list_size(modules); i++) {
00184 module_info *mi = list_index(modules, i);
00185 if (streq(mi->name, name)) {
00186 bs_status rv;
00187
00188 mi->def->cleanup();
00189 apr_dso_unload(mi->modh);
00190 list_remove(modules, i);
00191 unlock_module_mux();
00192
00193 rv = remove_service(mi->services->name);
00194
00195 printf("OK\n");
00196 return BS_OK;
00197 }
00198 }
00199
00200
00201 unlock_module_mux();
00202 printf("ERROR\n");
00203 fprintf(stderr, "Module not found while unloading: %s\n", name);
00204 return BS_ERROR;
00205 }
00206
00207
00208 bs_status unload_all_modules(void)
00209 {
00210 lock_module_mux();
00211 while (list_size(modules) > 0) {
00212 bs_status rv;
00213 module_info *mi;
00214
00215 mi = list_index(modules, 0);
00216 mi->def->cleanup();
00217 apr_dso_unload(mi->modh);
00218 list_remove(modules, 0);
00219
00220 rv = remove_service(mi->services->name);
00221 if (rv != BS_OK) {
00222 fprintf(stderr, "error while remove services for module %s", mi->name);
00223 unlock_module_mux();
00224 return rv;
00225 }
00226 }
00227 unlock_module_mux();
00228 return BS_OK;
00229 }
00230
00231
00232 bs_status init_module(apr_pool_t *mp)
00233 {
00234 unsigned i;
00235
00236 modules = new_list(mp);
00237 for (i = 0; global_module_names_list && i < list_size(global_module_names_list); i++) {
00238 char *tmp = list_index(global_module_names_list, i);
00239 if (load_module(tmp) != BS_OK) return BS_ERROR;
00240 }
00241 return BS_OK;
00242 }
00243
00244
00245 bs_module *get_module_info(const char *name)
00246 {
00247 unsigned i;
00248
00249 lock_module_mux();
00250 for (i = 0; i < list_size(modules); i++) {
00251 module_info *mi = list_index(modules, i);
00252 if (streq(mi->name, name)) {
00253 unlock_module_mux();
00254 return mi->def;
00255 }
00256 }
00257
00258
00259 unlock_module_mux();
00260 return NULL;
00261 }
00262
00263
00264 bs_status get_module_descriptions(bs_list *names,
00265 bs_list *fnames, bs_list *versions, bs_list *descriptions)
00266 {
00267 unsigned i;
00268 assert(names && fnames && versions && descriptions);
00269
00270 lock_module_mux();
00271 for (i = 0; i < list_size(modules); i++) {
00272 char *mname, *descr, *fname, *version;
00273 module_info *mi = list_index(modules, i);
00274
00275 mname = apr_pstrdup(names->pool, mi->name);
00276 list_append(names, mname);
00277
00278 version = apr_psprintf(fnames->pool, "%d.%d", mi->def->module_major,
00279 mi->def->module_minor);
00280 list_append(versions, version);
00281
00282 fname = apr_pstrdup(names->pool, mi->def->name);
00283 list_append(fnames, fname);
00284
00285 descr = apr_pstrdup(descriptions->pool, mi->def->description);
00286 list_append(descriptions, descr);
00287 }
00288 unlock_module_mux();
00289 return BS_OK;
00290 }