36 #include <sys/types.h>
59 static const unsigned long long BYTES_PER_MEG = 1048576ULL;
63 static const unsigned long long MAX_CACHE_SIZE_IN_MEGABYTES = (1ULL << 44);
66 BESCache::check_ctor_params()
68 if( _cache_dir.empty() )
70 string err =
"The cache directory was not specified, must be non-empty";
75 int statret = stat( _cache_dir.c_str(), &buf ) ;
76 if( statret != 0 || ! S_ISDIR(buf.st_mode) )
78 string err =
"The cache directory " + _cache_dir +
" does not exist" ;
84 string err =
"The cache file prefix was not specified, must be non-empty" ;
88 if( _cache_size_in_megs <= 0 )
90 string err =
"The cache size was not specified, must be non-zero" ;
98 if( _cache_size_in_megs > MAX_CACHE_SIZE_IN_MEGABYTES )
100 _cache_size_in_megs = MAX_CACHE_SIZE_IN_MEGABYTES ;
101 std::ostringstream msg;
102 msg <<
"The specified cache size was larger than the max cache size of: "
103 << MAX_CACHE_SIZE_IN_MEGABYTES;
107 BESDEBUG(
"bes",
"BES Cache: directory " << _cache_dir
108 <<
", prefix " << _prefix
109 <<
", max size " << _cache_size_in_megs << endl ) ;
121 BESCache::BESCache(
const string &cache_dir,
122 const string &prefix,
123 unsigned long long sizeInMegs )
124 : _cache_dir( cache_dir ),
126 _cache_size_in_megs( sizeInMegs ),
147 const string &cache_dir_key,
148 const string &prefix_key,
149 const string &size_key )
150 : _cache_size_in_megs( 0 ),
154 keys.
get_value( cache_dir_key, _cache_dir, found ) ;
157 string err =
"The cache directory key " + cache_dir_key
158 +
" was not found in the BES configuration file" ;
163 keys.
get_value( prefix_key, _prefix, found ) ;
166 string err =
"The prefix key " + prefix_key
167 +
" was not found in the BES configuration file" ;
172 string cache_size_str ;
173 keys.
get_value( size_key, cache_size_str, found ) ;
176 string err =
"The size key " + size_key
177 +
" was not found in the BES configuration file" ;
181 std::istringstream is( cache_size_str ) ;
182 is >> _cache_size_in_megs ;
197 if( num_tries > MAX_LOCK_TRIES )
198 num_tries = MAX_LOCK_TRIES ;
199 if( retry > MAX_LOCK_RETRY_MS )
200 retry = MAX_LOCK_RETRY_MS ;
202 bool got_lock = true ;
205 string lock_file = _cache_dir +
"/lock" ;
206 unsigned int tries = 0 ;
207 _lock_fd = open( lock_file.c_str(),
209 S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH ) ;
210 while( _lock_fd < 0 && got_lock )
213 if( tries > num_tries )
221 _lock_fd = open( lock_file.c_str(),
223 S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH ) ;
232 string err =
"The cache dir " + _cache_dir +
" is already locked" ;
250 bool unlocked = true ;
253 string lock_file = _cache_dir +
"/lock" ;
255 (void)unlink( lock_file.c_str() ) ;
280 string tmp_target = src ;
284 if( tmp_target.at(0) ==
'/' )
286 tmp_target = src.substr( 1, tmp_target.length() - 1 ) ;
288 string::size_type slash = 0 ;
289 while( ( slash = tmp_target.find(
'/' ) ) != string::npos )
291 tmp_target.replace( slash, 1, 1, BES_CACHE_CHAR ) ;
293 string::size_type last_dot = tmp_target.rfind(
'.' ) ;
294 if( last_dot != string::npos )
296 tmp_target = tmp_target.substr( 0, last_dot ) ;
299 target = _cache_dir +
"/" + _prefix + BES_CACHE_CHAR + tmp_target ;
303 int statret = stat( target.c_str(), &buf ) ;
337 BESDEBUG(
"bes",
"cache size = " << size << endl ) ;
338 BESDEBUG(
"bes",
"avg size = " << avg_size << endl ) ;
339 BESDEBUG(
"bes",
"num files in cache = "
340 << num_files_in_cache << endl ) ;
343 BESDEBUG(
"bes", endl <<
"BEFORE" << endl ) ;
344 CacheFilesByAgeMap::iterator ti = contents.begin() ;
345 CacheFilesByAgeMap::iterator te = contents.end() ;
346 for( ; ti != te; ti++ )
348 BESDEBUG(
"bes", (*ti).first <<
": " << (*ti).second.name <<
": size " << (*ti).second.size << endl ) ;
359 unsigned long long max_size_in_bytes = _cache_size_in_megs * BYTES_PER_MEG ;
360 while( (size+avg_size) > max_size_in_bytes )
364 CacheFilesByAgeMap::iterator i = contents.begin() ;
367 if( i == contents.end() )
373 BESDEBUG(
"bes",
"BESCache::purge - removing "
374 << (*i).second.name << endl ) ;
377 if( unlink( (*i).second.name.c_str() ) != 0 )
379 char *s_err = strerror( errno ) ;
380 string err =
"Unable to remove the file "
382 +
" from the cache: " ;
385 err.append( s_err ) ;
389 err.append(
"Unknown error" ) ;
394 size -= (*i).second.size ;
395 contents.erase( i ) ;
400 BESDEBUG(
"bes", endl <<
"AFTER" << endl ) ;
401 CacheFilesByAgeMap::iterator ti = contents.begin() ;
402 CacheFilesByAgeMap::iterator te = contents.end() ;
403 for( ; ti != te; ti++ )
405 BESDEBUG(
"bes", (*ti).first <<
": " << (*ti).second.name <<
": size " << (*ti).second.size << endl ) ;
414 DIR_Wrapper(
const std::string& dir_name)
416 _dip = opendir(dir_name.c_str());
424 DIR*
get()
const {
return _dip; }
447 time_t curr_time = time( NULL ) ;
450 DIR_Wrapper dip = DIR_Wrapper( _cache_dir );
453 string err =
"Unable to open cache directory " + _cache_dir ;
462 while( ( dit = readdir( dip.get() ) ) != NULL )
464 string dirEntry = dit->d_name ;
465 if( dirEntry.compare( 0, _prefix.length(), _prefix ) == 0)
469 string fullPath = _cache_dir +
"/" + dirEntry ;
470 int statret = stat( fullPath.c_str(), &buf ) ;
476 time_t file_time = buf.st_atime ;
482 double time_diff = difftime( curr_time, file_time ) ;
484 entry.
name = fullPath ;
485 entry.
size = buf.st_size ;
486 cd_info.
_contents.insert( pair<double, cache_entry>( time_diff, entry ) );
507 << (
void *)
this <<
")" << endl ;