Fawkes API  Fawkes Development Version
module_manager.cpp
00001 
00002 /***************************************************************************
00003  *  module_manager.cpp - manager for modules (i.e. shared objects)
00004  *
00005  *  Generated: Thu Jun 02 11:45:03 2011 (based on module_manager_template.h)
00006  *  Copyright  2006-2011  Tim Niemueller [www.niemueller.de]
00007  *
00008  ****************************************************************************/
00009 
00010 /*  This program is free software; you can redistribute it and/or modify
00011  *  it under the terms of the GNU General Public License as published by
00012  *  the Free Software Foundation; either version 2 of the License, or
00013  *  (at your option) any later version. A runtime exception applies to
00014  *  this software (see LICENSE.GPL_WRE file mentioned below for details).
00015  *
00016  *  This program is distributed in the hope that it will be useful,
00017  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
00018  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00019  *  GNU Library General Public License for more details.
00020  *
00021  *  Read the full text in the LICENSE.GPL_WRE file in the doc directory.
00022  */
00023 
00024 #include <utils/system/dynamic_module/module_manager.h>
00025 #include <core/threading/mutex.h>
00026 #include <core/threading/mutex_locker.h>
00027 
00028 namespace fawkes {
00029 #if 0 /* just to make Emacs auto-indent happy */
00030 }
00031 #endif
00032 
00033 
00034 /** @class ModuleManager <utils/system/dynamic_module/module_manager.h>
00035  * Dynamic module manager.
00036  * Manager to load and unload modules, keeps track of loaded modules
00037  * and does not reload modules if they are already loaded.
00038  * @author Tim Niemueller
00039  */
00040 
00041 /** Constructor of NetworkManagerTemplate
00042  * @param module_base_dir The module basedir where to look for plugins
00043  * @param open_flags flags to pass to modules when opening them
00044  */
00045 ModuleManager::ModuleManager(const char *module_base_dir,
00046                              Module::ModuleFlags open_flags)
00047 {
00048   __modules.clear();
00049   __module_base_dir = module_base_dir;
00050   __mutex = new Mutex();
00051   __open_flags = open_flags;
00052 }
00053 
00054 /** Destructor. */
00055 ModuleManager::~ModuleManager()
00056 {
00057   std::map<std::string, Module * >::iterator i;
00058   for (i = __modules.begin(); i != __modules.end(); ++i) {
00059     delete (*i).second;
00060   }
00061   __modules.clear();
00062   delete __mutex;
00063 }
00064 
00065 
00066 /** Set flags to open modules with.
00067  * @param open_flags flags to pass to modules when opening them
00068  */
00069 void
00070 ModuleManager::set_open_flags(Module::ModuleFlags open_flags)
00071 {
00072   __open_flags = open_flags;
00073 }
00074 
00075 
00076 /** Open a module
00077  * @param filename The file name of the module that should be
00078  * opened. If the ModuleManager implementation takes a base dir
00079  * argument (recommended) this filename is relative to that
00080  * base dir
00081  * @return Returns the module if the file was opened successfully
00082  * or NULL otherwise. Do NOT delete the module after usage but use
00083  * closeModule to close it.
00084  * @exception ModuleOpenException thrown if the module could not be opened
00085  */
00086 Module *
00087 ModuleManager::open_module(const char *filename)
00088 {
00089   __mutex->lock();
00090   if ( __modules.find(filename) != __modules.end() ) {
00091     __modules[filename]->ref();
00092     __mutex->unlock();
00093     return __modules[filename];
00094   } else {
00095     Module *module = new Module(std::string(__module_base_dir) + "/" + filename,
00096                                 __open_flags);
00097     try {
00098       module->open();
00099       // ref count of module is now 1
00100       __modules[module->get_base_filename()] = module;
00101       __mutex->unlock();
00102       return module;
00103     } catch (ModuleOpenException &e) {
00104       delete module;
00105       __mutex->unlock();
00106       throw;
00107     }
00108   }
00109   __mutex->unlock();
00110 }
00111 
00112 
00113 /** Close a module by Module instance
00114  * @param module The module that is to be closed
00115  */
00116 void
00117 ModuleManager::close_module(Module *module)
00118 {
00119   close_module(module->get_base_filename().c_str());
00120 }
00121 
00122 
00123 /** Close a module by filename
00124  * @param filename the name of the module file that should be closed, this
00125  * is compared to loaded modules and must match what
00126  * Module::GetBaseFilename() returns
00127  */
00128 void
00129 ModuleManager::close_module(const char *filename)
00130 {
00131   __mutex->lock();
00132   if ( __modules.find(filename) != __modules.end() ) {
00133     __modules[filename]->unref();
00134     if (__modules[filename]->notref()) {
00135       delete __modules[filename];
00136       __modules.erase( filename );
00137     }
00138   }
00139   __mutex->unlock();
00140 }
00141 
00142 
00143 /** Get a module if opened.
00144  * This will return a pointer to a module if it had already been opened! The
00145  * reference count is increased and you have to manually unref the module once
00146  * you are done with it! This method works similar to open_module() with the
00147  * difference that it is not tried to load the module if it is not open.
00148  * @param filename file name of the module
00149  * @return a pointer to the module with the reference cound incremented by one
00150  * if the module had been opened already or NULL if it was not opened.
00151  */
00152 Module *
00153 ModuleManager::get_module(const char *filename)
00154 {
00155   MutexLocker lock(__mutex);
00156   if ( __modules.find(filename) != __modules.end() ) {
00157     __modules[filename]->ref();
00158     return __modules[filename];
00159   } else {
00160     return NULL;
00161   }
00162 }
00163 
00164 
00165 /** Check if the module is already opened.
00166  * @param filename the name of the module file to check if it is opened.
00167  * It is compared to loaded modules and must match what
00168  * Module::get_base_filename() returns
00169  * @return true if module has been opened, false otherwise
00170  */
00171 bool
00172 ModuleManager::module_opened(const char *filename)
00173 {
00174   return ( __modules.find(filename) != __modules.end() );
00175 }
00176 
00177   
00178 /** Get the file extension for the current module type.
00179  * @return Returns a string with the file extension that has to
00180  * be used for modules on the current system (for example "so")
00181  */
00182 const char *
00183 ModuleManager::get_module_file_extension()
00184 {
00185   return Module::get_file_extension();
00186 }
00187 
00188 } // end of namespace fawkes