openModeller
Version 1.4.0
|
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 }