openModeller  Version 1.4.0
CacheManager.cpp
Go to the documentation of this file.
00001 
00027 #include <openmodeller/CacheManager.hh>
00028 #include <openmodeller/Log.hh>
00029 #include <openmodeller/Exceptions.hh>
00030 #include <openmodeller/Settings.hh>
00031 #include <openmodeller/os_specific.hh>
00032 extern "C" {
00033 #include <openmodeller/ext/md5/md5.h>
00034 }
00035 
00036 #include <stdlib.h>
00037 #include <string.h>
00038 #include <iostream>
00039 #include <sstream>
00040 #include <stdio.h>
00041 
00042 using namespace std;
00043 
00044 /**************************************************************************
00045  *
00046  * Implementation of CacheManager class
00047  *
00048  *************************************************************************/
00049 
00050 /*******************/
00051 /*** constructor ***/
00052 
00053 CacheManager::CacheManager() :
00054   _cacheDir()
00055 {
00056 }
00057 
00058 /******************/
00059 /*** destructor ***/
00060 
00061 CacheManager::~CacheManager()
00062 {
00063 }
00064 
00065 /**************************/
00066 /*** Singleton accessor ***/
00067 CacheManager&
00068 CacheManager::_getInstance()
00069 {
00070   static CacheManager theInstance;
00071   return theInstance;
00072 }
00073 
00074 /******************/
00075 /*** initialize ***/
00076 void
00077 CacheManager::initialize( const std::string dir )
00078 {
00079   CacheManager& cm = _getInstance();
00080 
00081   bool use_default = true;
00082 
00083   if ( ! dir.empty() ) {
00084 
00085     Log::instance()->debug( "Using specified directory as cache: %s\n", dir.c_str() );
00086     cm._cacheDir = dir;
00087     use_default = false;
00088   }
00089   else {
00090 
00091     if ( Settings::count( "CACHE_DIRECTORY" ) == 1 ) {
00092 
00093       cm._cacheDir = Settings::get( "CACHE_DIRECTORY" );
00094       Log::instance()->debug( "Using cache directory from configuration file: %s\n", cm._cacheDir.c_str() );
00095       use_default = false;
00096     }
00097     else {
00098 
00099       char *env = getenv( "OM_CACHE_PATH" );
00100 
00101       if ( env != 0 ) {
00102 
00103         string om_cache_path = (char const *)env;
00104 
00105         if ( ! om_cache_path.empty() ) {
00106 
00107           Log::instance()->debug( "Using cache directory defined in OM_CACHE_PATH: %s\n", om_cache_path.c_str() );
00108           cm._cacheDir = om_cache_path;
00109           use_default = false;
00110         }
00111       }
00112     }
00113   }
00114 
00115   if ( use_default ) {
00116 
00117     Log::instance()->debug( "Using default cache directory under the current path\n" );
00118     cm._cacheDir = getWorkingPath();
00119     cm._cacheDir.append("/cache");
00120   }
00121 
00122   if ( ! pathExists( cm._cacheDir ) ) {
00123 
00124     createPath( cm._cacheDir );
00125   }
00126 }
00127 
00128 /*****************/
00129 /*** is cached ***/
00130 void
00131 CacheManager::_ensureInitialized()
00132 {
00133   CacheManager& cm = _getInstance();
00134 
00135   if ( cm._cacheDir.empty() ) {
00136 
00137     cm.initialize();
00138   }
00139 }
00140 
00141 /*****************/
00142 /*** is cached ***/
00143 bool
00144 CacheManager::isCached( const std::string id, const std::string subdir )
00145 {
00146   _ensureInitialized();
00147 
00148   CacheManager& cm = _getInstance();
00149 
00150   std::string path = cm._cacheDir;
00151 
00152   if ( ! subdir.empty() ) {
00153 
00154     path.append("/");
00155     path.append(subdir);
00156   }
00157 
00158   createPath( path );
00159 
00160   path.append("/");
00161   path.append(id);
00162 
00163   ifstream ifile(path.c_str(), std::ios::in);
00164 
00165   if ( ifile ) {
00166 
00167     return true;
00168   }
00169 
00170   return false;
00171 }
00172 
00173 /*********************/
00174 /*** is cached md5 ***/
00175 bool
00176 CacheManager::isCachedMd5( const std::string id, const std::string subdir )
00177 {
00178   return isCached( getContentIdMd5( id ), subdir );
00179 }
00180 
00181 /*************/
00182 /*** cache ***/
00183 void
00184 CacheManager::cache( const std::string id, const std::ostringstream& content, const std::string subdir )
00185 {
00186   _ensureInitialized();
00187 
00188   CacheManager& cm = _getInstance();
00189 
00190   std::string path = cm._cacheDir;
00191 
00192   if ( ! subdir.empty() ) {
00193 
00194     path.append("/");
00195     path.append(subdir);
00196   }
00197 
00198   createPath( path );
00199 
00200   path.append("/");
00201   path.append(id);
00202 
00203   ofstream ofile( path.c_str() );
00204 
00205   if ( ofile ) {
00206 
00207     ofile << content.str();
00208   }
00209   else {
00210 
00211     Log::instance()->error( "Could not cache content for %s\n", id.c_str() );
00212     throw FileIOException( "Could not cache content\n", id );
00213   }
00214 }
00215 
00216 /*****************/
00217 /*** cache md5 ***/
00218 void
00219 CacheManager::cacheMd5( const std::string id, const std::ostringstream& content, const std::string subdir )
00220 {
00221   cache( getContentIdMd5( id ), content, subdir );
00222 }
00223 
00224 /****************************/
00225 /*** get Content Location ***/
00226 std::string
00227 CacheManager::getContentLocation( const std::string id, const std::string subdir )
00228 {
00229   _ensureInitialized();
00230 
00231   CacheManager& cm = _getInstance();
00232 
00233   std::string path = cm._cacheDir;
00234 
00235   if ( ! subdir.empty() ) {
00236 
00237     path.append("/");
00238     path.append(subdir);
00239   }
00240 
00241   path.append("/");
00242   path.append(id);
00243 
00244   return path;
00245 }
00246 
00247 /****************************/
00248 /*** get Content Location ***/
00249 std::string
00250 CacheManager::getContentLocationMd5( const std::string id, const std::string subdir )
00251 {
00252   return getContentLocation( getContentIdMd5( id ), subdir );
00253 }
00254 
00255 /*************************/
00256 /*** get Friendly Hash ***/
00257 std::string
00258 CacheManager::getContentIdMd5( const std::string id )
00259 {
00260   const size_t MYSIZE = 16;
00261 
00262   unsigned char digest[MYSIZE];
00263 
00264   MD5_CTX md5;
00265   MD5_Init( &md5 );
00266   MD5_Update( &md5, const_cast<char *>( id.c_str() ), id.size() );
00267   MD5_Final( digest, &md5 );
00268 
00269   char buffer[(MYSIZE*2)+1];
00270 
00271   for (unsigned int i = 0; i < MYSIZE; ++i ) {
00272 
00273     sprintf(&buffer[i*2], "%02x", (unsigned int)digest[i]);
00274   }
00275 
00276   std::string md5_id( buffer );
00277 
00278   return md5_id;
00279 }
00280 
00281 
00282 /*******************/
00283 /*** erase Cache ***/
00284 int 
00285 CacheManager::eraseCache( const std::string id, const std::string subdir )
00286 {
00287     std::string path = getContentLocation( id, subdir );
00288 
00289     return remove(path.c_str());
00290 }
00291 
00292 /***********************/
00293 /*** erase Cache md5 ***/
00294 int 
00295 CacheManager::eraseCacheMd5( const std::string id, const std::string subdir )
00296 {
00297   return eraseCache( getContentIdMd5( id ), subdir );
00298 }