class_loader_core.cpp
Go to the documentation of this file.
00001 /*
00002  * Copyright (c) 2012, Willow Garage, Inc.
00003  * All rights reserved.
00004  *
00005  * Redistribution and use in source and binary forms, with or without
00006  * modification, are permitted provided that the following conditions are met:
00007  *
00008  *     * Redistributions of source code must retain the above copyright
00009  *       notice, this list of conditions and the following disclaimer.
00010  *     * Redistributions in binary form must reproduce the above copyright
00011  *       notice, this list of conditions and the following disclaimer in the
00012  *       documentation and/or other materials provided with the distribution.
00013  *     * Neither the name of the Willow Garage, Inc. nor the names of its
00014  *       contributors may be used to endorse or promote products derived from
00015  *       this software without specific prior written permission.
00016  *
00017  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
00018  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
00019  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
00020  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
00021  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
00022  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
00023  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
00024  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
00025  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
00026  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
00027  * POSSIBILITY OF SUCH DAMAGE.
00028  */
00029 
00030 #include "class_loader/class_loader_core.hpp"
00031 #include "class_loader/class_loader.hpp"
00032 
00033 #include <Poco/SharedLibrary.h>
00034 
00035 #include <cassert>
00036 #include <string>
00037 #include <vector>
00038 
00039 namespace class_loader
00040 {
00041 namespace class_loader_private
00042 {
00043 
00044 
00045 // Global data
00046 /*****************************************************************************/
00047 /*****************************************************************************/
00048 /*****************************************************************************/
00049 
00050 boost::recursive_mutex & getLoadedLibraryVectorMutex()
00051 /*****************************************************************************/
00052 {
00053   static boost::recursive_mutex m;
00054   return m;
00055 }
00056 
00057 boost::recursive_mutex & getPluginBaseToFactoryMapMapMutex()
00058 /*****************************************************************************/
00059 {
00060   static boost::recursive_mutex m;
00061   return m;
00062 }
00063 
00064 BaseToFactoryMapMap & getGlobalPluginBaseToFactoryMapMap()
00065 /*****************************************************************************/
00066 {
00067   static BaseToFactoryMapMap instance;
00068   return instance;
00069 }
00070 
00071 FactoryMap & getFactoryMapForBaseClass(const std::string & typeid_base_class_name)
00072 /*****************************************************************************/
00073 {
00074   BaseToFactoryMapMap & factoryMapMap = getGlobalPluginBaseToFactoryMapMap();
00075   std::string base_class_name = typeid_base_class_name;
00076   if (factoryMapMap.find(base_class_name) == factoryMapMap.end()) {
00077     factoryMapMap[base_class_name] = FactoryMap();
00078   }
00079 
00080   return factoryMapMap[base_class_name];
00081 }
00082 
00083 MetaObjectVector & getMetaObjectGraveyard()
00084 /*****************************************************************************/
00085 {
00086   static MetaObjectVector instance;
00087   return instance;
00088 }
00089 
00090 LibraryVector & getLoadedLibraryVector()
00091 /*****************************************************************************/
00092 {
00093   static LibraryVector instance;
00094   return instance;
00095 }
00096 
00097 std::string & getCurrentlyLoadingLibraryNameReference()
00098 /*****************************************************************************/
00099 {
00100   static std::string library_name;
00101   return library_name;
00102 }
00103 
00104 std::string getCurrentlyLoadingLibraryName()
00105 /*****************************************************************************/
00106 {
00107   return getCurrentlyLoadingLibraryNameReference();
00108 }
00109 
00110 void setCurrentlyLoadingLibraryName(const std::string & library_name)
00111 /*****************************************************************************/
00112 {
00113   std::string & library_name_ref = getCurrentlyLoadingLibraryNameReference();
00114   library_name_ref = library_name;
00115 }
00116 
00117 ClassLoader * & getCurrentlyActiveClassLoaderReference()
00118 /*****************************************************************************/
00119 {
00120   static ClassLoader * loader = NULL;
00121   return loader;
00122 }
00123 
00124 ClassLoader * getCurrentlyActiveClassLoader()
00125 /*****************************************************************************/
00126 {
00127   return getCurrentlyActiveClassLoaderReference();
00128 }
00129 
00130 void setCurrentlyActiveClassLoader(ClassLoader * loader)
00131 /*****************************************************************************/
00132 {
00133   ClassLoader * & loader_ref = getCurrentlyActiveClassLoaderReference();
00134   loader_ref = loader;
00135 }
00136 
00137 bool & hasANonPurePluginLibraryBeenOpenedReference()
00138 /*****************************************************************************/
00139 {
00140   static bool hasANonPurePluginLibraryBeenOpenedReference = false;
00141   return hasANonPurePluginLibraryBeenOpenedReference;
00142 }
00143 
00144 bool hasANonPurePluginLibraryBeenOpened()
00145 /*****************************************************************************/
00146 {
00147   return hasANonPurePluginLibraryBeenOpenedReference();
00148 }
00149 
00150 void hasANonPurePluginLibraryBeenOpened(bool hasIt)
00151 /*****************************************************************************/
00152 {
00153   hasANonPurePluginLibraryBeenOpenedReference() = hasIt;
00154 }
00155 
00156 
00157 // MetaObject search/insert/removal/query
00158 /*****************************************************************************/
00159 /*****************************************************************************/
00160 /*****************************************************************************/
00161 
00162 MetaObjectVector allMetaObjects(const FactoryMap & factories)
00163 /*****************************************************************************/
00164 {
00165   MetaObjectVector all_meta_objs;
00166   for (
00167     FactoryMap::const_iterator factoryItr = factories.begin();
00168     factoryItr != factories.end(); factoryItr++
00169   )
00170   {
00171     all_meta_objs.push_back(factoryItr->second);
00172   }
00173   return all_meta_objs;
00174 }
00175 
00176 MetaObjectVector allMetaObjects()
00177 /*****************************************************************************/
00178 {
00179   boost::recursive_mutex::scoped_lock lock(getPluginBaseToFactoryMapMapMutex());
00180 
00181   MetaObjectVector all_meta_objs;
00182   BaseToFactoryMapMap & factory_map_map = getGlobalPluginBaseToFactoryMapMap();
00183   BaseToFactoryMapMap::iterator itr;
00184 
00185   for (itr = factory_map_map.begin(); itr != factory_map_map.end(); itr++) {
00186     MetaObjectVector objs = allMetaObjects(itr->second);
00187     all_meta_objs.insert(all_meta_objs.end(), objs.begin(), objs.end());
00188   }
00189   return all_meta_objs;
00190 }
00191 
00192 MetaObjectVector
00193 filterAllMetaObjectsOwnedBy(const MetaObjectVector & to_filter, const ClassLoader * owner)
00194 /*****************************************************************************/
00195 {
00196   MetaObjectVector filtered_objs;
00197   for (unsigned int c = 0; c < to_filter.size(); c++) {
00198     if (to_filter.at(c)->isOwnedBy(owner)) {
00199       filtered_objs.push_back(to_filter.at(c));
00200     }
00201   }
00202   return filtered_objs;
00203 }
00204 
00205 MetaObjectVector
00206 filterAllMetaObjectsAssociatedWithLibrary(
00207   const MetaObjectVector & to_filter, const std::string & library_path)
00208 /*****************************************************************************/
00209 {
00210   MetaObjectVector filtered_objs;
00211   for (unsigned int c = 0; c < to_filter.size(); c++) {
00212     if (to_filter.at(c)->getAssociatedLibraryPath() == library_path) {
00213       filtered_objs.push_back(to_filter.at(c));
00214     }
00215   }
00216   return filtered_objs;
00217 }
00218 
00219 MetaObjectVector
00220 allMetaObjectsForClassLoader(const ClassLoader * owner)
00221 /*****************************************************************************/
00222 {
00223   return filterAllMetaObjectsOwnedBy(allMetaObjects(), owner);
00224 }
00225 
00226 MetaObjectVector
00227 allMetaObjectsForLibrary(const std::string & library_path)
00228 /*****************************************************************************/
00229 {
00230   return filterAllMetaObjectsAssociatedWithLibrary(allMetaObjects(), library_path);
00231 }
00232 
00233 MetaObjectVector
00234 allMetaObjectsForLibraryOwnedBy(const std::string & library_path, const ClassLoader * owner)
00235 /*****************************************************************************/
00236 {
00237   return filterAllMetaObjectsOwnedBy(allMetaObjectsForLibrary(library_path), owner);
00238 }
00239 
00240 void insertMetaObjectIntoGraveyard(AbstractMetaObjectBase * meta_obj)
00241 /*****************************************************************************/
00242 {
00243   CONSOLE_BRIDGE_logDebug(
00244     "class_loader.class_loader_private: "
00245     "Inserting MetaObject (class = %s, base_class = %s, ptr = %p) into graveyard",
00246     meta_obj->className().c_str(), meta_obj->baseClassName().c_str(), meta_obj);
00247   getMetaObjectGraveyard().push_back(meta_obj);
00248 }
00249 
00250 void destroyMetaObjectsForLibrary(
00251   const std::string & library_path, FactoryMap & factories, const ClassLoader * loader)
00252 /*****************************************************************************/
00253 {
00254   FactoryMap::iterator factory_itr = factories.begin();
00255   while (factory_itr != factories.end()) {
00256     AbstractMetaObjectBase * meta_obj = factory_itr->second;
00257     if (meta_obj->getAssociatedLibraryPath() == library_path && meta_obj->isOwnedBy(loader)) {
00258       meta_obj->removeOwningClassLoader(loader);
00259       if (!meta_obj->isOwnedByAnybody()) {
00260         FactoryMap::iterator factory_itr_copy = factory_itr;
00261         factory_itr++;
00262         // TODO(mikaelarguedas) fix this when branching out for melodic
00263         // Note: map::erase does not return iterator like vector::erase does.
00264         // Hence the ugliness of this code and a need for copy. Should be fixed in next C++ revision
00265         factories.erase(factory_itr_copy);
00266 
00267         // Insert into graveyard
00268         // We remove the metaobject from its factory map, but we don't destroy it...instead it
00269         // saved to a "graveyard" to the side.
00270         // This is due to our static global variable initialization problem that causes factories
00271         // to not be registered when a library is closed and then reopened.
00272         // This is because it's truly not closed due to the use of global symbol binding i.e.
00273         // calling dlopen with RTLD_GLOBAL instead of RTLD_LOCAL.
00274         // We require using the former as the which is required to support RTTI
00275         insertMetaObjectIntoGraveyard(meta_obj);
00276       } else {
00277         factory_itr++;
00278       }
00279     } else {
00280       factory_itr++;
00281     }
00282   }
00283 }
00284 
00285 void destroyMetaObjectsForLibrary(const std::string & library_path, const ClassLoader * loader)
00286 /*****************************************************************************/
00287 {
00288   boost::recursive_mutex::scoped_lock lock(getPluginBaseToFactoryMapMapMutex());
00289 
00290   CONSOLE_BRIDGE_logDebug(
00291     "class_loader.class_loader_private: "
00292     "Removing MetaObjects associated with library %s and class loader %p from global "
00293     "plugin-to-factorymap map.\n",
00294     library_path.c_str(), loader);
00295 
00296   // We have to walk through all FactoryMaps to be sure
00297   BaseToFactoryMapMap & factory_map_map = getGlobalPluginBaseToFactoryMapMap();
00298   BaseToFactoryMapMap::iterator itr;
00299   for (itr = factory_map_map.begin(); itr != factory_map_map.end(); itr++) {
00300     destroyMetaObjectsForLibrary(library_path, itr->second, loader);
00301   }
00302 
00303   CONSOLE_BRIDGE_logDebug("%s", "class_loader.class_loader_private: Metaobjects removed.");
00304 }
00305 
00306 bool areThereAnyExistingMetaObjectsForLibrary(const std::string & library_path)
00307 /*****************************************************************************/
00308 {
00309   return allMetaObjectsForLibrary(library_path).size() > 0;
00310 }
00311 
00312 // Loaded Library Vector manipulation
00313 /*****************************************************************************/
00314 /*****************************************************************************/
00315 /*****************************************************************************/
00316 LibraryVector::iterator findLoadedLibrary(const std::string & library_path)
00317 /*****************************************************************************/
00318 {
00319   LibraryVector & open_libraries = getLoadedLibraryVector();
00320   LibraryVector::iterator itr;
00321   for (itr = open_libraries.begin(); itr != open_libraries.end(); itr++) {
00322     if (itr->first == library_path) {
00323       break;
00324     }
00325   }
00326   return itr;
00327 }
00328 
00329 bool isLibraryLoadedByAnybody(const std::string & library_path)
00330 /*****************************************************************************/
00331 {
00332   boost::recursive_mutex::scoped_lock lock(getLoadedLibraryVectorMutex());
00333 
00334   LibraryVector & open_libraries = getLoadedLibraryVector();
00335   LibraryVector::iterator itr = findLoadedLibrary(library_path);
00336 
00337   if (itr != open_libraries.end()) {
00338     assert(itr->second->isLoaded() == true);  // Ensure Poco actually thinks the library is loaded
00339     return true;
00340   } else {
00341     return false;
00342   }
00343 }
00344 
00345 bool isLibraryLoaded(const std::string & library_path, ClassLoader * loader)
00346 /*****************************************************************************/
00347 {
00348   bool is_lib_loaded_by_anyone = isLibraryLoadedByAnybody(library_path);
00349   int num_meta_objs_for_lib = allMetaObjectsForLibrary(library_path).size();
00350   int num_meta_objs_for_lib_bound_to_loader =
00351     allMetaObjectsForLibraryOwnedBy(library_path, loader).size();
00352   bool are_meta_objs_bound_to_loader =
00353     (0 == num_meta_objs_for_lib) ? true : (
00354     num_meta_objs_for_lib_bound_to_loader <= num_meta_objs_for_lib);
00355 
00356   return is_lib_loaded_by_anyone && are_meta_objs_bound_to_loader;
00357 }
00358 
00359 std::vector<std::string> getAllLibrariesUsedByClassLoader(const ClassLoader * loader)
00360 /*****************************************************************************/
00361 {
00362   MetaObjectVector all_loader_meta_objs = allMetaObjectsForClassLoader(loader);
00363   std::vector<std::string> all_libs;
00364   for (unsigned int c = 0; c < all_loader_meta_objs.size(); c++) {
00365     std::string lib_path = all_loader_meta_objs.at(c)->getAssociatedLibraryPath();
00366     if (std::find(all_libs.begin(), all_libs.end(), lib_path) == all_libs.end()) {
00367       all_libs.push_back(lib_path);
00368     }
00369   }
00370   return all_libs;
00371 }
00372 
00373 
00374 // Implementation of Remaining Core plugin_private Functions
00375 /*****************************************************************************/
00376 /*****************************************************************************/
00377 /*****************************************************************************/
00378 
00379 void addClassLoaderOwnerForAllExistingMetaObjectsForLibrary(
00380   const std::string & library_path, ClassLoader * loader)
00381 /*****************************************************************************/
00382 {
00383   MetaObjectVector all_meta_objs = allMetaObjectsForLibrary(library_path);
00384   for (unsigned int c = 0; c < all_meta_objs.size(); c++) {
00385     AbstractMetaObjectBase * meta_obj = all_meta_objs.at(c);
00386     CONSOLE_BRIDGE_logDebug(
00387       "class_loader.class_loader_private: "
00388       "Tagging existing MetaObject %p (base = %s, derived = %s) with "
00389       "class loader %p (library path = %s).",
00390       meta_obj, meta_obj->baseClassName().c_str(), meta_obj->className().c_str(),
00391       loader, loader ? loader->getLibraryPath().c_str() : "NULL");
00392     all_meta_objs.at(c)->addOwningClassLoader(loader);
00393   }
00394 }
00395 
00396 void revivePreviouslyCreateMetaobjectsFromGraveyard(
00397   const std::string & library_path, ClassLoader * loader)
00398 /*****************************************************************************/
00399 {
00400   boost::recursive_mutex::scoped_lock b2fmm_lock(getPluginBaseToFactoryMapMapMutex());
00401   MetaObjectVector & graveyard = getMetaObjectGraveyard();
00402 
00403   for (MetaObjectVector::iterator itr = graveyard.begin(); itr != graveyard.end(); itr++) {
00404     AbstractMetaObjectBase * obj = *itr;
00405     if (obj->getAssociatedLibraryPath() == library_path) {
00406       CONSOLE_BRIDGE_logDebug(
00407         "class_loader.class_loader_private: "
00408         "Resurrected factory metaobject from graveyard, class = %s, base_class = %s ptr = %p..."
00409         "bound to ClassLoader %p (library path = %s)",
00410         obj->className().c_str(), obj->baseClassName().c_str(), obj,
00411         loader, loader ? loader->getLibraryPath().c_str() : "NULL");
00412 
00413       obj->addOwningClassLoader(loader);
00414       assert(obj->typeidBaseClassName() != "UNSET");
00415       FactoryMap & factory = getFactoryMapForBaseClass(obj->typeidBaseClassName());
00416       factory[obj->className()] = obj;
00417     }
00418   }
00419 }
00420 
00421 void purgeGraveyardOfMetaobjects(
00422   const std::string & library_path, ClassLoader * loader, bool delete_objs)
00423 /*****************************************************************************/
00424 {
00425   MetaObjectVector all_meta_objs = allMetaObjects();
00426   // Note: Lock must happen after call to allMetaObjects as that will lock
00427   boost::recursive_mutex::scoped_lock b2fmm_lock(getPluginBaseToFactoryMapMapMutex());
00428 
00429   MetaObjectVector & graveyard = getMetaObjectGraveyard();
00430   MetaObjectVector::iterator itr = graveyard.begin();
00431 
00432   while (itr != graveyard.end()) {
00433     AbstractMetaObjectBase * obj = *itr;
00434     if (obj->getAssociatedLibraryPath() == library_path) {
00435       CONSOLE_BRIDGE_logDebug(
00436         "class_loader.class_loader_private: "
00437         "Purging factory metaobject from graveyard, class = %s, base_class = %s ptr = %p.."
00438         ".bound to ClassLoader %p (library path = %s)",
00439         obj->className().c_str(), obj->baseClassName().c_str(), obj,
00440         loader, loader ? loader->getLibraryPath().c_str() : "NULL");
00441 
00442       bool is_address_in_graveyard_same_as_global_factory_map =
00443         std::find(all_meta_objs.begin(), all_meta_objs.end(), *itr) != all_meta_objs.end();
00444       itr = graveyard.erase(itr);
00445       if (delete_objs) {
00446         if (is_address_in_graveyard_same_as_global_factory_map) {
00447           CONSOLE_BRIDGE_logDebug("%s",
00448             "class_loader.class_loader_private: "
00449             "Newly created metaobject factory in global factory map map has same address as "
00450             "one in graveyard -- metaobject has been purged from graveyard but not deleted.");
00451         } else {
00452           assert(hasANonPurePluginLibraryBeenOpened() == false);
00453           CONSOLE_BRIDGE_logDebug(
00454             "class_loader.class_loader_private: "
00455             "Also destroying metaobject %p (class = %s, base_class = %s, library_path = %s) "
00456             "in addition to purging it from graveyard.",
00457             obj, obj->className().c_str(), obj->baseClassName().c_str(),
00458             obj->getAssociatedLibraryPath().c_str());
00459           delete (obj);  // Note: This is the only place where metaobjects can be destroyed
00460         }
00461       }
00462     } else {
00463       itr++;
00464     }
00465   }
00466 }
00467 
00468 void loadLibrary(const std::string & library_path, ClassLoader * loader)
00469 /*****************************************************************************/
00470 {
00471   static boost::recursive_mutex loader_mutex;
00472   CONSOLE_BRIDGE_logDebug(
00473     "class_loader.class_loader_private: "
00474     "Attempting to load library %s on behalf of ClassLoader handle %p...\n",
00475     library_path.c_str(), loader);
00476   boost::recursive_mutex::scoped_lock loader_lock(loader_mutex);
00477 
00478   // If it's already open, just update existing metaobjects to have an additional owner.
00479   if (isLibraryLoadedByAnybody(library_path)) {
00480     boost::recursive_mutex::scoped_lock lock(getPluginBaseToFactoryMapMapMutex());
00481     CONSOLE_BRIDGE_logDebug("%s",
00482       "class_loader.class_loader_private: "
00483       "Library already in memory, but binding existing MetaObjects to loader if necesesary.\n");
00484     addClassLoaderOwnerForAllExistingMetaObjectsForLibrary(library_path, loader);
00485     return;
00486   }
00487 
00488   Poco::SharedLibrary * library_handle = NULL;
00489 
00490   {
00491     try {
00492       setCurrentlyActiveClassLoader(loader);
00493       setCurrentlyLoadingLibraryName(library_path);
00494       library_handle = new Poco::SharedLibrary(library_path);
00495     } catch (const Poco::LibraryLoadException & e) {
00496       setCurrentlyLoadingLibraryName("");
00497       setCurrentlyActiveClassLoader(NULL);
00498       throw(class_loader::LibraryLoadException(
00499               "Could not load library (Poco exception = " + std::string(e.message()) + ")"));
00500     } catch (const Poco::LibraryAlreadyLoadedException & e) {
00501       setCurrentlyLoadingLibraryName("");
00502       setCurrentlyActiveClassLoader(NULL);
00503       throw(class_loader::LibraryLoadException(
00504               "Library already loaded (Poco exception = " + std::string(e.message()) + ")"));
00505     } catch (const Poco::NotFoundException & e) {
00506       setCurrentlyLoadingLibraryName("");
00507       setCurrentlyActiveClassLoader(NULL);
00508       throw(class_loader::LibraryLoadException(
00509               "Library not found (Poco exception = " + std::string(e.message()) + ")"));
00510     }
00511 
00512     setCurrentlyLoadingLibraryName("");
00513     setCurrentlyActiveClassLoader(NULL);
00514   }
00515 
00516   assert(library_handle != NULL);
00517   CONSOLE_BRIDGE_logDebug(
00518     "class_loader.class_loader_private: "
00519     "Successfully loaded library %s into memory (Poco::SharedLibrary handle = %p).",
00520     library_path.c_str(), library_handle);
00521 
00522   // Graveyard scenario
00523   unsigned int num_lib_objs = allMetaObjectsForLibrary(library_path).size();
00524   if (0 == num_lib_objs) {
00525     CONSOLE_BRIDGE_logDebug(
00526       "class_loader.class_loader_private: "
00527       "Though the library %s was just loaded, it seems no factory metaobjects were registered. "
00528       "Checking factory graveyard for previously loaded metaobjects...",
00529       library_path.c_str());
00530     revivePreviouslyCreateMetaobjectsFromGraveyard(library_path, loader);
00531     // Note: The 'false' indicates we don't want to invoke delete on the metaobject
00532     purgeGraveyardOfMetaobjects(library_path, loader, false);
00533   } else {
00534     CONSOLE_BRIDGE_logDebug(
00535       "class_loader.class_loader_private: "
00536       "Library %s generated new factory metaobjects on load. "
00537       "Destroying graveyarded objects from previous loads...",
00538       library_path.c_str());
00539     purgeGraveyardOfMetaobjects(library_path, loader, true);
00540   }
00541 
00542   // Insert library into global loaded library vectory
00543   boost::recursive_mutex::scoped_lock llv_lock(getLoadedLibraryVectorMutex());
00544   LibraryVector & open_libraries = getLoadedLibraryVector();
00545   // Note: Poco::SharedLibrary automatically calls load() when library passed to constructor
00546   open_libraries.push_back(LibraryPair(library_path, library_handle));
00547 }
00548 
00549 void unloadLibrary(const std::string & library_path, ClassLoader * loader)
00550 /*****************************************************************************/
00551 {
00552   if (hasANonPurePluginLibraryBeenOpened()) {
00553     CONSOLE_BRIDGE_logDebug(
00554       "class_loader.class_loader_private: "
00555       "Cannot unload %s or ANY other library as a non-pure plugin library was opened. "
00556       "As class_loader has no idea which libraries class factories were exported from, "
00557       "it can safely close any library without potentially unlinking symbols that are still "
00558       "actively being used. "
00559       "You must refactor your plugin libraries to be made exclusively of plugins "
00560       "in order for this error to stop happening.",
00561       library_path.c_str());
00562   } else {
00563     CONSOLE_BRIDGE_logDebug(
00564       "class_loader.class_loader_private: "
00565       "Unloading library %s on behalf of ClassLoader %p...",
00566       library_path.c_str(), loader);
00567     boost::recursive_mutex::scoped_lock lock(getLoadedLibraryVectorMutex());
00568     LibraryVector & open_libraries = getLoadedLibraryVector();
00569     LibraryVector::iterator itr = findLoadedLibrary(library_path);
00570     if (itr != open_libraries.end()) {
00571       Poco::SharedLibrary * library = itr->second;
00572       std::string library_path = itr->first;
00573       try {
00574         destroyMetaObjectsForLibrary(library_path, loader);
00575 
00576         // Remove from loaded library list as well if no more factories associated with said library
00577         if (!areThereAnyExistingMetaObjectsForLibrary(library_path)) {
00578           CONSOLE_BRIDGE_logDebug(
00579             "class_loader.class_loader_private: "
00580             "There are no more MetaObjects left for %s so unloading library and "
00581             "removing from loaded library vector.\n",
00582             library_path.c_str());
00583           library->unload();
00584           assert(library->isLoaded() == false);
00585           delete (library);
00586           itr = open_libraries.erase(itr);
00587         } else {
00588           CONSOLE_BRIDGE_logDebug(
00589             "class_loader.class_loader_private: "
00590             "MetaObjects still remain in memory meaning other ClassLoaders are still using library"
00591             ", keeping library %s open.",
00592             library_path.c_str());
00593         }
00594         return;
00595       } catch (const Poco::RuntimeException & e) {
00596         delete (library);
00597         throw(class_loader::LibraryUnloadException(
00598                 "Could not unload library (Poco exception = " + std::string(e.message()) + ")"));
00599       }
00600     }
00601     throw(class_loader::LibraryUnloadException(
00602             "Attempt to unload library that class_loader is unaware of."));
00603   }
00604 }
00605 
00606 
00607 // Other
00608 /*****************************************************************************/
00609 /*****************************************************************************/
00610 /*****************************************************************************/
00611 
00612 void printDebugInfoToScreen()
00613 /*****************************************************************************/
00614 {
00615   printf("*******************************************************************************\n");
00616   printf("*****               class_loader_private DEBUG INFORMATION                   *****\n");
00617   printf("*******************************************************************************\n");
00618 
00619   printf("OPEN LIBRARIES IN MEMORY:\n");
00620   printf("--------------------------------------------------------------------------------\n");
00621   boost::recursive_mutex::scoped_lock lock(getLoadedLibraryVectorMutex());
00622   LibraryVector libs = getLoadedLibraryVector();
00623   for (unsigned int c = 0; c < libs.size(); c++) {
00624     printf(
00625       "Open library %i = %s (Poco SharedLibrary handle = %p)\n",
00626       c, (libs.at(c)).first.c_str(), (libs.at(c)).second);
00627   }
00628 
00629   printf("METAOBJECTS (i.e. FACTORIES) IN MEMORY:\n");
00630   printf("--------------------------------------------------------------------------------\n");
00631   MetaObjectVector meta_objs = allMetaObjects();
00632   for (unsigned int c = 0; c < meta_objs.size(); c++) {
00633     AbstractMetaObjectBase * obj = meta_objs.at(c);
00634     printf("Metaobject %i (ptr = %p):\n TypeId = %s\n Associated Library = %s\n",
00635       c,
00636       obj,
00637       (typeid(*obj).name()),
00638       obj->getAssociatedLibraryPath().c_str());
00639 
00640     ClassLoaderVector loaders = obj->getAssociatedClassLoaders();
00641     for (unsigned int i = 0; i < loaders.size(); i++) {
00642       printf(" Associated Loader %i = %p\n", i, loaders.at(i));
00643     }
00644     printf("--------------------------------------------------------------------------------\n");
00645   }
00646 
00647   printf("********************************** END DEBUG **********************************\n");
00648   printf("*******************************************************************************\n\n");
00649 }
00650 
00651 
00652 }  // namespace class_loader_private
00653 }  // namespace class_loader


class_loader
Author(s): Mirza Shah
autogenerated on Thu Jun 6 2019 20:43:27