/Users/maurits/Documents/studie/afstuderen/biosphere/daemon/module.c

Go to the documentation of this file.
00001 /*
00002  * Author: MA Hartman
00003  * Date: feb 14, 2007
00004  * 
00005  * Function:
00006  * Module subsystem which loads and unloads pluggable modules.
00007  * 
00008  * License information:
00009  * 
00010  * Copyright (c) 2006 Maurits Hartman
00011  *
00012  * Permission is hereby granted, free of charge, to any person
00013  * obtaining a copy of this software and associated documentation
00014  * files (the "Software"), to deal in the Software without
00015  * restriction, including without limitation the rights to use,
00016  * copy, modify, merge, publish, distribute, sublicense, and/or sell
00017  * copies of the Software, and to permit persons to whom the
00018  * Software is furnished to do so, subject to the following
00019  * conditions:
00020  * 
00021  * The above copyright notice and this permission notice shall be
00022  * included in all copies or substantial portions of the Software.
00023  * 
00024  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
00025  * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
00026  * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
00027  * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
00028  * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
00029  * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
00030  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
00031  * OTHER DEALINGS IN THE SOFTWARE.
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         /* Construct the filepath (thread-safe): */
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     /* Read the WSDL file: */
00084     rv = read_file_into_buf(wsdlpath, &xmlbuf, &len, mp);
00085     if (rv != BS_OK) return rv;
00086     
00087     /* Parse it: */
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         /* Scan the list to see if this module is not already loaded: */
00104         if (module_is_loaded(name)) {
00105                 fprintf(stderr, "Module already loaded: %s\n", name);
00106                 return BS_ERROR;        
00107         }
00108         
00109         /* Try to construct the filepath of the module: */
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] != '/') { /* Add path if necessary: */
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         /* Perform the actual loading of the module: */
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     /* Create a module_info struct and fill it up: */
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     /* Install the system-wide service handler,
00157      * call the modules initialization routine and add service: */
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     /* Finally add it to the modules list: */
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         /* Search the modules list for the named module: */
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         /* Module was apparently not found: */
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); /* Don't worry about threads yet... */
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         /* Module could not be found... */
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 }

Generated on Tue Jul 17 09:50:52 2007 for Bio-SPHERE by  doxygen 1.5.1