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


class_loader
Author(s): Mirza Shah
autogenerated on Thu Dec 7 2017 04:48:01