LibraryLoader.cpp

Go to the documentation of this file.
00001 /****************** <VPR heading BEGIN do not edit this line> *****************
00002  *
00003  * VR Juggler Portable Runtime
00004  *
00005  * Original Authors:
00006  *   Allen Bierbaum, Patrick Hartling, Kevin Meinert, Carolina Cruz-Neira
00007  *
00008  * -----------------------------------------------------------------
00009  * File:          $RCSfile$
00010  * Date modified: $Date: 2005-06-15 09:11:46 -0500 (Wed, 15 Jun 2005) $
00011  * Version:       $Revision: 17686 $
00012  * -----------------------------------------------------------------
00013  *
00014  ****************** <VPR heading END do not edit this line> ******************/
00015 
00016 /*************** <auto-copyright.pl BEGIN do not edit this line> **************
00017  *
00018  * VR Juggler is (C) Copyright 1998-2005 by Iowa State University
00019  *
00020  * Original Authors:
00021  *   Allen Bierbaum, Christopher Just,
00022  *   Patrick Hartling, Kevin Meinert,
00023  *   Carolina Cruz-Neira, Albert Baker
00024  *
00025  * This library is free software; you can redistribute it and/or
00026  * modify it under the terms of the GNU Library General Public
00027  * License as published by the Free Software Foundation; either
00028  * version 2 of the License, or (at your option) any later version.
00029  *
00030  * This library is distributed in the hope that it will be useful,
00031  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00032  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00033  * Library General Public License for more details.
00034  *
00035  * You should have received a copy of the GNU Library General Public
00036  * License along with this library; if not, write to the
00037  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
00038  * Boston, MA 02111-1307, USA.
00039  *
00040  *************** <auto-copyright.pl END do not edit this line> ***************/
00041 
00042 #include <vpr/vprConfig.h>
00043 
00044 #include <iomanip>
00045 #include <algorithm>
00046 #include <boost/filesystem/exception.hpp>
00047 #include <boost/filesystem/operations.hpp>
00048 
00049 #include <vpr/Util/Debug.h>
00050 #include <vpr/Util/Assert.h>
00051 #include <vpr/DynLoad/Library.h>
00052 
00053 #include <vpr/DynLoad/LibraryLoader.h>
00054 
00055 
00056 namespace fs = boost::filesystem;
00057 
00058 namespace vpr
00059 {
00060 
00061 #ifdef VPR_DEBUG
00062 static const std::string DSO_NAME_EXT("_d");
00063 #else
00064 static const std::string DSO_NAME_EXT("");
00065 #endif
00066 
00067 #if defined(VPR_OS_Windows)
00068 static const std::string PATH_SEP("\\");
00069 static const std::string DSO_FILE_EXT(".dll");
00070 #else
00071 static const std::string PATH_SEP("/");
00072 
00073 #  if defined(VPR_OS_Darwin)
00074 static const std::string DSO_FILE_EXT(".dylib");
00075 #  else
00076 static const std::string DSO_FILE_EXT(".so");
00077 #  endif
00078 #endif
00079 
00080 vpr::LibraryPtr LibraryLoader::findDSO(const std::string& dsoBaseName,
00081                                        const std::vector<std::string>& searchPath)
00082 {
00083    std::vector<fs::path> fs_path;
00084    makeBoostFsVector(searchPath, fs_path);
00085    return findDSO(dsoBaseName, fs_path);
00086 }
00087 
00088 vpr::LibraryPtr LibraryLoader::findDSO(const std::string& dsoBaseName,
00089                                        const std::vector<fs::path>& searchPath)
00090 {
00091    vpr::LibraryPtr dso;
00092 
00093    const std::string dso_name = makeFullDSOName(dsoBaseName);
00094 
00095    for ( std::vector<fs::path>::const_iterator i = searchPath.begin();
00096          i != searchPath.end();
00097          ++i )
00098    {
00099       try
00100       {
00101          fs::path temp_path = *i / dso_name;
00102 
00103          vprDEBUG(vprDBG_ALL, vprDBG_VERB_LVL)
00104             << "[vpr::LibraryLoader::findDSO()] Looking for '"
00105             << temp_path.native_file_string() << "'\n" << vprDEBUG_FLUSH;
00106 
00107          if ( fs::exists(temp_path) )
00108          {
00109             dso = vpr::LibraryPtr(new vpr::Library(temp_path.native_file_string()));
00110             break;
00111          }
00112       }
00113       catch(fs::filesystem_error& fsEx)
00114       {
00115          vprDEBUG(vprDBG_ERROR, vprDBG_CRITICAL_LVL)
00116             << clrOutNORM(clrRED, "ERROR:")
00117             << " File system exception caught: " << fsEx.what()
00118             << std::endl << vprDEBUG_FLUSH;
00119       }
00120    }
00121 
00122    return dso;
00123 }
00124 
00125 vpr::ReturnStatus LibraryLoader::findDSOAndCallEntryPoint(const std::string& dsoBaseName,
00126                                                           const std::vector<std::string>& searchPath,
00127                                                           const std::string& funcName,
00128                                                           boost::function1<bool, void*> callback,
00129                                                           vpr::LibraryPtr& dso)
00130 {
00131    std::vector<fs::path> fs_path;
00132    makeBoostFsVector(searchPath, fs_path);
00133    return findDSOAndCallEntryPoint(dsoBaseName, fs_path, funcName, callback,
00134                                    dso);
00135 }
00136 
00137 vpr::ReturnStatus LibraryLoader::findDSOAndCallEntryPoint(const std::string& dsoBaseName,
00138                                                           const std::vector<fs::path>& searchPath,
00139                                                           const std::string& funcName,
00140                                                           boost::function1<bool, void*> callback,
00141                                                           vpr::LibraryPtr& dso)
00142 {
00143    vpr::ReturnStatus status;
00144    bool load_attempted(false);
00145 
00146    dso = findDSO(dsoBaseName, searchPath);
00147 
00148    if ( dso.get() != NULL )
00149    {
00150       try
00151       {
00152          status = callEntryPoint(dso, funcName, callback);
00153          load_attempted = true;
00154       }
00155       catch(fs::filesystem_error& fsEx)
00156       {
00157          vprDEBUG(vprDBG_ERROR, vprDBG_CRITICAL_LVL)
00158             << clrOutNORM(clrRED, "ERROR:")
00159             << " File system exception caught: " << fsEx.what()
00160             << std::endl << vprDEBUG_FLUSH;
00161       }
00162    }
00163 
00164    // If no load was attempted, that means that the DSO does not exist in
00165    // searchPath.  We'll give it one last shot here using whatever features
00166    // the run-time loader has for searching on its own.
00167    if ( ! load_attempted )
00168    {
00169       const std::string dso_name = makeFullDSOName(dsoBaseName);
00170 
00171       vprDEBUG(vprDBG_ALL, vprDBG_STATE_LVL)
00172          << "[vpr::LibraryLoader::findDSOAndLookup()] Falling back on run-time loader search for '"
00173          << dso_name << "'\n" << vprDEBUG_FLUSH;
00174       vpr::LibraryPtr temp_dso = vpr::LibraryPtr(new vpr::Library(dso_name));
00175       status = callEntryPoint(temp_dso, funcName, callback);
00176 
00177       // If callEntryPoint succeeded, then store the vpr::LibraryPtr object
00178       // in the return storage.  Otherwise, we let it go out of scope and get
00179       // deleted.
00180       if ( ! status.failure() )
00181       {
00182          dso = temp_dso;
00183       }
00184    }
00185 
00186    return status;
00187 }
00188 
00189 vpr::ReturnStatus LibraryLoader::callEntryPoint(vpr::LibraryPtr dso,
00190                                                 const std::string& funcName,
00191                                                 boost::function1<bool, void*> callback)
00192 {
00193    vprASSERT(dso.get() != NULL && "Invalid vpr::LibraryPtr object");
00194 
00195    vpr::ReturnStatus status;
00196    const int lib_name_width(50);
00197    bool had_to_load(false);
00198 
00199    // Load the DSO if it has not already been loaded.
00200    if ( ! dso->isLoaded() )
00201    {
00202       had_to_load = true;
00203       vprDEBUG(vprDBG_ALL, vprDBG_CONFIG_STATUS_LVL)
00204          << "Loading library: " << std::setiosflags(std::ios::right)
00205          << std::setfill(' ') << std::setw(lib_name_width) << dso->getName()
00206          << std::resetiosflags(std::ios::right) << "     " << vprDEBUG_FLUSH;
00207 
00208       dso->load();
00209    }
00210 
00211    if ( dso->isLoaded() )
00212    {
00213       // Look up the named function in the DSO and store it in the pointer
00214       // called "entry_point".
00215       void* entry_point = dso->findSymbol(funcName);
00216 
00217       if ( NULL != entry_point )
00218       {
00219          // Only print this closing thing if we had to load the DSO ourselves.
00220          if ( had_to_load )
00221          {
00222             vprDEBUG_CONT(vprDBG_ALL, vprDBG_CONFIG_STATUS_LVL)
00223                << "[ " << clrSetNORM(clrGREEN) << "OK" << clrRESET << " ]\n"
00224                << vprDEBUG_FLUSH;
00225          }
00226 
00227          vprDEBUG(vprDBG_ALL, vprDBG_STATE_LVL)
00228             << "Got pointer to DSO entry point function.\n" << vprDEBUG_FLUSH;
00229 
00230          // Use the caller-provided callback function for actual invocation
00231          // of entry_point.  It is up to this function to cast creator to the
00232          // desired type and do the cool stuff with it.
00233          if ( ! callback(entry_point) )
00234          {
00235             status.setCode(vpr::ReturnStatus::Fail);
00236          }
00237       }
00238       else
00239       {
00240          // Only print this closing thing if we had to load the DSO ourselves.
00241          if ( had_to_load )
00242          {
00243             vprDEBUG_CONT(vprDBG_ALL, vprDBG_CONFIG_STATUS_LVL)
00244                << "[ " << clrSetNORM(clrRED) << "FAILED lookup" << clrRESET
00245                << " ]\n" << vprDEBUG_FLUSH;
00246          }
00247 
00248          vprDEBUG(vprDBG_ALL, vprDBG_WARNING_LVL)
00249             << clrOutNORM(clrYELLOW, "WARNING")
00250             << ": Failed to look up entry point function '" << funcName
00251             << "' in DSO '" << dso->getName() << "'\n"
00252             << vprDEBUG_FLUSH;
00253          status.setCode(vpr::ReturnStatus::Fail);
00254       }
00255    }
00256    else
00257    {
00258       status.setCode(vpr::ReturnStatus::Fail);
00259 
00260       // Only print this closing thing if we had to load the DSO ourselves.
00261       if ( had_to_load )
00262       {
00263          vprDEBUG_CONT(vprDBG_ALL, vprDBG_CONFIG_LVL)
00264             << "[ " << clrSetNORM(clrRED) << "FAILED" << clrRESET << " ]\n"
00265             << vprDEBUG_FLUSH;
00266       }
00267    }
00268 
00269    return status;
00270 }
00271 
00272 std::string LibraryLoader::makeFullDSOName(const std::string& dsoBaseName)
00273 {
00274    return dsoBaseName + DSO_NAME_EXT + DSO_FILE_EXT;
00275 }
00276 
00277 void LibraryLoader::makeBoostFsVector(const std::vector<std::string>& strVec,
00278                                       std::vector<fs::path>& boostFsVec)
00279 {
00280    boostFsVec.resize(strVec.size());
00281 
00282    // Convert the vector of std::string objects to a vector of
00283    // boost::filesystem::path objects.
00284    for ( std::vector<std::string>::size_type i = 0; i < strVec.size(); ++i )
00285    {
00286       try
00287       {
00288          vprDEBUG(vprDBG_ALL, vprDBG_HVERB_LVL)
00289             << "[vpr::LibraryLoader::makeBoostFsVector()] Converting std::string '"
00290             << strVec[i] << "' to a boost::filesystem::path object.\n"
00291             << vprDEBUG_FLUSH;
00292 
00293          // Use a Boost FS path object here so that we can indicate that
00294          // native path names are allowed.
00295          boostFsVec[i] = fs::path(strVec[i], fs::native);
00296       }
00297       catch(fs::filesystem_error& fsEx)
00298       {
00299          vprDEBUG(vprDBG_ERROR, vprDBG_CRITICAL_LVL)
00300             << clrOutNORM(clrRED, "ERROR:")
00301             << " File system exception caught while converting\n"
00302             << vprDEBUG_FLUSH;
00303          vprDEBUG_NEXT(vprDBG_ERROR, vprDBG_CRITICAL_LVL)
00304             << "'" << strVec[i] << "'\n" << vprDEBUG_FLUSH;
00305          vprDEBUG_NEXT(vprDBG_ERROR, vprDBG_CRITICAL_LVL)
00306             << "to a Boost.Filesystem path.\n" << vprDEBUG_FLUSH;
00307          vprDEBUG_NEXT(vprDBG_ERROR, vprDBG_CRITICAL_LVL)
00308             << fsEx.what() << std::endl << vprDEBUG_FLUSH;
00309       }
00310    }
00311 }
00312 
00313 }

Generated on Thu Jan 4 10:52:09 2007 for VR Juggler Portable Runtime by  doxygen 1.5.1